--- a/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65
ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67
+5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
--- a/.hgtags-top-repo Fri Jun 12 16:36:33 2015 -0400
+++ b/.hgtags-top-repo Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66
f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
+70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
--- a/corba/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/corba/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
44ee68f7dbacab24a45115fd6a8ccdc7eb6e8f0b jdk9-b66
4418697e56f1f43597f55c7cb6573549c6117868 jdk9-b67
+8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 <tt>Bounds</tt>.
+ * For more information on Helper files, see
+ * <a href="doc-files/generatedfiles.html#helper">
+ * "Generated Files: Helper Files"</a>.<P>
+ */
+
+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 ());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
+ * <tt>ORBPackage/InvalidName</tt>.
+ * For more information on Helper files, see
+ * <a href="doc-files/generatedfiles.html#helper">
+ * "Generated Files: Helper Files"</a>.<P>
+ */
+
+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 ());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
+ * <tt>TypeCodePackage/BadKind</tt>.
+ * For more information on Helper files, see
+ * <a href="doc-files/generatedfiles.html#helper">
+ * "Generated Files: Helper Files"</a>.<P>
+ */
+
+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 ());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
+ * <tt>TypeCodePackage/Bounds</tt>.
+ * For more information on Helper files, see
+ * <a href="doc-files/generatedfiles.html#helper">
+ * "Generated Files: Helper Files"</a>.<P>
+ */
+
+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 ());
+ }
+
+}
--- a/hotspot/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -470,3 +470,4 @@
e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66
d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
+11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
--- a/hotspot/make/linux/makefiles/dtrace.make Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/make/linux/makefiles/dtrace.make Fri Jun 12 16:40:05 2015 -0400
@@ -31,8 +31,8 @@
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
--- a/hotspot/make/test/JtregNative.gmk Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/make/test/JtregNative.gmk Fri Jun 12 16:40:05 2015 -0400
@@ -44,6 +44,7 @@
$(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
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Jun 12 16:40:05 2015 -0400
@@ -3372,6 +3372,25 @@
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 @@
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 @@
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 @@
format %{ %}
interface(CONST_INTER);
%}
-
// Integer Immediate: the value 255
operand immI_255() %{
predicate( n->get_int() == 255 );
@@ -3550,6 +3509,46 @@
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 @@
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 @@
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);
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Fri Jun 12 16:40:05 2015 -0400
@@ -5431,18 +5431,18 @@
%}
// 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 @@
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);
%}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Fri Jun 12 16:40:05 2015 -0400
@@ -4753,17 +4753,17 @@
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 @@
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);
%}
--- a/hotspot/src/os/aix/vm/os_aix.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1267,10 +1267,6 @@
// 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) {
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1131,10 +1131,6 @@
// 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) {
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1478,10 +1478,6 @@
// 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) {
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1520,10 +1520,6 @@
// 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) {
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -997,7 +997,16 @@
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 @@
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);
--- a/hotspot/src/share/vm/ci/ciCallSite.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciCallSite.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -50,25 +50,6 @@
}
// ------------------------------------------------------------------
-// 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
//
// Print debugging information about the CallSite.
--- a/hotspot/src/share/vm/ci/ciCallSite.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciCallSite.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -43,7 +43,6 @@
// Return the target MethodHandle of this CallSite.
ciMethodHandle* get_target() const;
- ciKlass* get_context();
void print();
};
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -709,24 +709,23 @@
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();
}
--- a/hotspot/src/share/vm/ci/ciField.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciField.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -352,11 +352,11 @@
}
}
+ 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()) {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -453,8 +453,12 @@
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();
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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 @@
||
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 @@
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 @@
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;
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -2967,47 +2967,42 @@
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) {
- assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-
- oop dep_oop = call_site->obj_field_volatile(_context_offset);
- return dep_oop;
-}
-
-void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) {
+oop java_lang_invoke_CallSite::context(oop call_site) {
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
- call_site->obj_field_put_volatile(_context_offset, context);
-}
-
-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<HeapWord>(_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);
+
+ oop dep_oop = call_site->obj_field(_context_offset);
+ return dep_oop;
+}
+
+// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext
+
+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 @@
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
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -1170,8 +1170,6 @@
private:
static int _target_offset;
static int _context_offset;
- static int _default_context_offset;
-
static void compute_offsets();
@@ -1181,11 +1179,7 @@
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 @@
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 @@
#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
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -49,6 +49,10 @@
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());
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -159,6 +159,7 @@
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 ) \
--- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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.
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -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;") \
--- a/hotspot/src/share/vm/code/codeCache.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/code/codeCache.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1047,40 +1047,6 @@
}
}
-// 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) {
--- a/hotspot/src/share/vm/code/codeCache.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/code/codeCache.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -224,7 +224,6 @@
// 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);
--- a/hotspot/src/share/vm/code/dependencies.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/code/dependencies.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -117,9 +117,7 @@
}
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 @@
}
}
} 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 @@
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 @@
return find_finalizable_subclass(search_at);
}
-Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
+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");
- assert(!oopDesc::is_null(method_handle), "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* 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;
--- a/hotspot/src/share/vm/code/dependencies.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/code/dependencies.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -173,7 +173,7 @@
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 @@
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 @@
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()); }
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -565,13 +565,18 @@
// 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 @@
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);
+ }
}
}
}
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -254,9 +254,9 @@
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,
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -43,7 +43,7 @@
}
// 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 @@
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
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -176,7 +176,7 @@
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
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1183,7 +1183,7 @@
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 @@
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;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -324,7 +324,8 @@
// 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
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -168,7 +168,7 @@
// +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");
--- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -130,7 +130,7 @@
// 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;
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -272,7 +272,7 @@
// 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
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -2053,7 +2053,7 @@
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 @@
// 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
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -290,7 +290,7 @@
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();
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -960,7 +960,7 @@
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;
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -244,7 +244,7 @@
// 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;
--- a/hotspot/src/share/vm/gc/shared/gcCause.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -103,6 +103,9 @@
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";
--- a/hotspot/src/share/vm/gc/shared/gcCause.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -74,12 +74,15 @@
_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
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -304,9 +304,16 @@
}
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,
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -47,7 +47,6 @@
/* 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 @@
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 @@
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::loop() {
int previous_sequence_number = 0;
Monitor* gang_monitor = gang()->monitor();
- for ( ; /* !terminate() */; ) {
+ for ( ; ; ) {
WorkData data;
int part; // Initialized below.
{
@@ -272,8 +240,6 @@
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 @@
}
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 @@
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) {
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -103,16 +103,15 @@
// An abstract class representing a gang of workers.
// You subclass this to supply an implementation of run_task().
class AbstractWorkGang: public CHeapObj<mtInternal> {
- // 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 @@
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 @@
virtual uint active_workers() const {
return _total_workers;
}
- bool terminate() const {
- return _terminate;
- }
GangWorker** gang_workers() const {
return _gang_workers;
}
@@ -205,21 +199,16 @@
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; }
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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) {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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 @@
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_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 @@
}
#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::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 @@
// 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<Method*>* 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<Method*>* 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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() ? "<NULL>" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "<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::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::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 @@
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 @@
}
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 @@
// 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 @@
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:
// <init>
@@ -932,11 +968,13 @@
// 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 <init>, that it is found in same klass as static type
@@ -951,10 +989,11 @@
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 @@
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 @@
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() ? "<NULL>" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "<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 @@
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 @@
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() ? "<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 @@
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 @@
resolved_method->name(),
resolved_method->signature()),
(current_klass.is_null() ? "<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 @@
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() ? "<NULL>" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "<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 @@
}
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() ? "<NULL>" : recv_klass->internal_name()),
- (resolved_klass.is_null() ? "<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 @@
}
// 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 @@
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 @@
}
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() ? "<NULL>" : recv_klass->internal_name()),
- (resolved_klass.is_null() ? "<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 @@
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_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::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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
- //resolve_pool(<resolved_klass>, 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 @@
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() ? "<NULL>" : klass->internal_name()),
+ (resolved_klass.is_null() ? "<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 ");
}
- tty->print_cr("Call %s@%d %s", kindstr, _call_index,
- _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string());
+ if (method->is_overpass()) {
+ tty->print("overpass ");
+ }
}
-
-#endif
+#endif // PRODUCT
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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 @@
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 @@
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 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_klass (KlassHandle& result, 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_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, 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 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 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 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 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 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 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);
- 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);
-
+ // 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);
-
- // 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_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);
- // 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);
+ 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);
- // 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);
+ // 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);
+
+ 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
--- a/hotspot/src/share/vm/memory/metaspace.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -614,8 +614,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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.
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -622,14 +622,6 @@
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 @@
// 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 @@
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 @@
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 @@
#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();
+
+ if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
+ set_has_unloaded_dependent(true);
}
-#ifdef ASSERT
- tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
- nm->print();
-#endif // ASSERT
- ShouldNotReachHere();
}
-
#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
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -1290,6 +1290,15 @@
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
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1136,7 +1136,7 @@
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.
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -599,10 +599,14 @@
}
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");
--- a/hotspot/src/share/vm/opto/callnode.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1946,7 +1946,7 @@
}
}
}
- 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;
--- a/hotspot/src/share/vm/opto/graphKit.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1457,18 +1457,18 @@
// 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()) {
--- a/hotspot/src/share/vm/opto/graphKit.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/graphKit.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -512,21 +512,24 @@
// 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.
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -2631,7 +2631,9 @@
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 @@
}
// 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.
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -437,7 +437,13 @@
}
}
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);
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1582,13 +1582,36 @@
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);
+ }
}
}
}
--- a/hotspot/src/share/vm/opto/loopopts.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -718,7 +718,7 @@
}
// 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 @@
// 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 )
--- a/hotspot/src/share/vm/opto/matcher.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/matcher.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -844,7 +844,7 @@
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));
--- a/hotspot/src/share/vm/opto/memnode.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/memnode.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -784,6 +784,9 @@
// 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 @@
//----------------------------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 @@
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);
}
--- a/hotspot/src/share/vm/opto/memnode.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/memnode.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -137,7 +137,33 @@
//------------------------------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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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; }
--- a/hotspot/src/share/vm/opto/parse3.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/parse3.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -235,7 +235,7 @@
//
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)
--- a/hotspot/src/share/vm/opto/phaseX.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1573,11 +1573,12 @@
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 @@
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
+ }
+ }
+ }
+ }
}
}
}
--- a/hotspot/src/share/vm/opto/superword.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/superword.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1631,7 +1631,7 @@
}
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 @@
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.
--- a/hotspot/src/share/vm/opto/superword.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/superword.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -428,6 +428,7 @@
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
--- a/hotspot/src/share/vm/opto/vectornode.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/vectornode.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -406,9 +406,11 @@
// 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.
--- a/hotspot/src/share/vm/opto/vectornode.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/opto/vectornode.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -454,8 +454,8 @@
// 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 @@
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--------------------------------
--- a/hotspot/src/share/vm/prims/jni.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/prims/jni.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -1126,39 +1126,32 @@
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);
}
}
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -842,7 +842,7 @@
// 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;
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -677,24 +677,24 @@
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 @@
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 @@
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 @@
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);
+ }
+}
+
+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);
+ }
}
- 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::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);
+ }
+ }
}
- return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
+ if (marked > 0) {
+ // At least one nmethod has been marked for deoptimization
+ VM_Deoptimize op;
+ VMThread::execute(&op);
+ }
}
//------------------------------------------------------------------------------
@@ -1276,7 +1311,7 @@
{
// 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 @@
{
// 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 @@
#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 @@
{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)}
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -69,7 +69,10 @@
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();
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -64,7 +64,7 @@
}
#endif
-#ifdef SPARC
+#if defined SPARC || defined AARCH64
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
}
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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_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_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");
--- a/hotspot/src/share/vm/runtime/os.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/runtime/os.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -775,6 +775,10 @@
pd_start_thread(thread);
}
+void os::abort(bool dump_core) {
+ abort(dump_core && CreateCoredumpOnCrash, NULL, NULL);
+}
+
//---------------------------------------------------------------------------
// Helper functions for fatal error handler
--- a/hotspot/src/share/vm/runtime/reflection.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -831,9 +831,9 @@
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();
}
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri Jun 12 16:40:05 2015 -0400
@@ -315,7 +315,7 @@
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.");
}
--- a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp Fri Jun 12 16:40:05 2015 -0400
@@ -89,11 +89,11 @@
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<TagType>(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;
}
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java Fri Jun 12 16:40:05 2015 -0400
@@ -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);
+ }
+ }
+}
--- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 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 @@
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 @@
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");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java Fri Jun 12 16:40:05 2015 -0400
@@ -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");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java Fri Jun 12 16:40:05 2015 -0400
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java Fri Jun 12 16:40:05 2015 -0400
@@ -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);
+ }
+}
--- a/hotspot/test/gc/TestSmallHeap.java Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/test/gc/TestSmallHeap.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of InterfaceWithToString.
+ */
+public class ImplementationOfWithToString implements InterfaceWithToString {
+
+ /**
+ * @see InterfaceWithToString#someMethod()
+ * {@inheritDoc}
+ */
+ @Override
+ public void someMethod() {
+ // May do something here.
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return "toString() from " + getClass().getName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/**
+ * Interface with toString declared.
+ */
+public interface InterfaceWithToString {
+
+ void someMethod();
+
+ /**
+ * Same as Object.toString().
+ *
+ * @return some custom string.
+ */
+ String toString();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,41 @@
+/*
+ * 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 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c Fri Jun 12 16:40:05 2015 -0400
@@ -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, "<init>", "()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);
+}
--- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -59,7 +59,7 @@
}
OutputAnalyzer output = new OutputAnalyzer(gcLog, "");
- output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*");
+ output.shouldContain("[Full GC (Diagnostic Command)");
}
@Test
--- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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();
+ }
}
}
--- a/hotspot/test/serviceability/sa/TestStackTrace.java Fri Jun 12 16:36:33 2015 -0400
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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();
+ }
}
}
--- a/jaxp/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxp/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
ae7406e82828fe1c245ac7507a9da5fd5b1c9529 jdk9-b65
d5963ccce28d7a3e96ee3e2dc8a8676e61699b70 jdk9-b66
78c2685daabafae827c686ca2d1bb2e451faed2b jdk9-b67
+82aae947938ec9b0119fdd78a616d0b7263072ee jdk9-b68
--- a/jaxp/test/javax/xml/jaxp/functional/TEST.properties Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxp/test/javax/xml/jaxp/functional/TEST.properties Fri Jun 12 16:40:05 2015 -0400
@@ -7,3 +7,6 @@
# Tests that must run in othervm mode
othervm.dirs= /javax/xml/jaxp/functional
+# Declare module dependency
+modules=java.xml
+
--- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties Fri Jun 12 16:40:05 2015 -0400
@@ -1,3 +1,6 @@
# jaxp test uses TestNG
TestNG.dirs = .
+# Declare module dependency
+modules=java.xml
+
--- a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 <xi:include> 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 @@
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");
+ 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.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 @@
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;
--- a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -44,6 +44,7 @@
/*
+ * @bug 6439439 8080906
* @summary Test LSSerializer.
*/
public class LSSerializerTest {
@@ -98,6 +99,17 @@
}
}
+ /*
+ * @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() {
--- a/jaxws/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxws/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -313,3 +313,4 @@
45ef73bb85c12ec1b291835c1d40e342a454e3f0 jdk9-b65
1232f4013417e4a9cd291096798d10f2e601d69d jdk9-b66
c9785bc8ade98a16a050d7520b70c68363857e00 jdk9-b67
+b5878b03d1b2e105917d959fbfa3c57c22495803 jdk9-b68
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java Fri Jun 12 16:40:05 2015 -0400
@@ -68,6 +68,9 @@
*/
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 @@
}
}
+ private static ServiceLoaderUtil.ExceptionHandler<JAXBException> EXCEPTION_HANDLER =
+ new ServiceLoaderUtil.ExceptionHandler<JAXBException>() {
+ @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 @@
}
}
- 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 @@
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 @@
throw handleClassCastException(context.getClass(), JAXBContext.class);
}
return (JAXBContext) context;
- } catch (NoSuchMethodException e) {
+
+ } catch (NoSuchMethodException | IllegalAccessException e) {
throw new JAXBException(e);
- } catch (IllegalAccessException e) {
- throw new JAXBException(e);
+
} catch (InvocationTargetException e) {
handleInvocationTargetException(e);
@@ -261,9 +276,10 @@
}
}
- 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,106 +291,155 @@
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<String, ?> 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);
+
+ JAXBContextFactory factory =
+ ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
+
+ if (factory != null) return factory.createContext(classes, properties);
- Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
+ // to ensure backwards compatibility
+ String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
+ if (className != null) return newInstance(classes, properties, className);
+
+ 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);
}
- // TODO: to be removed - deprecated!!! Requires SPEC change!!!
- 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;
-
// else no provider found
logger.fine("Trying to create the platform default provider");
return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
}
- 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) {
- 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");
- }
+ }
+ // 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) {
+ return factoryClassName;
}
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 @@
}
}
- // 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 @@
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 {
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java Fri Jun 12 16:40:05 2015 -0400
@@ -45,29 +45,20 @@
* specialized forms of the method available:
*
* <ul>
- * <li>{@link #newInstance(String,ClassLoader) JAXBContext.newInstance( "com.acme.foo:com.acme.bar" )} <br>
- * 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").
- * </li>
- * <li>{@link #newInstance(Class...) JAXBContext.newInstance( com.acme.foo.Foo.class )} <br>
- * 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.
- * </li>
+ * <li>{@link #newInstance(String, ClassLoader) JAXBContext.newInstance( "com.acme.foo:com.acme.bar" )} <br>
+ * 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").
+ * </li>
+ * <li>{@link #newInstance(Class...) JAXBContext.newInstance( com.acme.foo.Foo.class )} <br>
+ * 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.
+ * </li>
* </ul>
*
- * <p>
- * <i><B>SPEC REQUIREMENT:</B> the provider must supply an implementation
- * class containing the following method signatures:</i>
- *
- * <pre>{@code
- * 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
- * }</pre>
- *
* <p><i>
* 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 @@
* any of the schemas listed in the <tt>contextPath</tt>. For example:
*
* <pre>
- * 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
* </pre>
*
* <p>
@@ -146,7 +137,7 @@
* Section 4.2 <i>Java Package</i> of the specification.
*
* <p>
- * <i><B>SPEC REQUIREMENT:</B> the provider must generate a class in each
+ * <i>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
* <tt>newInstance( javaContentInterface )</tt> method</i>
@@ -214,6 +205,7 @@
* by the following steps.
*
* <ol>
+ *
* <li>
* For each package/class explicitly passed in to the {@link #newInstance} method, in the order they are specified,
* <tt>jaxb.properties</tt> file is looked up in its package, by using the associated classloader —
@@ -223,7 +215,7 @@
* <p>
* 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.
*
* <p>
* This phase of the look up allows some packages to force the use of a certain JAXB implementation.
@@ -234,10 +226,36 @@
* factory class. This phase of the look up enables per-JVM override of the JAXB implementation.
*
* <li>
- * Look for <tt>/META-INF/services/javax.xml.bind.JAXBContext</tt> 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.
+ * <br>
+ * In case of {@link java.util.ServiceConfigurationError service
+ * configuration error} a {@link javax.xml.bind.JAXBException} will be thrown.
+ * </li>
+ *
+ * <li>
+ * 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:
+ *
+ * <pre>
+ *
+ * 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
+ * </pre>
+ * This configuration method is deprecated.
*
* <li>
* Finally, if all the steps above fail, then the rest of the look up is unspecified. That said,
@@ -246,17 +264,30 @@
* </ol>
*
* <p>
- * Once the provider factory class is discovered, its
- * <tt>public static JAXBContext createContext(String,ClassLoader,Map)</tt> method
- * (see {@link #newInstance(String, ClassLoader, Map)} for the parameter semantics.)
- * or <tt>public static JAXBContext createContet(Class[],Map)</tt> 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 <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li><li>Joe Fialli, Sun Microsystems, Inc.</li></ul>
+ * <p/>
+ *
+ * @apiNote
+ * <p>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 <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li>
+ * <li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li>
+ * <li>Joe Fialli, Sun Microsystems, Inc.</li></ul>
+ *
* @see Marshaller
* @see Unmarshaller
- * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.4.1">S 7.4.1 "Named Packages" in Java Language Specification</a>
+ * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.4.1">S 7.4.1 "Named Packages"
+ * in Java Language Specification</a>
+ *
* @since 1.6, JAXB 1.0
*/
public abstract class JAXBContext {
@@ -265,9 +296,7 @@
* The name of the property that contains the name of the class capable
* of creating new <tt>JAXBContext</tt> 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 @@
/**
* <p>
- * Obtain a new instance of a <tt>JAXBContext</tt> class.
+ * Create a new instance of a <tt>JAXBContext</tt> class.
*
* <p>
* This is a convenience method to invoke the
@@ -300,7 +329,7 @@
/**
* <p>
- * Obtain a new instance of a <tt>JAXBContext</tt> class.
+ * Create a new instance of a <tt>JAXBContext</tt> class.
*
* <p>
* The client application must supply a context path which is a list of
@@ -396,7 +425,7 @@
/**
* <p>
- * Obtain a new instance of a <tt>JAXBContext</tt> class.
+ * Create a new instance of a <tt>JAXBContext</tt> class.
*
* <p>
* This is mostly the same as {@link JAXBContext#newInstance(String, ClassLoader)},
@@ -425,8 +454,9 @@
* </ol>
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( String contextPath, ClassLoader classLoader, Map<String,?> properties )
- throws JAXBException {
+ public static JAXBContext newInstance( String contextPath,
+ ClassLoader classLoader,
+ Map<String,?> properties ) throws JAXBException {
return ContextFinder.find(
/* The default property name according to the JAXB spec */
@@ -443,7 +473,7 @@
// TODO: resurrect this once we introduce external annotations
// /**
// * <p>
-// * Obtain a new instance of a <tt>JAXBContext</tt> class.
+// * Create a new instance of a <tt>JAXBContext</tt> class.
// *
// * <p>
// * The client application must supply a list of classes that the new
@@ -479,7 +509,7 @@
// * spec-defined classes will be returned.
// *
// * @return
-// * A new instance of a <tt>JAXBContext</tt>. Always non-null valid object.
+// * A new instance of a <tt>JAXBContext</tt>.
// *
// * @throws JAXBException
// * if an error was encountered while creating the
@@ -517,7 +547,7 @@
/**
* <p>
- * Obtain a new instance of a <tt>JAXBContext</tt> class.
+ * Create a new instance of a <tt>JAXBContext</tt> class.
*
* <p>
* The client application must supply a list of classes that the new
@@ -559,7 +589,7 @@
* spec-defined classes will be returned.
*
* @return
- * A new instance of a <tt>JAXBContext</tt>. Always non-null valid object.
+ * A new instance of a <tt>JAXBContext</tt>.
*
* @throws JAXBException
* if an error was encountered while creating the
@@ -578,7 +608,7 @@
*
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( Class... classesToBeBound )
+ public static JAXBContext newInstance( Class<?> ... classesToBeBound )
throws JAXBException {
return newInstance(classesToBeBound,Collections.<String,Object>emptyMap());
@@ -586,7 +616,7 @@
/**
* <p>
- * Obtain a new instance of a <tt>JAXBContext</tt> class.
+ * Create a new instance of a <tt>JAXBContext</tt> class.
*
* <p>
* An overloading of {@link JAXBContext#newInstance(Class...)}
@@ -605,7 +635,7 @@
* in an empty map.
*
* @return
- * A new instance of a <tt>JAXBContext</tt>. Always non-null valid object.
+ * A new instance of a <tt>JAXBContext</tt>.
*
* @throws JAXBException
* if an error was encountered while creating the
@@ -624,7 +654,7 @@
*
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( Class[] classesToBeBound, Map<String,?> properties )
+ public static JAXBContext newInstance( Class<?>[] classesToBeBound, Map<String,?> properties )
throws JAXBException {
if (classesToBeBound == null) {
@@ -756,9 +786,9 @@
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<ClassLoader>() {
+ public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java Fri Jun 12 16:40:05 2015 -0400
@@ -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;
+
+/**
+ * <p>Factory that creates new <code>JAXBContext</code> instances.
+ *
+ * JAXBContextFactory can be located using {@link java.util.ServiceLoader#load(Class)}
+ *
+ * @since 1.9, JAXB 2.3
+ */
+public interface JAXBContextFactory {
+
+ /**
+ * <p>
+ * Create a new instance of a <tt>JAXBContext</tt> class.
+ *
+ * <p>
+ * 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 <tt>JAXBContext</tt>.
+ *
+ * @throws JAXBException
+ * if an error was encountered while creating the
+ * <tt>JAXBContext</tt>, such as (but not limited to):
+ * <ol>
+ * <li>Classes use JAXB annotations incorrectly
+ * <li>Classes have colliding annotations (i.e., two classes with the same type name)
+ * <li>The JAXB implementation was unable to locate
+ * provider-specific out-of-band information (such as additional
+ * files generated at the development time.)
+ * </ol>
+ *
+ * @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<String, ?> properties ) throws JAXBException;
+
+ /**
+ * <p>
+ * Create a new instance of a <tt>JAXBContext</tt> class.
+ *
+ * <p>
+ * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(String, ClassLoader, java.util.Map)}
+ *
+ * <p>
+ * The interpretation of properties is up to implementations. Implementations should
+ * throw <tt>JAXBException</tt> 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 <tt>JAXBContext</tt>
+ * @throws JAXBException if an error was encountered while creating the
+ * <tt>JAXBContext</tt> such as
+ * <ol>
+ * <li>failure to locate either ObjectFactory.class or jaxb.index in the packages</li>
+ * <li>an ambiguity among global elements contained in the contextPath</li>
+ * <li>failure to locate a value for the context factory provider property</li>
+ * <li>mixing schema derived packages from different providers on the same contextPath</li>
+ * </ol>
+ * @since 1.9, JAXB 2.3
+ */
+ JAXBContext createContext(String contextPath,
+ ClassLoader classLoader,
+ Map<String, ?> properties ) throws JAXBException;
+
+}
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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> P firstByServiceLoader(Class<P> spiClass, Logger logger) {
+ static <P, T extends Exception> P firstByServiceLoader(Class<P> spiClass,
+ Logger logger,
+ ExceptionHandler<T> handler) throws T {
// service discovery
- ServiceLoader<P> serviceLoader = ServiceLoader.load(spiClass);
- for (P impl : serviceLoader) {
- logger.fine("ServiceProvider loading Facility used; returning object [" + impl.getClass().getName() + "]");
- return impl;
+ try {
+ ServiceLoader<P> 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) {
- 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 @@
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 @@
}
}
- /**
- * 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 <T> 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 <T extends Exception> Object newInstance(String className, String defaultImplClassName, final ExceptionHandler<T> 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 <T extends Exception> Object newInstance(String className,
+ String defaultImplClassName,
+ final ExceptionHandler<T> handler) throws T {
try {
return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance();
} catch (ClassNotFoundException x) {
@@ -151,7 +123,10 @@
}
}
- 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 @@
return nullSafeLoadClass(className, classLoader);
}
- static String getJavaHomeLibConfigPath(String filename) {
- String javah = AccessController.doPrivileged(new PrivilegedAction<String>() {
- @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();
--- a/jdk/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
ed94f3e7ba6bbfec0772de6d24e39543e13f6d88 jdk9-b65
4fbcca8ab812198c7fb747ea7b213b6e404f36e9 jdk9-b66
1abd45df5480a04bff98fba1851d66a5230e67d4 jdk9-b67
+046fd17bb9a0cdf6681124866df9626d17b0516a jdk9-b68
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
/**
* 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
*/
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
/**
* 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
*/
--- a/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
* 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();
--- a/jdk/src/java.base/share/classes/java/security/CodeSource.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java Fri Jun 12 16:40:05 2015 -0400
@@ -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.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.*;
+import sun.net.util.URLUtil;
/**
*
@@ -73,6 +74,15 @@
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 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 CodeSource(URL url, CodeSigner[] signers) {
this.location = url;
+ if (url != null) {
+ this.locationNoFragString = URLUtil.urlNoFragString(url);
+ }
// Copy the supplied signers
if (signers != null) {
@@ -169,6 +185,13 @@
}
/**
+ * 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.
* <p>
* If this CodeSource object was created using the
@@ -588,6 +611,10 @@
} catch (IOException ioe) {
// no signers present
}
+
+ if (location != null) {
+ locationNoFragString = URLUtil.urlNoFragString(location);
+ }
}
/*
--- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Fri Jun 12 16:40:05 2015 -0400
@@ -47,10 +47,16 @@
*/
private final boolean initialized;
- // HashMap that maps CodeSource to ProtectionDomain
- // @GuardedBy("pdcache")
- private final HashMap<CodeSource, ProtectionDomain> 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<String, ProtectionDomain> pdcache = new HashMap<>(11);
private static final Debug debug = Debug.getInstance("scl");
@@ -196,16 +202,22 @@
* 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("");
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
@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());
}
--- a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
public <T> 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 TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
& @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
- @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable > {
+ @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 extends @TypeAnno("M Runnable") Runnable> 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> L foo4() {return null;}
}
@Target(ElementType.TYPE_USE)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.java Fri Jun 12 16:40:05 2015 -0400
@@ -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<Permission> perms1 = getPermissions(scl, p,
+ "http://localhost/",
+ "Foo", FOO_CLASS);
+ checkPerms(perms1, GRANTED_PERMS);
+ ArrayList<Permission> 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<Permission> 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<Permission> 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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.policy Fri Jun 12 16:40:05 2015 -0400
@@ -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";
+};
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java Fri Jun 12 16:36:33 2015 -0400
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java Fri Jun 12 16:40:05 2015 -0400
@@ -26,6 +26,7 @@
* @summary unit test for Arrays.ParallelPrefix().
* @author Tristan Yan
* @run testng ParallelPrefix
+ * @key intermittent
*/
import java.util.Arrays;
--- a/langtools/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -310,3 +310,4 @@
4fcf722b811406a7db8f206d88446c82cda1b5f4 jdk9-b65
fd6bda430d96fc5ab421161de016412f2ddd9082 jdk9-b66
fd782cd69b0497299269952d30a6b88cad960fcf jdk9-b67
+c71857c93f57c63be44258d3d67e656c2bacdb45 jdk9-b68
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Jun 12 16:40:05 2015 -0400
@@ -2175,11 +2175,19 @@
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)) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java Fri Jun 12 16:40:05 2015 -0400
@@ -479,22 +479,6 @@
}
/**
- * 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 @@
.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)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
*/
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 void calculateDependents() {
dependents = new HashMap<>();
+
for (String s : packages.keySet()) {
Package p = packages.get(s);
- for (String d : p.dependencies()) {
- Set<String> ss = dependents.get(d);
- if (ss == null) {
- ss = new HashSet<>();
- dependents.put(d, ss);
- }
+
+ // Collect all dependencies of the classes in this package
+ Set<String> 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 void copyPackagesExcept(BuildState prev, Set<String> recompiled, Set<String> 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);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Fri Jun 12 16:40:05 2015 -0400
@@ -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.HashSet;
import java.util.List;
-import java.util.Set;
-import java.util.HashSet;
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 @@
Map<String,Set<String>> oldPackageDependencies,
URI destRoot,
Map<String,Set<URI>> packageArtifacts,
- Map<String,Set<String>> packageDependencies,
- Map<String,String> packagePublicApis,
+ Map<String, Map<String, Set<String>>> packageDependencies,
+ Map<String, Map<String, Set<String>>> packageCpDependencies,
+ Map<String, PubApi> packagePublicApis,
+ Map<String, PubApi> dependencyPublicApis,
int debugLevel,
boolean incremental,
int numCores,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Fri Jun 12 16:40:05 2015 -0400
@@ -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.net.URI;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
-import java.util.Map;
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 @@
Map<String,Set<String>> oldPackageDependents,
URI destRoot,
final Map<String,Set<URI>> packageArtifacts,
- final Map<String,Set<String>> packageDependencies,
- final Map<String,String> packagePubapis,
+ final Map<String,Map<String, Set<String>>> packageDependencies,
+ final Map<String,Map<String, Set<String>>> packageCpDependencies,
+ final Map<String, PubApi> packagePubapis,
+ final Map<String, PubApi> 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 @@
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.<File>emptyList(),
- cc.srcs,
- visibleSources);
- packageArtifacts.putAll(rn[ii].packageArtifacts);
- packageDependencies.putAll(rn[ii].packageDependencies);
- packagePubapis.putAll(rn[ii].packagePubapis);
+ id + "-" + ii,
+ args.prepJavacArgs(),
+ Collections.<File>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<URI> 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 @@
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 @@
* @return
*/
CompileChunk[] createCompileChunks(Map<String,Set<URI>> pkgSrcs,
- Map<String,Set<String>> oldPackageDependents,
- int numCompiles,
- int sourcesPerCompile) {
+ Map<String,Set<String>> oldPackageDependents,
+ int numCompiles,
+ int sourcesPerCompile) {
CompileChunk[] compileChunks = new CompileChunk[numCompiles];
for (int i=0; i<compileChunks.length; ++i) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Fri Jun 12 16:40:05 2015 -0400
@@ -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,19 +25,27 @@
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.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.Sjavac;
/**
@@ -70,8 +78,10 @@
Map<String,Set<String>> oldPackageDependents,
URI destRoot,
Map<String,Set<URI>> packageArtifacts,
- Map<String,Set<String>> packageDependencies,
- Map<String,String> packagePublicApis,
+ Map<String,Map<String, Set<String>>> packageDependencies,
+ Map<String,Map<String, Set<String>>> packageCpDependencies,
+ Map<String, PubApi> packagePublicApis,
+ Map<String, PubApi> dependencyPublicApis,
int debugLevel,
boolean incremental,
int numCores,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Fri Jun 12 16:40:05 2015 -0400
@@ -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 @@
Map<String,Set<String>> oldPackageDependents,
URI destRoot,
Map<String,Set<URI>> packageArtifacts,
- Map<String,Set<String>> packageDependencies,
- Map<String,String> packagePubapis,
+ Map<String,Map<String, Set<String>>> packageDependencies,
+ Map<String,Map<String, Set<String>>> packageCpDependencies,
+ Map<String, PubApi> packagePubapis,
+ Map<String, PubApi> dependencyPubapis,
int debugLevel,
boolean incremental,
int numCores,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Fri Jun 12 16:40:05 2015 -0400
@@ -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,11 +25,17 @@
package com.sun.tools.sjavac;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
import java.net.URI;
import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -37,8 +43,10 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.Sjavac;
/**
@@ -268,24 +276,25 @@
* Save the javac_state file.
*/
public void save() throws IOException {
- if (!needsSaving) return;
+ if (!needsSaving)
+ return;
try (FileWriter out = new FileWriter(javacState)) {
StringBuilder b = new StringBuilder();
long millisNow = System.currentTimeMillis();
Date d = new Date(millisNow);
- SimpleDateFormat df =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
- b.append("# javac_state ver 0.3 generated "+millisNow+" "+df.format(d)+"\n");
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
+ b.append("# javac_state ver 0.4 generated "+millisNow+" "+df.format(d)+"\n");
b.append("# This format might change at any time. Please do not depend on it.\n");
+ b.append("# R arguments\n");
b.append("# M module\n");
b.append("# P package\n");
b.append("# S C source_tobe_compiled timestamp\n");
b.append("# S L link_only_source timestamp\n");
b.append("# G C generated_source timestamp\n");
b.append("# A artifact timestamp\n");
- b.append("# D dependency\n");
+ b.append("# D S dependant -> source dependency\n");
+ b.append("# D C dependant -> classpath dependency\n");
b.append("# I pubapi\n");
- b.append("# R arguments\n");
b.append("R ").append(theArgs).append("\n");
// Copy over the javac_state for the packages that did not need recompilation.
@@ -312,6 +321,8 @@
boolean newCommandLine = false;
boolean syntaxError = false;
+ Log.debug("Loading javac state file: " + db.javacState);
+
try (BufferedReader in = new BufferedReader(new FileReader(db.javacState))) {
for (;;) {
String l = in.readLine();
@@ -327,11 +338,14 @@
} else
if (c == 'D') {
if (lastModule == null || lastPackage == null) { syntaxError = true; break; }
- lastPackage.loadDependency(l);
+ char depType = l.charAt(2);
+ if (depType != 'S' && depType != 'C')
+ throw new RuntimeException("Bad dependency string: " + l);
+ lastPackage.parseAndAddDependency(l.substring(4), depType == 'C');
} else
if (c == 'I') {
if (lastModule == null || lastPackage == null) { syntaxError = true; break; }
- lastPackage.loadPubapi(l);
+ lastPackage.getPubApi().appendItem(l.substring(2)); // Strip "I "
} else
if (c == 'A') {
if (lastModule == null || lastPackage == null) { syntaxError = true; break; }
@@ -356,7 +370,7 @@
int sp = l.indexOf(" ", 18);
if (sp != -1) {
String ver = l.substring(18,sp);
- if (!ver.equals("0.3")) {
+ if (!ver.equals("0.4")) {
break;
}
foundCorrectVerNr = true;
@@ -488,11 +502,92 @@
* Propagate recompilation through the dependency chains.
* Avoid re-tainting packages that have already been compiled.
*/
- public void taintPackagesDependingOnChangedPackages(Set<String> pkgs, Set<String> recentlyCompiled) {
+ public void taintPackagesDependingOnChangedPackages(Set<String> pkgsWithChangedPubApi, Set<String> recentlyCompiled) {
+ // For each to-be-recompiled-candidates...
+ for (Package pkg : new HashSet<>(prev.packages().values())) {
+ // Find out what it depends upon...
+ Set<String> deps = pkg.typeDependencies()
+ .values()
+ .stream()
+ .flatMap(s -> s.stream())
+ .collect(Collectors.toSet());
+ for (String dep : deps) {
+ String depPkg = ":" + dep.substring(0, dep.lastIndexOf('.'));
+ if (depPkg.equals(pkg.name()))
+ continue;
+ // Checking if that dependency has changed
+ if (pkgsWithChangedPubApi.contains(depPkg) && !recentlyCompiled.contains(pkg.name())) {
+ taintPackage(pkg.name(), "its depending on " + depPkg);
+ }
+ }
+ }
+ }
+
+ /**
+ * Compare the javac_state recorded public apis of packages on the classpath
+ * with the actual public apis on the classpath.
+ */
+ public void taintPackagesDependingOnChangedClasspathPackages() {
+
+ // 1. Collect fully qualified names of all interesting classpath dependencies
+ Set<String> fqDependencies = new HashSet<>();
for (Package pkg : prev.packages().values()) {
- for (String dep : pkg.dependencies()) {
- if (pkgs.contains(dep) && !recentlyCompiled.contains(pkg.name())) {
- taintPackage(pkg.name(), " its depending on "+dep);
+ // Check if this package was compiled. If it's presence is recorded
+ // because it was on the class path and we needed to save it's
+ // public api, it's not a candidate for tainting.
+ if (pkg.sources().isEmpty())
+ continue;
+
+ pkg.typeClasspathDependencies().values().forEach(fqDependencies::addAll);
+ }
+
+ // 2. Extract the public APIs from the on disk .class files
+ // (Reason for doing step 1 in a separate phase is to avoid extracting
+ // public APIs of the same class twice.)
+ PubApiExtractor pubApiExtractor = new PubApiExtractor(options);
+ Map<String, PubApi> onDiskPubApi = new HashMap<>();
+ for (String cpDep : fqDependencies) {
+ onDiskPubApi.put(cpDep, pubApiExtractor.getPubApi(cpDep));
+ }
+
+ // 3. Compare them with the public APIs as of last compilation (loaded from javac_state)
+ nextPkg:
+ for (Package pkg : prev.packages().values()) {
+ // Check if this package was compiled. If it's presence is recorded
+ // because it was on the class path and we needed to save it's
+ // public api, it's not a candidate for tainting.
+ if (pkg.sources().isEmpty())
+ continue;
+
+ Set<String> cpDepsOfThisPkg = new HashSet<>();
+ for (Set<String> cpDeps : pkg.typeClasspathDependencies().values())
+ cpDepsOfThisPkg.addAll(cpDeps);
+
+ for (String fqDep : cpDepsOfThisPkg) {
+
+ String depPkg = ":" + fqDep.substring(0, fqDep.lastIndexOf('.'));
+ PubApi prevPkgApi = prev.packages().get(depPkg).getPubApi();
+
+ // This PubApi directly lists the members of the class,
+ // i.e. [ MEMBER1, MEMBER2, ... ]
+ PubApi prevDepApi = prevPkgApi.types.get(fqDep).pubApi;
+
+ // In order to dive *into* the class, we need to add
+ // .types.get(fqDep).pubApi below.
+ PubApi currentDepApi = onDiskPubApi.get(fqDep).types.get(fqDep).pubApi;
+
+ if (!currentDepApi.isBackwardCompatibleWith(prevDepApi)) {
+ List<String> apiDiff = currentDepApi.diff(prevDepApi);
+ taintPackage(pkg.name(), "depends on classpath "
+ + "package which has an updated package api: "
+ + String.join("\n", apiDiff));
+ //Log.debug("========================================");
+ //Log.debug("------ PREV API ------------------------");
+ //prevDepApi.asListOfStrings().forEach(Log::debug);
+ //Log.debug("------ CURRENT API ---------------------");
+ //currentDepApi.asListOfStrings().forEach(Log::debug);
+ //Log.debug("========================================");
+ continue nextPkg;
}
}
}
@@ -660,7 +755,6 @@
Map<String,Transformer> suffixRules = new HashMap<>();
suffixRules.put(".java", compileJavaPackages);
compileJavaPackages.setExtra(args);
-
rcValue[0] = perform(sjavac, binDir, suffixRules);
recentlyCompiled.addAll(taintedPackages());
clearTaintedPackages();
@@ -668,6 +762,11 @@
taintPackagesDependingOnChangedPackages(packagesWithChangedPublicApis, recentlyCompiled);
packagesWithChangedPublicApis = new HashSet<>();
return again && rcValue[0];
+
+ // TODO: Figure out why 'again' checks packagesWithChangedPublicAPis.
+ // (It shouldn't matter if packages had changed pub apis as long as no
+ // one depends on them. Wouldn't it make more sense to let 'again'
+ // depend on taintedPackages?)
}
/**
@@ -699,68 +798,101 @@
Map<Transformer,Map<String,Set<URI>>> groupedSources = new HashMap<>();
for (Source src : now.sources().values()) {
Transformer t = suffixRules.get(src.suffix());
- if (t != null) {
+ if (t != null) {
if (taintedPackages.contains(src.pkg().name()) && !src.isLinkedOnly()) {
addFileToTransform(groupedSources, t, src);
}
}
}
// Go through the transforms and transform them.
- for (Map.Entry<Transformer,Map<String,Set<URI>>> e : groupedSources.entrySet()) {
+ for (Map.Entry<Transformer, Map<String, Set<URI>>> e : groupedSources.entrySet()) {
Transformer t = e.getKey();
- Map<String,Set<URI>> srcs = e.getValue();
- // These maps need to be synchronized since multiple threads will be writing results into them.
- Map<String,Set<URI>> packageArtifacts =
- Collections.synchronizedMap(new HashMap<String,Set<URI>>());
- Map<String,Set<String>> packageDependencies =
- Collections.synchronizedMap(new HashMap<String,Set<String>>());
- Map<String,String> packagePublicApis =
- Collections.synchronizedMap(new HashMap<String, String>());
+ Map<String, Set<URI>> srcs = e.getValue();
+ // These maps need to be synchronized since multiple threads will be
+ // writing results into them.
+ Map<String, Set<URI>> packageArtifacts = Collections.synchronizedMap(new HashMap<>());
+ Map<String, Map<String, Set<String>>> packageDependencies = Collections.synchronizedMap(new HashMap<>());
+ Map<String, Map<String, Set<String>>> packageCpDependencies = Collections.synchronizedMap(new HashMap<>());
+ Map<String, PubApi> packagePublicApis = Collections.synchronizedMap(new HashMap<>());
+ Map<String, PubApi> dependencyPublicApis = Collections.synchronizedMap(new HashMap<>());
- boolean r = t.transform(sjavac,
- srcs,
- visibleSrcs,
- visibleClasses,
- prev.dependents(),
- outputDir.toURI(),
- packageArtifacts,
- packageDependencies,
- packagePublicApis,
- 0,
- isIncremental(),
- numCores,
- out,
- err);
- if (!r) rc = false;
+ boolean r = t.transform(sjavac,
+ srcs,
+ visibleSrcs,
+ visibleClasses,
+ prev.dependents(),
+ outputDir.toURI(),
+ packageArtifacts,
+ packageDependencies,
+ packageCpDependencies,
+ packagePublicApis,
+ dependencyPublicApis,
+ 0,
+ isIncremental(),
+ numCores,
+ out,
+ err);
+ if (!r)
+ rc = false;
for (String p : srcs.keySet()) {
recompiledPackages.add(p);
}
// The transform is done! Extract all the artifacts and store the info into the Package objects.
- for (Map.Entry<String,Set<URI>> a : packageArtifacts.entrySet()) {
+ for (Map.Entry<String, Set<URI>> a : packageArtifacts.entrySet()) {
Module mnow = now.findModuleFromPackageName(a.getKey());
mnow.addArtifacts(a.getKey(), a.getValue());
}
// Extract all the dependencies and store the info into the Package objects.
- for (Map.Entry<String,Set<String>> a : packageDependencies.entrySet()) {
- Set<String> deps = a.getValue();
+ for (Map.Entry<String, Map<String, Set<String>>> a : packageDependencies.entrySet()) {
+ Map<String, Set<String>> deps = a.getValue();
Module mnow = now.findModuleFromPackageName(a.getKey());
- mnow.setDependencies(a.getKey(), deps);
+ mnow.setDependencies(a.getKey(), deps, false);
+ }
+ for (Map.Entry<String, Map<String, Set<String>>> a : packageCpDependencies.entrySet()) {
+ Map<String, Set<String>> deps = a.getValue();
+ Module mnow = now.findModuleFromPackageName(a.getKey());
+ mnow.setDependencies(a.getKey(), deps, true);
}
- // Extract all the pubapis and store the info into the Package objects.
- for (Map.Entry<String,String> a : packagePublicApis.entrySet()) {
- Module mprev = prev.findModuleFromPackageName(a.getKey());
- List<String> pubapi = Package.pubapiToList(a.getValue());
- Module mnow = now.findModuleFromPackageName(a.getKey());
- mnow.setPubapi(a.getKey(), pubapi);
- if (mprev.hasPubapiChanged(a.getKey(), pubapi)) {
+
+ // This map contains the public api of the types that this
+ // compilation depended upon. This means that it may not contain
+ // full packages. In other words, we shouldn't remove knowledge of
+ // public apis but merge these with what we already have.
+ for (Map.Entry<String, PubApi> a : dependencyPublicApis.entrySet()) {
+ String pkg = a.getKey();
+ PubApi packagePartialPubApi = a.getValue();
+ Package pkgNow = now.findModuleFromPackageName(pkg).lookupPackage(pkg);
+ PubApi currentPubApi = pkgNow.getPubApi();
+ PubApi newPubApi = PubApi.mergeTypes(currentPubApi, packagePartialPubApi);
+ pkgNow.setPubapi(newPubApi);
+
+ // See JDK-8071904
+ if (now.packages().containsKey(pkg))
+ now.packages().get(pkg).setPubapi(newPubApi);
+ else
+ now.packages().put(pkg, pkgNow);
+ }
+
+ // The packagePublicApis cover entire packages (since sjavac compiles
+ // stuff on package level). This means that if a type is missing
+ // in the public api of a given package, it means that it has been
+ // removed. In other words, we should *set* the pubapi to whatever
+ // this map contains, and not merge it with what we already have.
+ for (Map.Entry<String, PubApi> a : packagePublicApis.entrySet()) {
+ String pkg = a.getKey();
+ PubApi newPubApi = a.getValue();
+ Module mprev = prev.findModuleFromPackageName(pkg);
+ Module mnow = now.findModuleFromPackageName(pkg);
+ mnow.setPubapi(pkg, newPubApi);
+ if (mprev.hasPubapiChanged(pkg, newPubApi)) {
// Aha! The pubapi of this package has changed!
// It can also be a new compile from scratch.
- if (mprev.lookupPackage(a.getKey()).existsInJavacState()) {
+ if (mprev.lookupPackage(pkg).existsInJavacState()) {
// This is an incremental compile! The pubapi
// did change. Trigger recompilation of dependents.
- packagesWithChangedPublicApis.add(a.getKey());
- Log.info("The pubapi of "+Util.justPackageName(a.getKey())+" has changed!");
+ packagesWithChangedPublicApis.add(pkg);
+ Log.info("The API of " + Util.justPackageName(pkg) + " has changed!");
}
}
}
@@ -791,17 +923,21 @@
}
/**
- * Compare the calculate source list, with an explicit list, usually supplied from the makefile.
- * Used to detect bugs where the makefile and sjavac have different opinions on which files
- * should be compiled.
+ * Compare the calculate source list, with an explicit list, usually
+ * supplied from the makefile. Used to detect bugs where the makefile and
+ * sjavac have different opinions on which files should be compiled.
*/
- public void compareWithMakefileList(File makefileSourceList) throws ProblemException {
- // If we are building on win32 using for example cygwin the paths in the makefile source list
+ public void compareWithMakefileList(File makefileSourceList)
+ throws ProblemException {
+ // If we are building on win32 using for example cygwin the paths in the
+ // makefile source list
// might be /cygdrive/c/.... which does not match c:\....
- // We need to adjust our calculated sources to be identical, if necessary.
+ // We need to adjust our calculated sources to be identical, if
+ // necessary.
boolean mightNeedRewriting = File.pathSeparatorChar == ';';
- if (makefileSourceList == null) return;
+ if (makefileSourceList == null)
+ return;
Set<String> calculatedSources = new HashSet<>();
Set<String> listedSources = new HashSet<>();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -28,10 +28,11 @@
import java.io.File;
import java.net.URI;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
+import com.sun.tools.sjavac.pubapi.PubApi;
+
/**
* The module is the root of a set of packages/sources/artifacts.
* At the moment there is only one module in use, the empty/no-name/default module.
@@ -86,8 +87,7 @@
return new Module(name, "");
}
- public static void saveModules(Map<String,Module> ms, StringBuilder b)
- {
+ public static void saveModules(Map<String,Module> ms, StringBuilder b) {
for (Module m : ms.values()) {
m.save(b);
}
@@ -98,6 +98,7 @@
}
public Package lookupPackage(String pkg) {
+ // See JDK-8071904
Package p = packages.get(pkg);
if (p == null) {
p = new Package(this, pkg);
@@ -124,18 +125,17 @@
}
}
- public void setDependencies(String pkg, Set<String> deps) {
- Package p = lookupPackage(pkg);
- p.setDependencies(deps);
+ public void setDependencies(String pkg, Map<String, Set<String>> deps, boolean cp) {
+ lookupPackage(pkg).setDependencies(deps, cp);
}
- public void setPubapi(String pkg, List<String> ps) {
+ public void setPubapi(String pkg, PubApi ps) {
Package p = lookupPackage(pkg);
p.setPubapi(ps);
}
- public boolean hasPubapiChanged(String pkg, List<String> ps) {
+ public boolean hasPubapiChanged(String pkg, PubApi newPubApi) {
Package p = lookupPackage(pkg);
- return p.hasPubapiChanged(ps);
+ return p.hasPubApiChanged(newPubApi);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -31,11 +31,16 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
import com.sun.tools.javac.util.Assert;
+import com.sun.tools.sjavac.pubapi.PubApi;
/**
* The Package class maintains meta information about a package.
@@ -71,12 +76,16 @@
// The directory path to the package. If the package belongs to a module,
// then that module's file system name is part of the path.
private String dirname;
- // This package depends on these packages.
- private Set<String> dependencies = new HashSet<>();
// This package has the following dependents, that depend on this package.
private Set<String> dependents = new HashSet<>();
+
+ // Fully qualified name of class in this package -> fully qualified name of dependency
+ private Map<String, Set<String>> dependencies = new TreeMap<>();
+ // Fully qualified name of class in this package -> fully qualified name of dependency on class path
+ private Map<String, Set<String>> cpDependencies = new TreeMap<>();
+
// This is the public api of this package.
- private List<String> pubapi = new ArrayList<>();
+ private PubApi pubApi = new PubApi();
// Map from source file name to Source info object.
private Map<String,Source> sources = new HashMap<>();
// This package generated these artifacts.
@@ -85,7 +94,6 @@
public Package(Module m, String n) {
int c = n.indexOf(":");
Assert.check(c != -1);
- String mn = n.substring(0,c);
Assert.check(m.name().equals(m.name()));
name = n;
dirname = n.replace('.', File.separatorChar);
@@ -100,9 +108,11 @@
public String dirname() { return dirname; }
public Map<String,Source> sources() { return sources; }
public Map<String,File> artifacts() { return artifacts; }
- public List<String> pubapi() { return pubapi; }
+ public PubApi getPubApi() { return pubApi; }
- public Set<String> dependencies() { return dependencies; }
+ public Map<String,Set<String>> typeDependencies() { return dependencies; }
+ public Map<String,Set<String>> typeClasspathDependencies() { return cpDependencies; }
+
public Set<String> dependents() { return dependents; }
@Override
@@ -124,70 +134,48 @@
sources.put(s.file().getPath(), s);
}
- public void addDependency(String d) {
- dependencies.add(d);
+ private static Pattern DEP_PATTERN = Pattern.compile("(.*) -> (.*)");
+ public void parseAndAddDependency(String d, boolean cp) {
+ Matcher m = DEP_PATTERN.matcher(d);
+ if (!m.matches())
+ throw new IllegalArgumentException("Bad dependency string: " + d);
+ addDependency(m.group(1), m.group(2), cp);
+ }
+
+ public void addDependency(String fullyQualifiedFrom,
+ String fullyQualifiedTo,
+ boolean cp) {
+ Map<String, Set<String>> map = cp ? cpDependencies : dependencies;
+ if (!map.containsKey(fullyQualifiedFrom))
+ map.put(fullyQualifiedFrom, new HashSet<>());
+ map.get(fullyQualifiedFrom).add(fullyQualifiedTo);
}
public void addDependent(String d) {
dependents.add(d);
}
- public void addPubapi(String p) {
- pubapi.add(p);
- }
-
/**
* Check if we have knowledge in the javac state that
* describe the results of compiling this package before.
*/
public boolean existsInJavacState() {
- return artifacts.size() > 0 || pubapi.size() > 0;
+ return artifacts.size() > 0 || !pubApi.isEmpty();
}
- public static List<String> pubapiToList(String ps)
- {
- String[] lines = ps.split("\n");
- List<String> r = new ArrayList<>();
- for (String l : lines) {
- r.add(l);
- }
- return r;
+ public boolean hasPubApiChanged(PubApi newPubApi) {
+ return !newPubApi.isBackwardCompatibleWith(pubApi);
}
- public boolean hasPubapiChanged(List<String> ps) {
- Iterator<String> i = ps.iterator();
- Iterator<String> j = pubapi.iterator();
- int line = 0;
- while (i.hasNext() && j.hasNext()) {
- String is = i.next();
- String js = j.next();
- if (!is.equals(js)) {
- Log.debug("Change in pubapi for package "+name+" line "+line);
- Log.debug("Old: "+js);
- Log.debug("New: "+is);
- return true;
- }
- line++;
- }
- if ((i.hasNext() && !j.hasNext() ) ||
- (!i.hasNext() && j.hasNext())) {
- Log.debug("Change in pubapi for package "+name);
- if (i.hasNext()) {
- Log.debug("New has more lines!");
- } else {
- Log.debug("Old has more lines!");
- }
- return true;
- }
- return false;
+ public void setPubapi(PubApi newPubApi) {
+ pubApi = newPubApi;
}
- public void setPubapi(List<String> ps) {
- pubapi = ps;
- }
-
- public void setDependencies(Set<String> ds) {
- dependencies = ds;
+ public void setDependencies(Map<String, Set<String>> ds, boolean cp) {
+ (cp ? cpDependencies : dependencies).clear();
+ for (String fullyQualifiedFrom : ds.keySet())
+ for (String fullyQualifiedTo : ds.get(fullyQualifiedFrom))
+ addDependency(fullyQualifiedFrom, fullyQualifiedTo, cp);
}
public void save(StringBuilder b) {
@@ -203,31 +191,28 @@
return new Package(module, name);
}
- public void loadDependency(String l) {
- String n = l.substring(2);
- addDependency(n);
- }
+ public void saveDependencies(StringBuilder b) {
- public void loadPubapi(String l) {
- String pi = l.substring(2);
- addPubapi(pi);
- }
+ // Dependencies where *to* is among sources
+ for (String fullyQualifiedFrom : dependencies.keySet()) {
+ for (String fullyQualifiedTo : dependencies.get(fullyQualifiedFrom)) {
+ b.append(String.format("D S %s -> %s%n", fullyQualifiedFrom, fullyQualifiedTo));
+ }
+ }
- public void saveDependencies(StringBuilder b) {
- List<String> sorted_dependencies = new ArrayList<>();
- for (String key : dependencies) {
- sorted_dependencies.add(key);
- }
- Collections.sort(sorted_dependencies);
- for (String a : sorted_dependencies) {
- b.append("D "+a+"\n");
+ // Dependencies where *to* is on class path
+ for (String fullyQualifiedFrom : cpDependencies.keySet()) {
+ for (String fullyQualifiedTo : cpDependencies.get(fullyQualifiedFrom)) {
+ b.append(String.format("D C %s -> %s%n", fullyQualifiedFrom, fullyQualifiedTo));
+ }
}
}
public void savePubapi(StringBuilder b) {
- for (String l : pubapi) {
- b.append("I "+l+"\n");
- }
+ pubApi.asListOfStrings()
+ .stream()
+ .flatMap(l -> Stream.of("I ", l, "\n"))
+ .forEach(b::append);
}
public static void savePackages(Map<String,Package> packages, StringBuilder b) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012-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 com.sun.tools.sjavac;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileManager;
+
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.code.ClassFinder;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.sjavac.comp.PubapiVisitor;
+import com.sun.tools.sjavac.comp.SmartFileManager;
+import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
+
+public class PubApiExtractor {
+ // Setup a compiler context for finding classes in the classpath
+ // and to execute annotation processors.
+ Context context;
+ CompilationTask task;
+
+ /**
+ * Setup a compilation context, used for reading public apis of classes on the classpath
+ * as well as annotation processors.
+ */
+ public PubApiExtractor(Options options) {
+ JavacTool compiler = com.sun.tools.javac.api.JavacTool.create();
+ SmartFileManager fileManager = new SmartFileManager(compiler.getStandardFileManager(null, null, null));
+ context = new com.sun.tools.javac.util.Context();
+ String[] args = options.prepJavacArgs();
+ task = compiler.getTask(new PrintWriter(System.err),
+ fileManager,
+ null,
+ Arrays.asList(args),
+ null,
+ null,
+ context);
+ // Trigger a creation of the JavaCompiler, necessary to get a sourceCompleter for ClassFinder.
+ // The sourceCompleter is used for build situations where a classpath class references other classes
+ // that happens to be on the sourcepath.
+ JavaCompiler.instance(context);
+
+// context.put(JavaFileManager.class, fileManager);
+ }
+
+ public PubApi getPubApi(String fullyQualifiedClassName) {
+ ClassFinder cr = ClassFinder.instance(context);
+ Names ns = Names.instance(context);
+ Name n = ns.fromString(fullyQualifiedClassName);
+ ClassSymbol cs = cr.loadClass(n);
+ PubapiVisitor v = new PubapiVisitor();
+ v.visit(cs);
+ return v.getCollectedPubApi();
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -373,8 +373,6 @@
return currentModule;
}
- private static boolean gurka = false;
-
static private void scanDirectory(File dir, int rootPrefix, File root,
Set<String> suffixes,
List<String> excludes, List<String> includes,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -27,10 +27,11 @@
import java.io.PrintStream;
import java.net.URI;
+import java.util.Map;
import java.util.Set;
-import java.util.Map;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.Sjavac;
/**
@@ -89,8 +90,10 @@
Map<String,Set<String>> oldPackageDependencies,
URI destRoot,
Map<String,Set<URI>> packageArtifacts,
- Map<String,Set<String>> packageDependencies,
- Map<String,String> packagePublicApis,
+ Map<String, Map<String, Set<String>>> packageDependencies, // Package name -> Fully Qualified Type [from] -> Set of fully qualified type [to]
+ Map<String, Map<String, Set<String>>> packageCpDependencies, // Package name -> Fully Qualified Type [from] -> Set of fully qualified type [to]
+ Map<String, PubApi> packagePublicApis,
+ Map<String, PubApi> dependencyApis,
int debugLevel,
boolean incremental,
int numCores,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Fri Jun 12 16:40:05 2015 -0400
@@ -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,9 +30,13 @@
import java.io.StringWriter;
import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* Utilities.
@@ -107,6 +111,20 @@
}
/**
+ * Extract the package name from a fully qualified class name.
+ *
+ * Example: Given "pkg.subpkg.A" this method returns ":pkg.subpkg".
+ * Given "C" this method returns ":".
+ *
+ * @returns package name of the given class name
+ */
+ public static String pkgNameOfClassName(String fqClassName) {
+ int i = fqClassName.lastIndexOf('.');
+ String pkg = i == -1 ? "" : fqClassName.substring(0, i);
+ return ":" + pkg;
+ }
+
+ /**
* Clean out unwanted sub options supplied inside a primary option.
* For example to only had portfile remaining from:
* settings="--server:id=foo,portfile=bar"
@@ -183,6 +201,13 @@
return union;
}
+ public static <E> Set<E> subtract(Set<? extends E> orig,
+ Set<? extends E> toSubtract) {
+ Set<E> difference = new HashSet<>(orig);
+ difference.removeAll(toSubtract);
+ return difference;
+ }
+
public static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
@@ -193,4 +218,16 @@
public static File pathToFile(Path path) {
return path == null ? null : path.toFile();
}
+
+ public static <E> Set<E> intersection(Collection<? extends E> c1,
+ Collection<? extends E> c2) {
+ Set<E> intersection = new HashSet<E>(c1);
+ intersection.retainAll(c2);
+ return intersection;
+ }
+
+ public static <I, T> Map<I, T> indexBy(Collection<? extends T> c,
+ Function<? super T, ? extends I> indexFunction) {
+ return c.stream().collect(Collectors.<T, I, T>toMap(indexFunction, o -> o));
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -93,6 +93,11 @@
if (hdrdir != null && !createIfMissing(hdrdir))
return -1;
+ Log.debug("==========================================================");
+ Log.debug("Launching sjavac client with the following parameters:");
+ Log.debug(" " + options.getStateArgsString());
+ Log.debug("==========================================================");
+
// Load the prev build state database.
JavacState javac_state = JavacState.load(options, out, err);
@@ -167,6 +172,9 @@
javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
javac_state.setVisibleSources(sources_to_link_to);
+ int round = 0;
+ printRound(round);
+
// If there is any change in the source files, taint packages
// and mark the database in need of saving.
javac_state.checkSourceStatus(false);
@@ -188,6 +196,10 @@
// Go through all sources and taint all packages that miss artifacts.
javac_state.taintPackagesThatMissArtifacts();
+ // Check recorded classpath public apis. Taint packages that depend on
+ // classpath classes whose public apis have changed.
+ javac_state.taintPackagesDependingOnChangedClasspathPackages();
+
// Now clean out all known artifacts belonging to tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
// Copy files, for example property files, images files, xml files etc etc.
@@ -231,11 +243,22 @@
}
do {
+ if (round > 0)
+ printRound(round);
// Clean out artifacts in tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc);
- if (!rc[0]) break;
+ if (!rc[0]) {
+ Log.debug("Compilation failed.");
+ break;
+ }
+ if (!again) {
+ Log.debug("Nothing left to do.");
+ }
+ round++;
} while (again);
+ Log.debug("No need to do another round.");
+
// Only update the state if the compile went well.
if (rc[0]) {
javac_state.save();
@@ -323,4 +346,10 @@
}
}
+ private static void printRound(int round) {
+ Log.debug("****************************************");
+ Log.debug("* Round " + round + " *");
+ Log.debug("****************************************");
+ }
+
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 1999, 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 com.sun.tools.sjavac.comp;
-
-import javax.lang.model.element.Element;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Name;
-
-/** Utility class containing dependency information between packages
- * and the pubapi for a package.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Dependencies {
- protected static final Context.Key<Dependencies> dependenciesKey = new Context.Key<>();
-
- // The log to be used for error reporting.
- protected Log log;
- // Map from package name to packages that the package depends upon.
- protected Map<Name,Set<Name>> deps;
- // This is the set of all packages that are supplied
- // through the java files at the command line.
- protected Set<Name> explicitPackages;
-
- // Map from a package name to its public api.
- // Will the Name encode the module in the future?
- // If not, this will have to change to map from Module+Name to public api.
- protected Map<Name,StringBuffer> publicApiPerClass;
-
- public static Dependencies instance(Context context) {
- Dependencies instance = context.get(dependenciesKey);
- if (instance == null)
- instance = new Dependencies(context);
- return instance;
- }
-
- private Dependencies(Context context) {
- context.put(dependenciesKey, this);
- log = Log.instance(context);
- deps = new HashMap<>();
- explicitPackages = new HashSet<>();
- publicApiPerClass = new HashMap<>();
- }
-
- /**
- * Fetch the set of dependencies that are relevant to the compile
- * that has just been performed. I.e. we are only interested in
- * dependencies for classes that were explicitly compiled.
- * @return
- */
- public Map<String,Set<String>> getDependencies() {
- Map<String,Set<String>> new_deps = new HashMap<>();
- if (explicitPackages == null) return new_deps;
- for (Name pkg : explicitPackages) {
- Set<Name> set = deps.get(pkg);
- if (set != null) {
- Set<String> new_set = new_deps.get(pkg.toString());
- if (new_set == null) {
- new_set = new HashSet<>();
- // Modules beware....
- new_deps.put(":"+pkg.toString(), new_set);
- }
- for (Name d : set) {
- new_set.add(":"+d.toString());
- }
- }
- }
- return new_deps;
- }
-
- static class CompareNames implements Comparator<Name> {
- public int compare(Name a, Name b) {
- return a.toString().compareTo(b.toString());
- }
-
- }
-
- /**
- * Convert the map from class names to their pubapi to a map
- * from package names to their pubapi (which is the sorted concatenation
- * of all the class pubapis)
- */
- public Map<String,String> getPubapis() {
- Map<String,String> publicApiPerPackage = new HashMap<>();
- if (publicApiPerClass == null) return publicApiPerPackage;
- Name[] keys = publicApiPerClass.keySet().toArray(new Name[0]);
- Arrays.sort(keys, new CompareNames());
- StringBuffer newPublicApi = new StringBuffer();
- int i=0;
- String prevPkg = "";
- for (Name k : keys) {
- String cn = k.toString();
- String pn = "";
- int dp = cn.lastIndexOf('.');
- if (dp != -1) {
- pn = cn.substring(0,dp);
- }
- if (!pn.equals(prevPkg)) {
- if (!prevPkg.equals("")) {
- // Add default module name ":"
- publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
- }
- newPublicApi = new StringBuffer();
- prevPkg = pn;
- }
- newPublicApi.append(publicApiPerClass.get(k));
- i++;
- }
- if (!prevPkg.equals(""))
- publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
- return publicApiPerPackage;
- }
-
- /**
- * Visit the api of a class and construct a pubapi string and
- * store it into the pubapi_perclass map.
- */
- public void visitPubapi(Element e) {
- Name n = ((ClassSymbol)e).fullname;
- Name p = ((ClassSymbol)e).packge().fullname;
- StringBuffer sb = publicApiPerClass.get(n);
- Assert.check(sb == null);
- sb = new StringBuffer();
- PubapiVisitor v = new PubapiVisitor(sb);
- v.visit(e);
- if (sb.length()>0) {
- publicApiPerClass.put(n, sb);
- }
- explicitPackages.add(p);
- }
-
- /**
- * Collect a dependency. curr_pkg is marked as depending on dep_pkg.
- */
- public void collect(Name currPkg, Name depPkg) {
- if (!currPkg.equals(depPkg)) {
- Set<Name> theset = deps.get(currPkg);
- if (theset==null) {
- theset = new HashSet<>();
- deps.put(currPkg, theset);
- }
- theset.add(depPkg);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/FileObjectWithLocation.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.comp;
+
+import javax.tools.FileObject;
+import javax.tools.ForwardingFileObject;
+import javax.tools.JavaFileManager.Location;
+
+import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
+
+@Trusted
+public class FileObjectWithLocation<F extends FileObject> extends ForwardingFileObject<F> {
+
+ private final Location loc;
+
+ public FileObjectWithLocation(F delegate, Location loc) {
+ super(delegate);
+ this.loc = loc;
+ }
+
+ public Location getLocation() {
+ return loc;
+ }
+
+ public FileObject getDelegate() {
+ return fileObject;
+ }
+
+ public String toString() {
+ return "FileObjectWithLocation[" + fileObject + "]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaFileObjectWithLocation.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.comp;
+
+import javax.tools.ForwardingJavaFileObject;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
+
+@Trusted
+public class JavaFileObjectWithLocation<F extends JavaFileObject> extends ForwardingJavaFileObject<F> {
+
+ private final Location loc;
+
+ public JavaFileObjectWithLocation(F delegate, Location loc) {
+ super(delegate);
+ this.loc = loc;
+ }
+
+ public Location getLocation() {
+ return loc;
+ }
+
+ public F getDelegate() {
+ return fileObject;
+ }
+
+ public String toString() {
+ return "JavaFileObjectWithLocation[loc: " + loc + ", " + fileObject + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ return loc.hashCode() ^ fileObject.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JavaFileObjectWithLocation))
+ return false;
+ JavaFileObjectWithLocation<?> other = (JavaFileObjectWithLocation<?>) obj;
+ return loc.equals(other.loc) && fileObject.equals(other.fileObject);
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PathAndPackageVerifier.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PathAndPackageVerifier.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -41,6 +41,7 @@
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.Name;
+import com.sun.tools.sjavac.Log;
public class PathAndPackageVerifier implements TaskListener {
@@ -50,30 +51,37 @@
@Override
@DefinedBy(Api.COMPILER_TREE)
- public void started(TaskEvent e) {
+ public void finished(TaskEvent e) {
+ if (e.getKind() == TaskEvent.Kind.ANALYZE) {
+
+ CompilationUnitTree cu = e.getCompilationUnit();
+ if (cu == null)
+ return;
+
+ JavaFileObject jfo = cu.getSourceFile();
+ if (jfo == null)
+ return; // No source file -> package doesn't matter
+
+ JCTree pkg = (JCTree) cu.getPackageName();
+ if (pkg == null)
+ return; // Default package. See JDK-8048144.
+
+ Path dir = Paths.get(jfo.toUri()).normalize().getParent();
+ if (!checkPathAndPackage(dir, pkg))
+ misplacedCompilationUnits.add(cu);
+ }
+
+ if (e.getKind() == TaskEvent.Kind.COMPILATION) {
+ for (CompilationUnitTree cu : misplacedCompilationUnits) {
+ Log.error("Misplaced compilation unit.");
+ Log.error(" Directory: " + Paths.get(cu.getSourceFile().toUri()).getParent());
+ Log.error(" Package: " + cu.getPackageName());
+ }
+ }
}
- @Override
- @DefinedBy(Api.COMPILER_TREE)
- public void finished(TaskEvent e) {
- if (e.getKind() != TaskEvent.Kind.ANALYZE)
- return;
-
- CompilationUnitTree cu = e.getCompilationUnit();
- if (cu == null)
- return;
-
- JavaFileObject jfo = cu.getSourceFile();
- if (jfo == null)
- return; // No source file -> package doesn't matter
-
- JCTree pkg = (JCTree) cu.getPackageName();
- if (pkg == null)
- return; // Default package. See JDK-8048144.
-
- Path dir = Paths.get(jfo.toUri()).normalize().getParent();
- if (!checkPathAndPackage(dir, pkg))
- misplacedCompilationUnits.add(cu);
+ public boolean errorsDiscovered() {
+ return misplacedCompilationUnits.size() > 0;
}
/* Returns true if dir matches pkgName.
@@ -94,10 +102,6 @@
return !pkgIter.hasNext(); /*&& !pathIter.hasNext() See JDK-8059598 */
}
- public Set<CompilationUnitTree> getMisplacedCompilationUnits() {
- return misplacedCompilationUnits;
- }
-
/* Iterates over the names of the parents of the given path:
* Example: dir1/dir2/dir3 results in dir3 -> dir2 -> dir1
*/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -29,12 +29,9 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.server.CompilationResult;
@@ -58,28 +55,13 @@
public PooledSjavac(Sjavac delegate, int poolsize) {
Objects.requireNonNull(delegate);
this.delegate = delegate;
- pool = Executors.newFixedThreadPool(poolsize, new ThreadFactory() {
- AtomicInteger count = new AtomicInteger();
- @Override
- public Thread newThread(Runnable runnable) {
- String cls = PooledSjavac.class.getSimpleName();
- int num = count.incrementAndGet();
- Thread t = new Thread(runnable, cls + "-" + num);
- t.setDaemon(true);
- return t;
- }
- });
+ pool = Executors.newFixedThreadPool(poolsize);
}
@Override
public SysInfo getSysInfo() {
try {
- return pool.submit(new Callable<SysInfo>() {
- @Override
- public SysInfo call() throws Exception {
- return delegate.getSysInfo();
- }
- }).get();
+ return pool.submit(() -> delegate.getSysInfo()).get();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error during getSysInfo", e);
@@ -94,16 +76,13 @@
final Set<URI> sourcesToCompile,
final Set<URI> visibleSources) {
try {
- return pool.submit(new Callable<CompilationResult>() {
- @Override
- public CompilationResult call() throws Exception {
- return delegate.compile(protocolId,
- invocationId,
- args,
- explicitSources,
- sourcesToCompile,
- visibleSources);
- }
+ return pool.submit(() -> {
+ return delegate.compile(protocolId,
+ invocationId,
+ args,
+ explicitSources,
+ sourcesToCompile,
+ visibleSources);
}).get();
} catch (Exception e) {
e.printStackTrace();
@@ -113,6 +92,7 @@
@Override
public void shutdown() {
+ Log.debug("Shutting down PooledSjavac");
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
@@ -122,8 +102,6 @@
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
Log.error("ThreadPool did not terminate");
}
- // Grace period for thread termination
- Thread.sleep(1000);
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubAPIs.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,108 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.comp;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.lang.model.element.Element;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.sjavac.pubapi.PubApi;
+
+/**
+ * Utility class containing public API information.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class PubAPIs {
+ protected static final Context.Key<PubAPIs> pubApisKey = new Context.Key<>();
+
+ // The log to be used for error reporting.
+ protected Log log;
+
+ // Map from a class name to its public api.
+ // Will the Name encode the module in the future?
+ // If not, this will have to change to map from Module+Name to public api.
+ protected Map<ClassSymbol, PubApi> publicApiPerClass = new HashMap<>();
+
+ public static PubAPIs instance(Context context) {
+ PubAPIs instance = context.get(pubApisKey);
+ if (instance == null)
+ instance = new PubAPIs(context);
+ return instance;
+ }
+
+ private PubAPIs(Context context) {
+ context.put(pubApisKey, this);
+ log = Log.instance(context);
+ }
+
+ /**
+ * Convert the map from class names to their pubapi to a map
+ * from package names to their pubapi.
+ */
+ public Map<String, PubApi> getPubapis(Collection<JavaFileObject> explicitJFOs, boolean explicits) {
+
+ // Maps ":java.lang" to a package level pub api (with only types on top level)
+ Map<String, PubApi> result = new HashMap<>();
+ for (ClassSymbol cs : publicApiPerClass.keySet()) {
+
+ boolean amongExplicits = explicitJFOs.contains(cs.sourcefile);
+ if (explicits != amongExplicits)
+ continue;
+
+ String pkg = ":" + cs.packge().fullname;
+ PubApi currentPubApi = result.getOrDefault(pkg, new PubApi());
+ result.put(pkg, PubApi.mergeTypes(currentPubApi, publicApiPerClass.get(cs)));
+ }
+
+ return result;
+ }
+
+ /**
+ * Visit the api of a class and construct a pubapi and
+ * store it into the pubapi_perclass map.
+ */
+ @SuppressWarnings("deprecation")
+ public void visitPubapi(Element e) {
+
+ // Skip anonymous classes for now
+ if (e == null)
+ return;
+
+ PubapiVisitor v = new PubapiVisitor();
+ v.visit(e);
+ publicApiPerClass.put((ClassSymbol) e, v.getCollectedPubApi());
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -25,17 +25,28 @@
package com.sun.tools.sjavac.comp;
-import java.util.Iterator;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
import java.util.List;
-import javax.lang.model.element.Modifier;
+import java.util.stream.Collectors;
+
+import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementScanner9;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.sjavac.pubapi.PubApi;
+import com.sun.tools.sjavac.pubapi.PubApiTypeParam;
+import com.sun.tools.sjavac.pubapi.PubMethod;
+import com.sun.tools.sjavac.pubapi.PubType;
+import com.sun.tools.sjavac.pubapi.PubVar;
+import com.sun.tools.sjavac.pubapi.TypeDesc;
/** Utility class that constructs a textual representation
* of the public api of a class.
@@ -47,40 +58,67 @@
*/
public class PubapiVisitor extends ElementScanner9<Void, Void> {
- StringBuffer sb;
- // Important that it is 1! Part of protocol over wire, silly yes.
- // Fix please.
- int indent = 1;
+ private PubApi collectedApi = new PubApi();
- public PubapiVisitor(StringBuffer sb) {
- this.sb = sb;
- }
-
- String depth(int l) {
- return " ".substring(0, l);
+ private boolean isNonPrivate(Element e) {
+ return !e.getModifiers().contains(PRIVATE);
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Void visitType(TypeElement e, Void p) {
- if (e.getModifiers().contains(Modifier.PUBLIC)
- || e.getModifiers().contains(Modifier.PROTECTED))
- {
- sb.append(depth(indent) + "TYPE " + e.getQualifiedName() + "\n");
- indent += 2;
- Void v = super.visitType(e, p);
- indent -= 2;
- return v;
+ if (isNonPrivate(e)) {
+ PubApi prevApi = collectedApi;
+ collectedApi = new PubApi();
+ super.visitType(e, p);
+ if (!isAnonymous(e)) {
+ String name = ((ClassSymbol) e).flatname.toString();
+ PubType t = new PubType(e.getModifiers(),
+ name,
+ //e.getQualifiedName().toString(),
+ collectedApi);
+ prevApi.types.put(t.fqName, t);
+ }
+ collectedApi = prevApi;
}
return null;
}
+ private boolean isAnonymous(TypeElement e) {
+ return e.getQualifiedName().length() == 0;
+ }
+
+ private static String encodeChar(int c) {
+ return String.format("\\u%04x", c);
+ }
+
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Void visitVariable(VariableElement e, Void p) {
- if (e.getModifiers().contains(Modifier.PUBLIC)
- || e.getModifiers().contains(Modifier.PROTECTED)) {
- sb.append(depth(indent)).append("VAR ")
- .append(makeVariableString(e)).append("\n");
+ if (isNonPrivate(e)) {
+ Object constVal = e.getConstantValue();
+ String constValStr = null;
+ // TODO: This doesn't seem to be entirely accurate. What if I change
+ // from, say, 0 to 0L? (And the field is public final static so that
+ // it could get inlined.)
+ if (constVal != null) {
+ if (e.asType().toString().equals("char")) {
+ // What type is 'value'? Is it already a char?
+ char c = constVal.toString().charAt(0);
+ constValStr = "'" + encodeChar(c) + "'";
+ } else {
+ constValStr = constVal.toString()
+ .chars()
+ .mapToObj(PubapiVisitor::encodeChar)
+ .collect(Collectors.joining("", "\"", "\""));
+ }
+ }
+
+ PubVar v = new PubVar(e.getModifiers(),
+ TypeDesc.fromType(e.asType()),
+ e.toString(),
+ constValStr);
+ collectedApi.variables.put(v.identifier, v);
}
+
// Safe to not recurse here, because the only thing
// to visit here is the constructor of a variable declaration.
// If it happens to contain an anonymous inner class (which it might)
@@ -91,70 +129,38 @@
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Void visitExecutable(ExecutableElement e, Void p) {
- if (e.getModifiers().contains(Modifier.PUBLIC)
- || e.getModifiers().contains(Modifier.PROTECTED)) {
- sb.append(depth(indent)).append("METHOD ")
- .append(makeMethodString(e)).append("\n");
+ if (isNonPrivate(e)) {
+ PubMethod m = new PubMethod(e.getModifiers(),
+ getTypeParameters(e.getTypeParameters()),
+ TypeDesc.fromType(e.getReturnType()),
+ e.getSimpleName().toString(),
+ getTypeDescs(getParamTypes(e)),
+ getTypeDescs(e.getThrownTypes()));
+ collectedApi.methods.put(m.asSignatureString(), m);
}
return null;
}
- /**
- * Creates a String representation of a method element with everything
- * necessary to track all public aspects of it in an API.
- * @param e Element to create String for.
- * @return String representation of element.
- */
- protected String makeMethodString(ExecutableElement e) {
- StringBuilder result = new StringBuilder();
- for (Modifier modifier : e.getModifiers()) {
- result.append(modifier.toString());
- result.append(" ");
- }
- result.append(e.getReturnType().toString());
- result.append(" ");
- result.append(e.toString());
-
- List<? extends TypeMirror> thrownTypes = e.getThrownTypes();
- if (!thrownTypes.isEmpty()) {
- result.append(" throws ");
- for (Iterator<? extends TypeMirror> iterator = thrownTypes
- .iterator(); iterator.hasNext();) {
- TypeMirror typeMirror = iterator.next();
- result.append(typeMirror.toString());
- if (iterator.hasNext()) {
- result.append(", ");
- }
- }
- }
- return result.toString();
+ private List<PubApiTypeParam> getTypeParameters(List<? extends TypeParameterElement> elements) {
+ return elements.stream()
+ .map(e -> new PubApiTypeParam(e.getSimpleName().toString(), getTypeDescs(e.getBounds())))
+ .collect(Collectors.toList());
}
- /**
- * Creates a String representation of a variable element with everything
- * necessary to track all public aspects of it in an API.
- * @param e Element to create String for.
- * @return String representation of element.
- */
- protected String makeVariableString(VariableElement e) {
- StringBuilder result = new StringBuilder();
- for (Modifier modifier : e.getModifiers()) {
- result.append(modifier.toString());
- result.append(" ");
- }
- result.append(e.asType().toString());
- result.append(" ");
- result.append(e.toString());
- Object value = e.getConstantValue();
- if (value != null) {
- result.append(" = ");
- if (e.asType().toString().equals("char")) {
- int v = (int)value.toString().charAt(0);
- result.append("'\\u"+Integer.toString(v,16)+"'");
- } else {
- result.append(value.toString());
- }
- }
- return result.toString();
+ private List<TypeMirror> getParamTypes(ExecutableElement e) {
+ return e.getParameters()
+ .stream()
+ .map(VariableElement::asType)
+ .collect(Collectors.toList());
+ }
+
+ private List<TypeDesc> getTypeDescs(List<? extends TypeMirror> list) {
+ return list.stream()
+ .map(TypeDesc::fromType)
+ .collect(Collectors.toList());
+ }
+
+ public PubApi getCollectedPubApi() {
+ return collectedApi;
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -29,24 +29,25 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
-import java.nio.file.Paths;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
-import com.sun.source.tree.CompilationUnitTree;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Dependencies;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Options;
+import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.Util;
-import com.sun.tools.sjavac.comp.dependencies.DependencyCollector;
+import com.sun.tools.sjavac.comp.dependencies.NewDependencyCollector;
import com.sun.tools.sjavac.comp.dependencies.PublicApiCollector;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac;
@@ -76,86 +77,79 @@
List<File> explicitSources,
Set<URI> sourcesToCompile,
Set<URI> visibleSources) {
- JavacTool compiler = JavacTool.create();
- try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
- SmartFileManager smartFileManager = new SmartFileManager(fileManager);
+
+ JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler();
+ try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+ SmartFileManager sfm = new SmartFileManager(fm);
Context context = new Context();
- // Now setup the actual compilation....
+ Dependencies.GraphDependencies.preRegister(context);
+
+ // Now setup the actual compilation
CompilationResult compilationResult = new CompilationResult(0);
- // First deal with explicit source files on cmdline and in at file.
- ListBuffer<JavaFileObject> compilationUnits = new ListBuffer<>();
- for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) {
- compilationUnits.append(i);
+ // First deal with explicit source files on cmdline and in at file
+ ListBuffer<JavaFileObject> explicitJFOs = new ListBuffer<>();
+ for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(explicitSources)) {
+ explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH));
}
- // Now deal with sources supplied as source_to_compile.
+ // Now deal with sources supplied as source_to_compile
ListBuffer<File> sourcesToCompileFiles = new ListBuffer<>();
- for (URI u : sourcesToCompile) {
+ for (URI u : sourcesToCompile)
sourcesToCompileFiles.append(new File(u));
- }
- for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) {
- compilationUnits.append(i);
- }
- // Create a new logger.
+ for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles))
+ explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH));
+
+ // Create a new logger
StringWriter stdoutLog = new StringWriter();
StringWriter stderrLog = new StringWriter();
PrintWriter stdout = new PrintWriter(stdoutLog);
PrintWriter stderr = new PrintWriter(stderrLog);
com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK;
- DependencyCollector depsCollector = new DependencyCollector();
- PublicApiCollector pubApiCollector = new PublicApiCollector();
+ PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs);
PathAndPackageVerifier papVerifier = new PathAndPackageVerifier();
+ NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs);
try {
- if (compilationUnits.size() > 0) {
- smartFileManager.setVisibleSources(visibleSources);
- smartFileManager.cleanArtifacts();
- smartFileManager.setLog(stdout);
+ if (explicitJFOs.size() > 0) {
+ sfm.setVisibleSources(visibleSources);
+ sfm.cleanArtifacts();
+ sfm.setLog(stdout);
// Do the compilation!
JavacTaskImpl task =
(JavacTaskImpl) compiler.getTask(stderr,
- smartFileManager,
+ sfm,
null,
Arrays.asList(args),
null,
- compilationUnits,
+ explicitJFOs,
context);
- smartFileManager.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file"));
+ sfm.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file"));
task.addTaskListener(depsCollector);
task.addTaskListener(pubApiCollector);
task.addTaskListener(papVerifier);
+ logJavacInvocation(args);
rc = task.doCall();
- smartFileManager.flush();
+ Log.debug("javac returned with code " + rc);
+ sfm.flush();
}
} catch (Exception e) {
+ Log.error(Util.getStackTrace(e));
stderrLog.append(Util.getStackTrace(e));
rc = com.sun.tools.javac.main.Main.Result.ERROR;
}
- compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts();
+ compilationResult.packageArtifacts = sfm.getPackageArtifacts();
- Dependencies deps = Dependencies.instance(context);
- for (PackageSymbol from : depsCollector.getSourcePackages()) {
- for (PackageSymbol to : depsCollector.getDependenciesForPkg(from))
- deps.collect(from.fullname, to.fullname);
- }
-
- for (ClassSymbol cs : pubApiCollector.getClassSymbols())
- deps.visitPubapi(cs);
+ if (papVerifier.errorsDiscovered())
+ rc = com.sun.tools.javac.main.Main.Result.ERROR;
- if (papVerifier.getMisplacedCompilationUnits().size() > 0) {
- for (CompilationUnitTree cu : papVerifier.getMisplacedCompilationUnits()) {
- System.err.println("Misplaced compilation unit.");
- System.err.println(" Directory: " + Paths.get(cu.getSourceFile().toUri()).getParent());
- System.err.println(" Package: " + cu.getPackageName());
- }
- rc = com.sun.tools.javac.main.Main.Result.ERROR;
- }
+ compilationResult.packageDependencies = depsCollector.getDependencies(false);
+ compilationResult.packageCpDependencies = depsCollector.getDependencies(true);
- compilationResult.packageDependencies = deps.getDependencies();
- compilationResult.packagePubapis = deps.getPubapis();
+ compilationResult.packagePubapis = pubApiCollector.getPubApis(true); // pubApis.getPubapis(explicitJFOs, true);
+ compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); // pubApis.getPubapis(explicitJFOs, false);
compilationResult.stdout = stdoutLog.toString();
compilationResult.stderr = stderrLog.toString();
compilationResult.returnCode = rc.exitCode;
@@ -172,10 +166,22 @@
// ... maybe we should wait for any current request to finish?
}
-
@Override
public String serverSettings() {
return "";
}
+ private void logJavacInvocation(String[] args) {
+ Log.debug("Invoking javac with args");
+ Iterator<String> argIter = Arrays.asList(args).iterator();
+ while (argIter.hasNext()) {
+ String arg = argIter.next();
+ String line = " " + arg;
+ if (arg.matches("\\-(d|cp|classpath|sourcepath|source|target)")
+ && argIter.hasNext()) {
+ line += " " + argIter.next();
+ }
+ Log.debug(line);
+ }
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -91,6 +91,12 @@
((JavacFileManager) fileManager).setSymbolFileEnabled(b);
}
+ @DefinedBy(Api.COMPILER)
+ public String inferBinaryName(Location location, JavaFileObject file) {
+ return super.inferBinaryName(location, locUnwrap(file));
+ }
+
+
public Map<String,Set<URI>> getPackageArtifacts() {
return packageArtifacts;
}
@@ -100,10 +106,11 @@
String packageName,
Set<Kind> kinds,
boolean recurse) throws IOException {
+ // TODO: Do this lazily by returning an iterable with a filtering Iterator
// Acquire the list of files.
Iterable<JavaFileObject> files = super.list(location, packageName, kinds, recurse);
if (visibleSources.isEmpty()) {
- return files;
+ return locWrapMany(files, location);
}
// Now filter!
ListBuffer<JavaFileObject> filteredFiles = new ListBuffer<>();
@@ -116,12 +123,8 @@
filteredFiles.add(f);
}
}
- return filteredFiles;
- }
- @Override @DefinedBy(Api.COMPILER)
- public boolean hasLocation(Location location) {
- return super.hasLocation(location);
+ return locWrapMany(filteredFiles, location);
}
@Override @DefinedBy(Api.COMPILER)
@@ -129,6 +132,7 @@
String className,
Kind kind) throws IOException {
JavaFileObject file = super.getJavaFileForInput(location, className, kind);
+ file = locWrap(file, location);
if (file == null || visibleSources.isEmpty()) {
return file;
}
@@ -145,6 +149,7 @@
Kind kind,
FileObject sibling) throws IOException {
JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling);
+ file = locWrap(file, location);
if (file == null) return file;
int dp = className.lastIndexOf('.');
String pkg_name = "";
@@ -162,6 +167,7 @@
String packageName,
String relativeName) throws IOException {
FileObject file = super.getFileForInput(location, packageName, relativeName);
+ file = locWrap(file, location);
if (file == null || visibleSources.isEmpty()) {
return file;
}
@@ -177,11 +183,12 @@
String packageName,
String relativeName,
FileObject sibling) throws IOException {
- FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling);
+ FileObject superFile = super.getFileForOutput(location, packageName, relativeName, sibling);
+ FileObject file = locWrap(superFile, location);
if (file == null) return file;
- if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) &&
- file instanceof JavaFileObject) {
- file = new SmartFileObject((JavaFileObject)file, stdout);
+
+ if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && superFile instanceof JavaFileObject) {
+ file = new SmartFileObject((JavaFileObject) file, stdout);
packageName = ":" + packageNameFromFileName(relativeName);
}
if (packageName.equals("")) {
@@ -191,7 +198,7 @@
return file;
}
- private String packageNameFromFileName(String fn) {
+ private static String packageNameFromFileName(String fn) {
StringBuilder sb = new StringBuilder();
int p = fn.indexOf('_'), pp = 0;
while (p != -1) {
@@ -204,16 +211,6 @@
return sb.toString();
}
- @Override @DefinedBy(Api.COMPILER)
- public void flush() throws IOException {
- super.flush();
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public void close() throws IOException {
- super.close();
- }
-
void addArtifact(String pkgName, URI art) {
Set<URI> s = packageArtifacts.get(pkgName);
if (s == null) {
@@ -222,4 +219,50 @@
}
s.add(art);
}
+
+ public static JavaFileObject locWrap(JavaFileObject jfo, Location loc) {
+
+ // From sjavac's perspective platform classes are not interesting and
+ // there is no need to track the location for these file objects.
+ // Also, there exists some jfo instanceof checks which breaks if
+ // the jfos for platform classes are wrapped.
+ if (loc == StandardLocation.PLATFORM_CLASS_PATH)
+ return jfo;
+
+ return jfo == null ? null : new JavaFileObjectWithLocation<>(jfo, loc);
+ }
+
+ private static FileObject locWrap(FileObject fo, Location loc) {
+ if (fo instanceof JavaFileObject)
+ return locWrap((JavaFileObject) fo, loc);
+ return fo == null ? null : new FileObjectWithLocation<>(fo, loc);
+ }
+
+ @DefinedBy(Api.COMPILER)
+ @Override
+ public boolean isSameFile(FileObject a, FileObject b) {
+ return super.isSameFile(locUnwrap(a), locUnwrap(b));
+ }
+
+ private static ListBuffer<JavaFileObject> locWrapMany(Iterable<JavaFileObject> jfos,
+ Location loc) {
+ ListBuffer<JavaFileObject> locWrapped = new ListBuffer<>();
+ for (JavaFileObject f : jfos)
+ locWrapped.add(locWrap(f, loc));
+ return locWrapped;
+ }
+
+ private static FileObject locUnwrap(FileObject fo) {
+ if (fo instanceof FileObjectWithLocation<?>)
+ return ((FileObjectWithLocation<?>) fo).getDelegate();
+ if (fo instanceof JavaFileObjectWithLocation<?>)
+ return ((JavaFileObjectWithLocation<?>) fo).getDelegate();
+ return fo;
+ }
+
+ private static JavaFileObject locUnwrap(JavaFileObject fo) {
+ if (fo instanceof JavaFileObjectWithLocation<?>)
+ return ((JavaFileObjectWithLocation<?>) fo).getDelegate();
+ return fo;
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/Dependency.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * 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 com.sun.tools.sjavac.comp.dependencies;
-
-import java.util.Set;
-
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-
-interface Dependency {
- Set<PackageSymbol> getPackages();
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/DependencyCollector.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * 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 com.sun.tools.sjavac.comp.dependencies;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.sjavac.Util;
-
-public class DependencyCollector implements TaskListener {
-
- Map<PackageSymbol, Set<PackageSymbol>> collectedDependencies = new HashMap<>();
-
- @Override
- @DefinedBy(Api.COMPILER_TREE)
- public void started(TaskEvent e) {
- }
-
- @Override
- @DefinedBy(Api.COMPILER_TREE)
- public void finished(TaskEvent e) {
- if (e.getKind() == TaskEvent.Kind.ANALYZE) {
- JCCompilationUnit cu = (JCCompilationUnit) e.getCompilationUnit();
- PackageSymbol thisPkg = cu.packge;
- if (thisPkg == null) {
- // Compilation unit in default package. See JDK-8048144.
- return;
- }
- DependencyScanner ds = new DependencyScanner();
- cu.accept(ds);
- Set<PackageSymbol> pkgDeps = ds.getResult()
- .stream()
- .flatMap(dep -> dep.getPackages().stream())
- .collect(Collectors.toSet());
- collectedDependencies.merge(thisPkg, pkgDeps, Util::union);
- }
- }
-
- public Set<PackageSymbol> getSourcePackages() {
- return collectedDependencies.keySet();
- }
-
- public Set<PackageSymbol> getDependenciesForPkg(PackageSymbol ps) {
- return collectedDependencies.get(ps);
- }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/DependencyScanner.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * 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 com.sun.tools.sjavac.comp.dependencies;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCIdent;
-import com.sun.tools.javac.tree.TreeScanner;
-
-class DependencyScanner extends TreeScanner {
-
- public final Set<Dependency> dependencies = new HashSet<>();
-
- private boolean isValidDependency(Type t) {
- if (t == null || t.isPrimitiveOrVoid() || t.isErroneous())
- return false;
- TypeTag tag = t.getTag();
- return tag != TypeTag.PACKAGE
- && tag != TypeTag.METHOD
- && tag != TypeTag.ARRAY
- && tag != TypeTag.TYPEVAR;
- }
-
- @Override
- public void visitIdent(JCIdent tree) {
- if (isValidDependency(tree.type))
- dependencies.add(new TypeAndSupertypesDependency(tree.type.tsym));
- super.visitIdent(tree);
- }
-
- @Override
- public void visitSelect(JCFieldAccess tree) {
- if (tree.getIdentifier().contentEquals("*")) {
- Symbol sym = tree.selected instanceof JCIdent ? ((JCIdent) tree.selected).sym
- : ((JCFieldAccess) tree.selected).sym;
- if (sym instanceof ClassSymbol) {
- ClassSymbol clsSym = (ClassSymbol) sym;
- dependencies.add(new TypeAndSupertypesDependency(clsSym.type.tsym));
- } else {
- dependencies.add(new PackageDependency((PackageSymbol) sym));
- }
- } else if (tree.type != null && tree.type.hasTag(TypeTag.METHOD)) { // Method call? Depend on the result (even though we never access it elsewhere)
- Type retType = tree.type.getReturnType();
- if (isValidDependency(retType))
- dependencies.add(new TypeAndSupertypesDependency(retType.tsym));
- } else if (isValidDependency(tree.type)) {
- dependencies.add(new TypeAndSupertypesDependency(tree.type.tsym));
- }
- super.visitSelect(tree);
- }
-
- public Set<Dependency> getResult() {
- return dependencies;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/NewDependencyCollector.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,158 @@
+/*
+ * 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 com.sun.tools.sjavac.comp.dependencies;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Dependencies.GraphDependencies;
+import com.sun.tools.javac.util.Dependencies.GraphDependencies.CompletionNode;
+import com.sun.tools.javac.util.GraphUtils.Node;
+import com.sun.tools.sjavac.Util;
+import com.sun.tools.sjavac.comp.JavaFileObjectWithLocation;
+import com.sun.tools.sjavac.comp.PubAPIs;
+
+
+public class NewDependencyCollector implements TaskListener {
+
+ private final Context context;
+ private final Collection<JavaFileObject> explicitJFOs;
+
+ private Map<String, Map<String, Set<String>>> deps;
+ private Map<String, Map<String, Set<String>>> cpDeps;
+
+ public NewDependencyCollector(Context context,
+ Collection<JavaFileObject> explicitJFOs) {
+ this.context = context;
+ this.explicitJFOs = explicitJFOs;
+ }
+
+ @Override
+ @DefinedBy(Api.COMPILER_TREE)
+ public void finished(TaskEvent e) {
+ if (e.getKind() == TaskEvent.Kind.COMPILATION) {
+ collectPubApisOfDependencies(context, explicitJFOs);
+ deps = getDependencies(context, explicitJFOs, false);
+ cpDeps = getDependencies(context, explicitJFOs, true);
+ }
+ }
+
+ public Map<String, Map<String, Set<String>>> getDependencies(boolean cp) {
+ return cp ? cpDeps : deps;
+ }
+
+ private Set<CompletionNode> getDependencyNodes(Context context,
+ Collection<JavaFileObject> explicitJFOs,
+ boolean explicits) {
+ GraphDependencies deps = (GraphDependencies) GraphDependencies.instance(context);
+
+ return deps.getNodes()
+ .stream()
+ .filter(n -> n instanceof CompletionNode)
+ .map(n -> (CompletionNode) n)
+ .filter(n -> n.getClassSymbol().fullname != null)
+ .filter(n -> explicits == explicitJFOs.contains(n.getClassSymbol().classfile))
+ .collect(Collectors.toSet());
+ }
+
+ private void collectPubApisOfDependencies(Context context,
+ Collection<JavaFileObject> explicitJFOs) {
+ PubAPIs pubApis = PubAPIs.instance(context);
+ for (CompletionNode cDepNode : getDependencyNodes(context, explicitJFOs, false)) {
+ ClassSymbol cs = cDepNode.getClassSymbol().outermostClass();
+ Location loc = getLocationOf(cs);
+ // We're completely ignorant of PLATFORM_CLASS_PATH classes
+ if (loc == StandardLocation.CLASS_PATH || loc == StandardLocation.SOURCE_PATH)
+ pubApis.visitPubapi(cs);
+ }
+ }
+
+ private Location getLocationOf(ClassSymbol cs) {
+ JavaFileObject jfo = cs.outermostClass().classfile;
+ if (jfo instanceof JavaFileObjectWithLocation) {
+ return ((JavaFileObjectWithLocation<?>) jfo).getLocation();
+ }
+
+ // jfo is most likely on PLATFORM_CLASS_PATH.
+ // See notes in SmartFileManager::locWrap
+
+ return null;
+ }
+
+ // :Package -> fully qualified class name [from] -> set of fully qualified class names [to]
+ private Map<String, Map<String, Set<String>>> getDependencies(Context context,
+ Collection<JavaFileObject> explicitJFOs,
+ boolean cp) {
+ Map<String, Map<String, Set<String>>> result = new HashMap<>();
+
+ for (CompletionNode cnode : getDependencyNodes(context, explicitJFOs, true)) {
+
+ String fqDep = cnode.getClassSymbol().outermostClass().flatname.toString();
+ String depPkg = Util.pkgNameOfClassName(fqDep);
+
+ Map<String, Set<String>> depsForThisClass = result.get(depPkg);
+ if (depsForThisClass == null)
+ result.put(depPkg, depsForThisClass = new HashMap<>());
+
+ for (Node<?,?> depNode : cnode.getDependenciesByKind(GraphDependencies.Node.DependencyKind.REQUIRES)) {
+ boolean isCompletionNode = depNode instanceof CompletionNode;
+ if (isCompletionNode) {
+ CompletionNode cDepNode = (CompletionNode) depNode;
+ if (cDepNode == cnode)
+ continue;
+ if (cDepNode.getClassSymbol().fullname == null) // Anonymous class
+ continue;
+ Location depLoc = getLocationOf(cDepNode.getClassSymbol());
+ boolean relevant = (cp && depLoc == StandardLocation.CLASS_PATH)
+ || (!cp && depLoc == StandardLocation.SOURCE_PATH);
+ if (!relevant)
+ continue;
+
+ Set<String> fqDeps = depsForThisClass.get(fqDep);
+ if (fqDeps == null)
+ depsForThisClass.put(fqDep, fqDeps = new HashSet<>());
+ fqDeps.add(cDepNode.getClassSymbol().outermostClass().flatname.toString());
+ }
+ }
+ }
+ return result;
+ }
+
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/PackageDependency.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * 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 com.sun.tools.sjavac.comp.dependencies;
-
-import java.util.Collections;
-import java.util.Set;
-
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-
-public class PackageDependency implements Dependency {
- PackageSymbol ps;
- public PackageDependency(PackageSymbol ps) {
- this.ps = ps;
- }
- @Override
- public Set<PackageSymbol> getPackages() {
- return Collections.singleton(ps);
- }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/PublicApiCollector.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/PublicApiCollector.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -22,40 +22,91 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp.dependencies;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
+import javax.tools.JavaFileObject;
+
import com.sun.source.tree.Tree;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.sjavac.Log;
+import com.sun.tools.sjavac.comp.PubAPIs;
+import com.sun.tools.sjavac.pubapi.PubApi;
+
public class PublicApiCollector implements TaskListener {
- final Set<ClassSymbol> classSymbols = new HashSet<>();
+ private Context context;
+ private final Set<ClassSymbol> classSymbols = new HashSet<>();
+ private final Collection<JavaFileObject> explicitJFOs;
- @Override
- @DefinedBy(Api.COMPILER_TREE)
- public void started(TaskEvent e) {
+ // Result collected upon compilation task finished
+ private Map<String, PubApi> explicitPubApis;
+ private Map<String, PubApi> nonExplicitPubApis;
+
+ public PublicApiCollector(Context context,
+ Collection<JavaFileObject> explicitJFOs) {
+ this.context = context;
+ this.explicitJFOs = explicitJFOs;
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public void finished(TaskEvent e) {
- if (e.getKind() == TaskEvent.Kind.ANALYZE) {
- for (Tree t : e.getCompilationUnit().getTypeDecls()) {
- if (t instanceof JCClassDecl) // Can also be a JCSkip
- classSymbols.add(((JCClassDecl) t).sym);
- }
+ switch (e.getKind()) {
+ case ANALYZE:
+ collectClassSymbols((JCCompilationUnit) e.getCompilationUnit());
+ break;
+ case COMPILATION:
+ Log.debug("Compilation finished");
+ Log.debug("Extracting pub APIs for the following symbols:");
+ for (ClassSymbol cs : classSymbols)
+ Log.debug(" " + cs.fullname);
+ extractPubApis();
+
+ // Save result for later retrieval. (Important that we do this
+ // before we return from this method, because we may not access
+ // symbols after compilation is finished.)
+ PubAPIs pa = PubAPIs.instance(context);
+ explicitPubApis = pa.getPubapis(explicitJFOs, true);
+ nonExplicitPubApis = pa.getPubapis(explicitJFOs, false);
+
+ Log.debug("done");
+ break;
}
}
- public Set<ClassSymbol> getClassSymbols() {
- return classSymbols;
+ private void collectClassSymbols(JCCompilationUnit cu) {
+ for (Tree t : cu.getTypeDecls()) {
+ if (t instanceof JCClassDecl) // Can also be a JCSkip
+ classSymbols.add(((JCClassDecl) t).sym);
+ }
+ }
+
+ private void extractPubApis() {
+ // To handle incremental builds (subsequent sjavac invocations) we need
+ // to keep track of the public API of what we depend upon.
+ //
+ // During the recompilation loop (within a single sjavac invocation) we
+ // need to keep track of public API of what we're compiling to decide if
+ // any dependants needs to be tainted.
+ PubAPIs pubApis = PubAPIs.instance(context);
+ classSymbols.forEach(pubApis::visitPubapi);
+ }
+
+ public Map<String, PubApi> getPubApis(boolean explicit) {
+ return explicit ? explicitPubApis : nonExplicitPubApis;
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/TypeAndSupertypesDependency.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * 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 com.sun.tools.sjavac.comp.dependencies;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.code.Symbol.TypeSymbol;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.Type;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-public class TypeAndSupertypesDependency implements Dependency {
-
- protected TypeSymbol type;
-
- public TypeAndSupertypesDependency(TypeSymbol type) {
- this.type = Objects.requireNonNull(type);
- }
-
- private Set<TypeSymbol> allSupertypes(TypeSymbol t) {
- if (t == null)
- return Collections.emptySet();
- Set<TypeSymbol> result = new HashSet<>();
- result.add(t);
- if (t instanceof ClassSymbol) {
- ClassSymbol cs = (ClassSymbol) t;
- result.addAll(allSupertypes(cs.getSuperclass().tsym));
- for (Type it : cs.getInterfaces())
- result.addAll(allSupertypes(it.tsym));
- }
- return result;
- }
-
- @Override
- public Set<PackageSymbol> getPackages() {
- if (type.kind == ERR)
- return Collections.emptySet();
- if (type instanceof ClassSymbol) {
- return allSupertypes(type).stream()
- .map(TypeSymbol::packge)
- .collect(Collectors.toSet());
- }
- throw new AssertionError("Could not get package name for " + type);
- }
-}
-
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Fri Jun 12 16:40:05 2015 -0400
@@ -316,9 +316,19 @@
args.add(concatenateSourceLocations(classSearchPaths));
}
+ // Enable dependency generation
+ args.add("-XDcompletionDeps=source,class");
+
// This can't be anything but 'none'. Enforced by sjavac main method.
args.add("-implicit:" + implicitPolicy);
+ // If this option is not used, Object for instance is erroneously
+ // picked up from PLATFORM_CLASS_PATH instead of CLASS_PATH.
+ //
+ // Discussing this further led to the decision of letting bootclasspath
+ // be a dummy (empty) directory when building the JDK.
+ //args.add("-XXuserPathsFirst");
+
// Append javac-options (i.e. pass through options not recognized by
// sjavac to javac.)
args.addAll(javacArgs);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ArrayTypeDesc.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+
+import javax.lang.model.type.TypeKind;
+
+public class ArrayTypeDesc extends TypeDesc implements Serializable {
+
+ private static final long serialVersionUID = -1177329549163314996L;
+
+ TypeDesc compTypeDesc;
+
+ public ArrayTypeDesc(TypeDesc compTypeDesc) {
+ super(TypeKind.ARRAY);
+ this.compTypeDesc = compTypeDesc;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj))
+ return false;
+ return compTypeDesc.equals(((ArrayTypeDesc) obj).compTypeDesc);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ compTypeDesc.hashCode();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PrimitiveTypeDesc.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,49 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+
+import javax.lang.model.type.TypeKind;
+
+import com.sun.tools.javac.util.StringUtils;
+
+public class PrimitiveTypeDesc extends TypeDesc implements Serializable {
+
+ private static final long serialVersionUID = 6051065543149129106L;
+
+ public PrimitiveTypeDesc(TypeKind typeKind) {
+ super(typeKind);
+ if (!typeKind.isPrimitive() && typeKind != TypeKind.VOID)
+ throw new IllegalArgumentException("Only primitives or void accepted");
+ }
+
+ // This class has no fields, so the inherited hashCode and equals should do fine.
+
+ @Override
+ public String toString() {
+ return StringUtils.toLowerCase(typeKind.toString());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApi.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,434 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+
+import static com.sun.tools.sjavac.Util.union;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.lang.model.element.Modifier;
+
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.StringUtils;
+
+public class PubApi implements Serializable {
+
+ private static final long serialVersionUID = 5926627347801986850L;
+
+ // Used to have Set here. Problem is that the objects are mutated during
+ // javac_state loading, causing them to change hash codes. We could probably
+ // change back to Set once javac_state loading is cleaned up.
+ public final Map<String, PubType> types = new HashMap<>();
+ public final Map<String, PubVar> variables = new HashMap<>();
+ public final Map<String, PubMethod> methods = new HashMap<>();
+
+ public PubApi() {
+ }
+
+ public PubApi(Collection<PubType> types,
+ Collection<PubVar> variables,
+ Collection<PubMethod> methods) {
+ types.forEach(this::addPubType);
+ variables.forEach(this::addPubVar);
+ methods.forEach(this::addPubMethod);
+ }
+
+ // Currently this is implemented as equality. This is far from optimal. It
+ // should preferably make sure that all previous methods are still available
+ // and no abstract methods are added. It should also be aware of inheritance
+ // of course.
+ public boolean isBackwardCompatibleWith(PubApi older) {
+ return equals(older);
+ }
+
+ private static String typeLine(PubType type) {
+ if (type.fqName.isEmpty())
+ throw new RuntimeException("empty class name " + type);
+ return String.format("TYPE %s%s", asString(type.modifiers), type.fqName);
+ }
+
+ private static String varLine(PubVar var) {
+ return String.format("VAR %s%s %s%s",
+ asString(var.modifiers),
+ TypeDesc.encodeAsString(var.type),
+ var.identifier,
+ var.getConstValue().map(v -> " = " + v).orElse(""));
+ }
+
+ private static String methodLine(PubMethod method) {
+ return String.format("METHOD %s%s%s %s(%s)%s",
+ asString(method.modifiers),
+ method.typeParams.isEmpty() ? "" : ("<" + method.typeParams.stream().map(PubApiTypeParam::asString).collect(Collectors.joining(",")) + "> "),
+ TypeDesc.encodeAsString(method.returnType),
+ method.identifier,
+ commaSeparated(method.paramTypes),
+ method.throwDecls.isEmpty()
+ ? ""
+ : " throws " + commaSeparated(method.throwDecls));
+ }
+
+ public List<String> asListOfStrings() {
+ List<String> lines = new ArrayList<>();
+
+ // Types
+ types.values()
+ .stream()
+ .sorted(Comparator.comparing(PubApi::typeLine))
+ .forEach(type -> {
+ lines.add(typeLine(type));
+ for (String subline : type.pubApi.asListOfStrings())
+ lines.add(" " + subline);
+ });
+
+ // Variables
+ variables.values()
+ .stream()
+ .map(PubApi::varLine)
+ .sorted()
+ .forEach(lines::add);
+
+ // Methods
+ methods.values()
+ .stream()
+ .map(PubApi::methodLine)
+ .sorted()
+ .forEach(lines::add);
+
+ return lines;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ PubApi other = (PubApi) obj;
+ return types.equals(other.types)
+ && variables.equals(other.variables)
+ && methods.equals(other.methods);
+ }
+
+ @Override
+ public int hashCode() {
+ return types.keySet().hashCode()
+ ^ variables.keySet().hashCode()
+ ^ methods.keySet().hashCode();
+ }
+
+ private static String commaSeparated(List<TypeDesc> typeDescs) {
+ return typeDescs.stream()
+ .map(TypeDesc::encodeAsString)
+ .collect(Collectors.joining(","));
+ }
+
+ // Create space separated list of modifiers (with a trailing space)
+ private static String asString(Set<Modifier> modifiers) {
+ return modifiers.stream()
+ .map(mod -> mod + " ")
+ .sorted()
+ .collect(Collectors.joining());
+ }
+
+ // Used to combine class PubApis to package level PubApis
+ public static PubApi mergeTypes(PubApi api1, PubApi api2) {
+ Assert.check(api1.methods.isEmpty(), "Can only merge types.");
+ Assert.check(api2.methods.isEmpty(), "Can only merge types.");
+ Assert.check(api1.variables.isEmpty(), "Can only merge types.");
+ Assert.check(api2.variables.isEmpty(), "Can only merge types.");
+ PubApi merged = new PubApi();
+ merged.types.putAll(api1.types);
+ merged.types.putAll(api2.types);
+ return merged;
+ }
+
+
+ // Used for line-by-line parsing
+ private PubType lastInsertedType = null;
+
+ private final static String MODIFIERS = Stream.of(Modifier.values())
+ .map(Modifier::name)
+ .map(StringUtils::toLowerCase)
+ .collect(Collectors.joining("|", "(", ")"));
+
+ private final static Pattern MOD_PATTERN = Pattern.compile("(" + MODIFIERS + " )*");
+ private final static Pattern METHOD_PATTERN = Pattern.compile("(?<ret>.+?) (?<name>\\S+)\\((?<params>.*)\\)( throws (?<throws>.*))?");
+ private final static Pattern VAR_PATTERN = Pattern.compile("VAR (?<modifiers>("+MODIFIERS+" )*)(?<type>.+?) (?<id>\\S+)( = (?<val>.*))?");
+ private final static Pattern TYPE_PATTERN = Pattern.compile("TYPE (?<modifiers>("+MODIFIERS+" )*)(?<fullyQualified>\\S+)");
+
+ public void appendItem(String l) {
+ try {
+ if (l.startsWith(" ")) {
+ lastInsertedType.pubApi.appendItem(l.substring(2));
+ return;
+ }
+
+ if (l.startsWith("METHOD")) {
+ l = l.substring("METHOD ".length());
+ Set<Modifier> modifiers = new HashSet<>();
+ Matcher modMatcher = MOD_PATTERN.matcher(l);
+ if (modMatcher.find()) {
+ String modifiersStr = modMatcher.group();
+ modifiers.addAll(parseModifiers(modifiersStr));
+ l = l.substring(modifiersStr.length());
+ }
+ List<PubApiTypeParam> typeParams = new ArrayList<>();
+ if (l.startsWith("<")) {
+ int closingPos = findClosingTag(l, 0);
+ String str = l.substring(1, closingPos);
+ l = l.substring(closingPos+1);
+ typeParams.addAll(parseTypeParams(splitOnTopLevelCommas(str)));
+ }
+ Matcher mm = METHOD_PATTERN.matcher(l);
+ if (!mm.matches())
+ throw new AssertionError("Could not parse return type, identifier, parameter types or throws declaration of method: " + l);
+
+ List<String> params = splitOnTopLevelCommas(mm.group("params"));
+ String th = Optional.ofNullable(mm.group("throws")).orElse("");
+ List<String> throwz = splitOnTopLevelCommas(th);
+ PubMethod m = new PubMethod(modifiers,
+ typeParams,
+ TypeDesc.decodeString(mm.group("ret")),
+ mm.group("name"),
+ parseTypeDescs(params),
+ parseTypeDescs(throwz));
+ addPubMethod(m);
+ return;
+ }
+
+ Matcher vm = VAR_PATTERN.matcher(l);
+ if (vm.matches()) {
+ addPubVar(new PubVar(parseModifiers(vm.group("modifiers")),
+ TypeDesc.decodeString(vm.group("type")),
+ vm.group("id"),
+ vm.group("val")));
+ return;
+ }
+
+ Matcher tm = TYPE_PATTERN.matcher(l);
+ if (tm.matches()) {
+ addPubType(new PubType(parseModifiers(tm.group("modifiers")),
+ tm.group("fullyQualified"),
+ new PubApi()));
+ return;
+ }
+
+ throw new AssertionError("No matching line pattern.");
+ } catch (Throwable e) {
+ throw new AssertionError("Could not parse API line: " + l, e);
+ }
+ }
+
+ public void addPubType(PubType t) {
+ types.put(t.fqName, t);
+ lastInsertedType = t;
+ }
+
+ public void addPubVar(PubVar v) {
+ variables.put(v.identifier, v);
+ }
+
+ public void addPubMethod(PubMethod m) {
+ methods.put(m.asSignatureString(), m);
+ }
+
+ private static List<TypeDesc> parseTypeDescs(List<String> strs) {
+ return strs.stream()
+ .map(TypeDesc::decodeString)
+ .collect(Collectors.toList());
+ }
+
+ private static List<PubApiTypeParam> parseTypeParams(List<String> strs) {
+ return strs.stream().map(PubApi::parseTypeParam).collect(Collectors.toList());
+ }
+
+ // Parse a type parameter string. Example input:
+ // identifier
+ // identifier extends Type (& Type)*
+ private static PubApiTypeParam parseTypeParam(String typeParamString) {
+ int extPos = typeParamString.indexOf(" extends ");
+ if (extPos == -1)
+ return new PubApiTypeParam(typeParamString, Collections.emptyList());
+ String identifier = typeParamString.substring(0, extPos);
+ String rest = typeParamString.substring(extPos + " extends ".length());
+ List<TypeDesc> bounds = parseTypeDescs(splitOnTopLevelChars(rest, '&'));
+ return new PubApiTypeParam(identifier, bounds);
+ }
+
+ public Set<Modifier> parseModifiers(String modifiers) {
+ if (modifiers == null)
+ return Collections.emptySet();
+ return Stream.of(modifiers.split(" "))
+ .map(String::trim)
+ .map(StringUtils::toUpperCase)
+ .filter(s -> !s.isEmpty())
+ .map(Modifier::valueOf)
+ .collect(Collectors.toSet());
+ }
+
+ // Find closing tag of the opening tag at the given 'pos'.
+ private static int findClosingTag(String l, int pos) {
+ while (true) {
+ pos = pos + 1;
+ if (l.charAt(pos) == '>')
+ return pos;
+ if (l.charAt(pos) == '<')
+ pos = findClosingTag(l, pos);
+ }
+ }
+
+ public List<String> splitOnTopLevelCommas(String s) {
+ return splitOnTopLevelChars(s, ',');
+ }
+
+ public static List<String> splitOnTopLevelChars(String s, char split) {
+ if (s.isEmpty())
+ return Collections.emptyList();
+ List<String> result = new ArrayList<>();
+ StringBuilder buf = new StringBuilder();
+ int depth = 0;
+ for (char c : s.toCharArray()) {
+ if (c == split && depth == 0) {
+ result.add(buf.toString().trim());
+ buf = new StringBuilder();
+ } else {
+ if (c == '<') depth++;
+ if (c == '>') depth--;
+ buf.append(c);
+ }
+ }
+ result.add(buf.toString().trim());
+ return result;
+ }
+
+ public boolean isEmpty() {
+ return types.isEmpty() && variables.isEmpty() && methods.isEmpty();
+ }
+
+ // Used for descriptive debug messages when figuring out what triggers
+ // recompilation.
+ public List<String> diff(PubApi prevApi) {
+ return diff("", prevApi);
+ }
+ private List<String> diff(String scopePrefix, PubApi prevApi) {
+
+ List<String> diffs = new ArrayList<>();
+
+ for (String typeKey : union(types.keySet(), prevApi.types.keySet())) {
+ PubType type = types.get(typeKey);
+ PubType prevType = prevApi.types.get(typeKey);
+ if (prevType == null) {
+ diffs.add("Type " + scopePrefix + typeKey + " was added");
+ } else if (type == null) {
+ diffs.add("Type " + scopePrefix + typeKey + " was removed");
+ } else {
+ // Check modifiers
+ if (!type.modifiers.equals(prevType.modifiers)) {
+ diffs.add("Modifiers for type " + scopePrefix + typeKey
+ + " changed from " + prevType.modifiers + " to "
+ + type.modifiers);
+ }
+
+ // Recursively check types pub API
+ diffs.addAll(type.pubApi.diff(prevType.pubApi));
+ }
+ }
+
+ for (String varKey : union(variables.keySet(), prevApi.variables.keySet())) {
+ PubVar var = variables.get(varKey);
+ PubVar prevVar = prevApi.variables.get(varKey);
+ if (prevVar == null) {
+ diffs.add("Variable " + scopePrefix + varKey + " was added");
+ } else if (var == null) {
+ diffs.add("Variable " + scopePrefix + varKey + " was removed");
+ } else {
+ if (!var.modifiers.equals(prevVar.modifiers)) {
+ diffs.add("Modifiers for var " + scopePrefix + varKey
+ + " changed from " + prevVar.modifiers + " to "
+ + var.modifiers);
+ }
+ if (!var.type.equals(prevVar.type)) {
+ diffs.add("Type of " + scopePrefix + varKey
+ + " changed from " + prevVar.type + " to "
+ + var.type);
+ }
+ if (!var.getConstValue().equals(prevVar.getConstValue())) {
+ diffs.add("Const value of " + scopePrefix + varKey
+ + " changed from " + prevVar.getConstValue().orElse("<none>")
+ + " to " + var.getConstValue().orElse("<none>"));
+ }
+ }
+ }
+
+ for (String methodKey : union(methods.keySet(), prevApi.methods.keySet())) {
+ PubMethod method = methods.get(methodKey);
+ PubMethod prevMethod = prevApi.methods.get(methodKey);
+ if (prevMethod == null) {
+ diffs.add("Method " + scopePrefix + methodKey + " was added");
+ } else if (method == null) {
+ diffs.add("Method " + scopePrefix + methodKey + " was removed");
+ } else {
+ if (!method.modifiers.equals(prevMethod.modifiers)) {
+ diffs.add("Modifiers for method " + scopePrefix + methodKey
+ + " changed from " + prevMethod.modifiers + " to "
+ + method.modifiers);
+ }
+ if (!method.typeParams.equals(prevMethod.typeParams)) {
+ diffs.add("Type parameters for method " + scopePrefix
+ + methodKey + " changed from " + prevMethod.typeParams
+ + " to " + method.typeParams);
+ }
+ if (!method.throwDecls.equals(prevMethod.throwDecls)) {
+ diffs.add("Throw decl for method " + scopePrefix + methodKey
+ + " changed from " + prevMethod.throwDecls + " to "
+ + " to " + method.throwDecls);
+ }
+ }
+ }
+
+ return diffs;
+ }
+
+ public String toString() {
+ return String.format("%s[types: %s, variables: %s, methods: %s]",
+ getClass().getSimpleName(),
+ types.values(),
+ variables.values(),
+ methods.values());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApiTypeParam.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,49 @@
+package com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class PubApiTypeParam implements Serializable {
+
+ private static final long serialVersionUID = 8899204612014329162L;
+
+ private final String identifier;
+ private final List<TypeDesc> bounds;
+
+ public PubApiTypeParam(String identifier, List<TypeDesc> bounds) {
+ this.identifier = identifier;
+ this.bounds = bounds;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ PubApiTypeParam other = (PubApiTypeParam) obj;
+ return identifier.equals(other.identifier)
+ && bounds.equals(other.bounds);
+ }
+
+ @Override
+ public int hashCode() {
+ return identifier.hashCode() ^ bounds.hashCode();
+ }
+
+ public String asString() {
+ if (bounds.isEmpty())
+ return identifier;
+ String boundsStr = bounds.stream()
+ .map(TypeDesc::encodeAsString)
+ .collect(Collectors.joining(" & "));
+ return identifier + " extends " + boundsStr;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s[id: %s, bounds: %s]",
+ getClass().getSimpleName(),
+ identifier,
+ bounds);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubMethod.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,115 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.lang.model.element.Modifier;
+
+public class PubMethod implements Serializable {
+
+ private static final long serialVersionUID = -7813050194553446243L;
+
+ Set<Modifier> modifiers;
+ List<PubApiTypeParam> typeParams;
+ TypeDesc returnType;
+ String identifier;
+ List<TypeDesc> paramTypes;
+ List<TypeDesc> throwDecls;
+
+ public PubMethod(Set<Modifier> modifiers,
+ List<PubApiTypeParam> typeParams,
+ TypeDesc returnType,
+ String identifier,
+ List<TypeDesc> paramTypes,
+ List<TypeDesc> throwDecls) {
+ this.modifiers = modifiers;
+ this.typeParams = typeParams;
+ this.returnType = returnType;
+ this.identifier = identifier;
+ this.paramTypes = paramTypes;
+ this.throwDecls = throwDecls;
+ }
+
+ // We need to include return type and type parameters to be sure to have
+ // different values for different methods. (A method can be overloaded with
+ // the only difference being the upper bound of the return type.)
+ public String asSignatureString() {
+ StringBuilder sb = new StringBuilder();
+
+ // <A extends String, Serializable, B extends List>
+ if (typeParams.size() > 0) {
+ sb.append(typeParams.stream()
+ .map(PubApiTypeParam::asString)
+ .collect(Collectors.joining(",", "<", "> ")));
+ }
+ sb.append(TypeDesc.encodeAsString(returnType));
+ sb.append(" ");
+ sb.append(identifier);
+ sb.append("(");
+ sb.append(paramTypes.stream()
+ .map(TypeDesc::encodeAsString)
+ .collect(Collectors.joining(",")));
+ sb.append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ PubMethod other = (PubMethod) obj;
+ return modifiers.equals(other.modifiers)
+ && typeParams.equals(other.typeParams)
+ && returnType.equals(other.returnType)
+ && identifier.equals(other.identifier)
+ && paramTypes.equals(other.paramTypes)
+ && throwDecls.equals(other.throwDecls);
+ }
+
+ @Override
+ public int hashCode() {
+ return modifiers.hashCode()
+ ^ typeParams.hashCode()
+ ^ returnType.hashCode()
+ ^ identifier.hashCode()
+ ^ paramTypes.hashCode()
+ ^ throwDecls.hashCode();
+ }
+
+ public String toString() {
+ return String.format("%s[modifiers: %s, typeParams: %s, retType: %s, identifier: %s, params: %s, throws: %s]",
+ getClass().getSimpleName(),
+ modifiers,
+ typeParams,
+ returnType,
+ identifier,
+ paramTypes,
+ throwDecls);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubType.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,75 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.lang.model.element.Modifier;
+
+public class PubType implements Serializable {
+
+ private static final long serialVersionUID = -7423416049253889793L;
+
+ public final Set<Modifier> modifiers;
+ public final String fqName;
+ public final PubApi pubApi;
+
+ public PubType(Set<Modifier> modifiers,
+ String fqName,
+ PubApi pubApi) {
+ this.modifiers = modifiers;
+ this.fqName = fqName;
+ this.pubApi = pubApi;
+ }
+
+ public String getFqName() {
+ return fqName.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ PubType other = (PubType) obj;
+ return modifiers.equals(other.modifiers)
+ && fqName.equals(other.fqName)
+ && pubApi.equals(other.pubApi);
+ }
+
+ @Override
+ public int hashCode() {
+ return modifiers.hashCode() ^ fqName.hashCode() ^ pubApi.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s[modifiers: %s, fqName: %s, pubApi: %s]",
+ getClass().getSimpleName(),
+ modifiers,
+ fqName,
+ pubApi);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubVar.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.lang.model.element.Modifier;
+
+public class PubVar implements Serializable {
+
+ private static final long serialVersionUID = 5806536061153374575L;
+
+ public final Set<Modifier> modifiers;
+ public final TypeDesc type;
+ public final String identifier;
+ private final String constValue;
+
+ public PubVar(Set<Modifier> modifiers,
+ TypeDesc type,
+ String identifier,
+ String constValue) {
+ this.modifiers = modifiers;
+ this.type = type;
+ this.identifier = identifier;
+ this.constValue = constValue;
+ }
+
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ PubVar other = (PubVar) obj;
+ return modifiers.equals(other.modifiers)
+ && type.equals(other.type)
+ && identifier.equals(other.identifier)
+ && getConstValue().equals(other.getConstValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return modifiers.hashCode()
+ ^ type.hashCode()
+ ^ identifier.hashCode()
+ ^ getConstValue().hashCode();
+ }
+
+ public String toString() {
+ return String.format("%s[modifiers: %s, type: %s, identifier: %s, constValue: %s]",
+ getClass().getSimpleName(),
+ modifiers,
+ type,
+ identifier,
+ constValue);
+ }
+
+ public Optional<String> getConstValue() {
+ return Optional.ofNullable(constValue);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ReferenceTypeDesc.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+
+import javax.lang.model.type.TypeKind;
+
+public class ReferenceTypeDesc extends TypeDesc implements Serializable {
+
+ private static final long serialVersionUID = 3357616754544796372L;
+
+ // Example: "java.util.Vector<java.lang.String>"
+ String javaType;
+
+ public ReferenceTypeDesc(String javaType) {
+ super(TypeKind.DECLARED);
+ this.javaType = javaType;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj))
+ return false;
+ return javaType.equals(((ReferenceTypeDesc) obj).javaType);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ javaType.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s[type: %s]", getClass().getSimpleName(), javaType);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeDesc.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,139 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ErrorType;
+import javax.lang.model.type.NoType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.SimpleTypeVisitor9;
+
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.StringUtils;
+
+public abstract class TypeDesc implements Serializable {
+
+ private static final long serialVersionUID = -8201634143915519172L;
+
+ TypeKind typeKind;
+
+ public TypeDesc(TypeKind typeKind) {
+ this.typeKind = typeKind;
+ }
+
+ public static TypeDesc decodeString(String s) {
+ s = s.trim();
+ if (s.endsWith("[]")) {
+ String componentPart = s.substring(0, s.length()-2);
+ return new ArrayTypeDesc(decodeString(componentPart));
+ }
+
+ if (s.startsWith("#"))
+ return new TypeVarTypeDesc(s.substring(1));
+
+ if (s.matches("boolean|byte|char|double|float|int|long|short|void")) {
+ TypeKind tk = TypeKind.valueOf(StringUtils.toUpperCase(s));
+ return new PrimitiveTypeDesc(tk);
+ }
+
+ return new ReferenceTypeDesc(s);
+ }
+
+ public static String encodeAsString(TypeDesc td) {
+ if (td.typeKind.isPrimitive() || td.typeKind == TypeKind.VOID)
+ return StringUtils.toLowerCase(td.typeKind.toString());
+
+ if (td.typeKind == TypeKind.ARRAY)
+ return encodeAsString(((ArrayTypeDesc) td).compTypeDesc) + "[]";
+
+ if (td.typeKind == TypeKind.TYPEVAR)
+ return "#" + ((TypeVarTypeDesc) td).identifier;
+
+ if (td.typeKind == TypeKind.DECLARED)
+ return ((ReferenceTypeDesc) td).javaType.toString();
+
+ throw new AssertionError("Unhandled type: " + td.typeKind);
+ }
+
+ public static TypeDesc fromType(TypeMirror type) {
+ TypeVisitor<TypeDesc, Void> v = new SimpleTypeVisitor9<TypeDesc, Void>() {
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitArray(ArrayType t, Void p) {
+ return new ArrayTypeDesc(t.getComponentType().accept(this, p));
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitDeclared(DeclaredType t, Void p) {
+ return new ReferenceTypeDesc(((ClassType) t).tsym.flatName().toString());
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitNoType(NoType t, Void p) {
+ return new PrimitiveTypeDesc(TypeKind.VOID);
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitTypeVariable(TypeVariable t, Void p) {
+ return new TypeVarTypeDesc(t.toString());
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitPrimitive(PrimitiveType t, Void p) {
+ return new PrimitiveTypeDesc(t.getKind());
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public TypeDesc visitError(ErrorType t, Void p) {
+ return new ReferenceTypeDesc("<error type>");
+ }
+ };
+
+ TypeDesc td = v.visit(type);
+ if (td == null)
+ throw new AssertionError("Unhandled type mirror: " + type + " (" + type.getClass() + ")");
+ return td;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (getClass() != obj.getClass())
+ return false;
+ return typeKind.equals(((TypeDesc) obj).typeKind);
+ }
+
+ @Override
+ public int hashCode() {
+ return typeKind.hashCode();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeVarTypeDesc.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * 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 com.sun.tools.sjavac.pubapi;
+
+import java.io.Serializable;
+
+import javax.lang.model.type.TypeKind;
+
+public class TypeVarTypeDesc extends TypeDesc implements Serializable {
+
+ private static final long serialVersionUID = 3357616754544796373L;
+
+ String identifier; // Example: "T"
+
+ public TypeVarTypeDesc(String identifier) {
+ super(TypeKind.TYPEVAR);
+ this.identifier = identifier;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj))
+ return false;
+ return identifier.equals(((TypeVarTypeDesc) obj).identifier);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ identifier.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s[identifier: %s]",
+ getClass().getSimpleName(),
+ identifier);
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -31,6 +31,8 @@
import java.util.Map;
import java.util.Set;
+import com.sun.tools.sjavac.pubapi.PubApi;
+
/**
*
* <p><b>This is NOT part of any supported API.
@@ -47,8 +49,10 @@
public int returnCode;
public Map<String, Set<URI>> packageArtifacts = new HashMap<>();
- public Map<String, Set<String>> packageDependencies = new HashMap<>();
- public Map<String, String> packagePubapis = new HashMap<>();
+ public Map<String, Map<String, Set<String>>> packageDependencies = new HashMap<>();
+ public Map<String, Map<String, Set<String>>> packageCpDependencies = new HashMap<>();
+ public Map<String, PubApi> packagePubapis = new HashMap<>();
+ public Map<String, PubApi> dependencyPubapis = new HashMap<>();
public String stdout = "";
public String stderr = "";
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -27,6 +27,8 @@
import java.io.IOException;
+import com.sun.tools.sjavac.Log;
+
/**
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
@@ -36,6 +38,8 @@
public class ServerMain {
public static int run(String[] args) {
+ Log.initializeLog(System.out, System.err);
+
// Any options other than --startserver?
if (args.length > 1) {
System.err.println("When spawning a background server, only a single --startserver argument is allowed.");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/diamond/pos/NestedDiamondAllocationTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,53 @@
+/*
+ * 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 8081521
+ * @summary Ensure that anonymous class construction using <> can be nested within another
+ * @compile NestedDiamondAllocationTest.java
+ * @run main NestedDiamondAllocationTest
+ *
+ */
+
+public class NestedDiamondAllocationTest {
+ static class Clazz2 {
+ static class A {
+ };
+ public A a;
+ }
+ static class FooNest<Q> {
+ FooNest(Q q, Foo<Q> foo) {
+ }
+ }
+
+ static class Foo<T> {
+ }
+
+ static Clazz2 clazz = new Clazz2();
+
+ public static void main(String [] args) {
+ FooNest fooNest = new FooNest<>(clazz.a, new Foo<>() {
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/BitWiseOperators.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,113 @@
+/*
+ * 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 8082311
+ * @summary Verify that bitwise operators don't allow to mix numeric and boolean operands.
+ * @library ../lib
+ */
+
+import com.sun.tools.javac.util.StringUtils;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+
+public class BitWiseOperators extends JavacTestingAbstractThreadedTest {
+ public static void main(String... args) {
+ new BitWiseOperators().run();
+ }
+
+ void run() {
+ for (TYPE type1 : TYPE.values()) {
+ for (OPERATION op : OPERATION.values()) {
+ for (TYPE type2 : TYPE.values()) {
+ runTest(type1, op, type2);
+ }
+ }
+ }
+ }
+
+ void runTest(TYPE type1, OPERATION op, TYPE type2) {
+ DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<>();
+ List<JavaSource> files = Arrays.asList(new JavaSource(type1, op, type2));
+ comp.getTask(null, null, dc, null, null, files).call();
+ if (dc.getDiagnostics().isEmpty() ^ TYPE.compatible(type1, type2)) {
+ throw new AssertionError("Unexpected behavior. Type1: " + type1 +
+ "; type2: " + type2 +
+ "; diagnostics: " + dc.getDiagnostics());
+ }
+ }
+
+ enum TYPE {
+ BYTE,
+ CHAR,
+ SHORT,
+ INT,
+ LONG,
+ BOOLEAN;
+
+ public static boolean compatible(TYPE op1, TYPE op2) {
+ return !(op1 == BOOLEAN ^ op2 == BOOLEAN);
+ }
+ }
+
+ enum OPERATION {
+ BITAND("&"),
+ BITOR("|"),
+ BITXOR("^");
+
+ String op;
+
+ private OPERATION(String op) {
+ this.op = op;
+ }
+
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ String template = "class Test {\n" +
+ " public Object test(#TYPE1 var1, #TYPE2 var2) {\n" +
+ " return var1 #OP var2;\n" +
+ " }\n" +
+ "}";
+
+ String source;
+
+ public JavaSource(TYPE type1, OPERATION op, TYPE type2) {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ source = template.replaceAll("#TYPE1", StringUtils.toLowerCase(type1.name()))
+ .replaceAll("#OP", StringUtils.toLowerCase(op.op))
+ .replaceAll("#TYPE2", StringUtils.toLowerCase(type2.name()));
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/ApiExtraction.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8054717
+ * @summary Make sure extraction of non-private APIs work as expected.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.file
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.sjavac
+ * @build Wrapper ToolBox
+ * @run main Wrapper ApiExtraction
+ */
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PROTECTED;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.type.TypeKind;
+
+import com.sun.tools.sjavac.PubApiExtractor;
+import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PrimitiveTypeDesc;
+import com.sun.tools.sjavac.pubapi.PubApi;
+import com.sun.tools.sjavac.pubapi.PubMethod;
+import com.sun.tools.sjavac.pubapi.PubType;
+import com.sun.tools.sjavac.pubapi.PubVar;
+import com.sun.tools.sjavac.pubapi.ReferenceTypeDesc;
+
+
+public class ApiExtraction {
+ public static void main(String[] args) throws IOException {
+
+ String testSrc = String.join("\n",
+ "import java.util.*;",
+ "public final class TestClass extends Thread {",
+
+ // Fields with various combination of modifiers
+ " private String s1 = \"str 1\";",
+ " public String s2 = \"str 2\";",
+ " protected final String s3 = \"str 3\";",
+ " static String s4 = \"str 4\";",
+
+ // Methods with various combinations of types and modifiers
+ " protected void m1() {}",
+ " public static Map<Integer, List<String>> m2() {",
+ " return null;",
+ " }",
+ " final void m3(Set<Map<Integer, Map<String, String>>> s) {}",
+
+ // Some inner classes
+ " static class DummyInner1 implements Runnable {",
+ " protected int field;",
+ " public void run() {}",
+ " }",
+ " final class DummyInner2 { }",
+ "}");
+
+ // Create class file to extract API from
+ new ToolBox().new JavacTask().sources(testSrc).run();
+
+ // Extract PubApi
+ Options options = Options.parseArgs("-d", "bin", "-cp", ".");
+ PubApiExtractor pubApiExtr = new PubApiExtractor(options);
+ PubApi actualApi = pubApiExtr.getPubApi("TestClass");
+
+ // Validate result
+ PubApi expectedApi = getExpectedPubApi();
+ if (!expectedApi.equals(actualApi)) {
+ List<String> diffs = expectedApi.diff(actualApi);
+ System.out.println(diffs.size() + " differences found.");
+ for (String diff : diffs) {
+ System.out.println(diff);
+ }
+ throw new AssertionError("Actual API differs from expected API.");
+ }
+ }
+
+ private static PubApi getExpectedPubApi() {
+
+ ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String");
+
+ // Fields
+ // (s1 is private and therefore not included)
+ PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null);
+ PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null);
+ PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3",
+ "\"\\u0073\\u0074\\u0072\\u0020\\u0033\"");
+
+ // Methods
+ PubMethod init = new PubMethod(setOf(PUBLIC),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "<init>",
+ emptyList(),
+ emptyList());
+
+ PubMethod clinit = new PubMethod(setOf(STATIC),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "<clinit>",
+ emptyList(),
+ emptyList());
+
+ PubMethod m1 = new PubMethod(setOf(PROTECTED),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "m1",
+ emptyList(),
+ emptyList());
+
+ PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC),
+ emptyList(),
+ new ReferenceTypeDesc("java.util.Map"),
+ "m2",
+ emptyList(),
+ emptyList());
+
+ PubMethod m3 = new PubMethod(setOf(FINAL),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "m3",
+ asList(new ReferenceTypeDesc("java.util.Set")),
+ emptyList());
+
+ // Complete class
+ PubType testClass = new PubType(setOf(PUBLIC, FINAL),
+ "TestClass",
+ new PubApi(asList(getDummyInner1(), getDummyInner2()),
+ asList(s2, s3, s4),
+ asList(init, clinit, m1, m2, m3)));
+
+ // Wrap in "package level" PubApi
+ return new PubApi(asList(testClass), emptyList(), emptyList());
+ }
+
+ private static PubType getDummyInner1() {
+ PubMethod init = new PubMethod(setOf(),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "<init>",
+ emptyList(),
+ emptyList());
+
+ PubMethod run = new PubMethod(setOf(PUBLIC),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "run",
+ emptyList(),
+ emptyList());
+
+ PubVar field = new PubVar(setOf(PROTECTED),
+ new PrimitiveTypeDesc(TypeKind.INT),
+ "field",
+ null);
+
+ return new PubType(setOf(STATIC),
+ "TestClass$DummyInner1",
+ new PubApi(emptyList(),
+ asList(field),
+ asList(init, run)));
+ }
+
+ private static PubType getDummyInner2() {
+ PubMethod init = new PubMethod(setOf(),
+ emptyList(),
+ new PrimitiveTypeDesc(TypeKind.VOID),
+ "<init>",
+ emptyList(),
+ emptyList());
+
+ return new PubType(setOf(FINAL),
+ "TestClass$DummyInner2",
+ new PubApi(emptyList(),
+ emptyList(),
+ asList(init)));
+ }
+
+ @SafeVarargs
+ private static <T> Set<T> setOf(T... elements) {
+ return new HashSet<>(asList(elements));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/ClasspathDependencies.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8054717
+ * @summary Make sure changes of public API on classpath triggers recompilation
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.file
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.sjavac
+ * @build Wrapper ToolBox
+ * @run main Wrapper ClasspathDependencies
+ */
+
+import static com.sun.tools.javac.util.Assert.check;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+
+public class ClasspathDependencies extends SjavacBase {
+
+ static final String server = "--server:portfile=testserver,background=false";
+
+ public static void main(String... args) throws Exception {
+
+ Path root = Paths.get(ClasspathDependencies.class.getSimpleName() + "Test");
+
+ delete(root);
+
+ Path src = root.resolve("src");
+ Path classes = root.resolve("classes");
+ Path srcDep = root.resolve("srcDep");
+ Path classesDep = root.resolve("classesDep");
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Create a test dependency, Dep.class, and put it in the classpath dir");
+ String depCode = "package dep; public class Dep { public void m1() {} }";
+ toolbox.writeFile(srcDep.resolve("dep/Dep.java"), depCode);
+ int rc = compile(server, "-d", classesDep, srcDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Compile and link against the Dep.class");
+ toolbox.writeFile(src.resolve("pkg/C.java"),
+ "package pkg;" +
+ "import dep.Dep;" +
+ "public class C { Dep dep; public void m() { new Dep().m1(); } }");
+ rc = compile(server, "-d", classes, src, "-cp", classesDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+ FileTime modTime1 = Files.getLastModifiedTime(classes.resolve("pkg/C.class"));
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Update dependency (without changing the public api)");
+ Thread.sleep(2000);
+ depCode = depCode.replaceAll("}$", "private void m2() {} }");
+ toolbox.writeFile(srcDep.resolve("dep/Dep.java"), depCode);
+ rc = compile(server, "-d", classesDep, srcDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Make sure that this does not trigger recompilation of C.java");
+ rc = compile(server, "-d", classes, src, "-cp", classesDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+ FileTime modTime2 = Files.getLastModifiedTime(classes.resolve("pkg/C.class"));
+ check(modTime1.equals(modTime2), "Recompilation erroneously triggered");
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Update public API of dependency");
+ Thread.sleep(2000);
+ depCode = depCode.replace("m1()", "m1(String... arg)");
+ toolbox.writeFile(srcDep.resolve("dep/Dep.java"), depCode);
+ rc = compile(server, "-d", classesDep, srcDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+
+ ////////////////////////////////////////////////////////////////////////
+ headline("Make sure that recompilation of C.java is triggered");
+ rc = compile(server, "-d", classes, src, "-cp", classesDep);
+ check(rc == 0, "Compilation failed unexpectedly");
+ FileTime modTime3 = Files.getLastModifiedTime(classes.resolve("pkg/C.class"));
+ check(modTime2.compareTo(modTime3) < 0, "Recompilation not triggered");
+ }
+
+ static void headline(String str) {
+ System.out.println();
+ System.out.println(str);
+ System.out.println(str.replaceAll(".", "-"));
+ }
+
+ static void delete(Path root) throws IOException {
+ if (!Files.exists(root))
+ return;
+ Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path f, BasicFileAttributes a)
+ throws IOException {
+ Files.delete(f);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException e)
+ throws IOException {
+ if (e != null)
+ throw e;
+ if (!dir.equals(root))
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
+}
--- a/langtools/test/tools/sjavac/CompileCircularSources.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/CompileCircularSources.java Fri Jun 12 16:40:05 2015 -0400
@@ -48,27 +48,33 @@
}
void test() throws Exception {
- Files.createDirectory(BIN);
+ clean(TEST_ROOT);
+ Files.createDirectories(BIN);
clean(GENSRC, BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A { beta.B b; }");
+ "package alfa.omega; public class A { beta.B b; }");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; public class B { gamma.C c; }");
+ "package beta; public class B { gamma.C c; }");
tb.writeFile(GENSRC.resolve("gamma/C.java"),
- "package gamma; public class C { alfa.omega.A a; }");
+ "package gamma; public class C { alfa.omega.A a; }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3",
- SERVER_ARG,"--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "3",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
- verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/beta/B.class",
- "bin/gamma/C.class",
- "bin/javac_state");
+ verifyThatFilesHaveBeenAdded(previous_bin_state,
+ new_bin_state,
+ BIN + "/alfa/omega/A.class",
+ BIN + "/beta/B.class",
+ BIN + "/gamma/C.class",
+ BIN + "/javac_state");
clean(GENSRC, BIN);
}
}
--- a/langtools/test/tools/sjavac/CompileExcludingDependency.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/CompileExcludingDependency.java Fri Jun 12 16:40:05 2015 -0400
@@ -49,22 +49,27 @@
// Verify that excluding classes from compilation but not from linking works
void test() throws Exception {
- Files.createDirectory(BIN);
+ clean(TEST_ROOT);
+ Files.createDirectories(BIN);
clean(GENSRC,BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A { beta.B b; }");
+ "package alfa.omega; public class A { beta.B b; }");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; public class B { }");
+ "package beta; public class B { }");
- compile("-x", "beta", "-src", "gensrc", "-x", "alfa/omega", "-sourcepath", "gensrc",
- "-d", "bin", SERVER_ARG);
+ compile("-x", "beta",
+ "-src", GENSRC.toString(),
+ "-x", "alfa/omega",
+ "-sourcepath", GENSRC.toString(),
+ "-d", BIN.toString(),
+ SERVER_ARG);
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/javac_state");
clean(GENSRC, BIN);
}
}
--- a/langtools/test/tools/sjavac/CompileWithAtFile.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/CompileWithAtFile.java Fri Jun 12 16:40:05 2015 -0400
@@ -48,9 +48,13 @@
}
void test() throws Exception {
+ clean(TEST_ROOT);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("list.txt"),
- "-if */alfa/omega/A.java\n-if */beta/B.java\ngensrc\n-d bin\n");
+ "-if */alfa/omega/A.java\n" +
+ "-if */beta/B.java\n" +
+ GENSRC + "\n" +
+ "-d " + BIN + "\n");
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
"package alfa.omega; import beta.B; public class A { B b; }");
tb.writeFile(GENSRC.resolve("beta/B.java"),
@@ -60,13 +64,14 @@
Files.createDirectory(BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
- compile("@gensrc/list.txt", "--server:portfile=testserver,background=false");
+
+ compile("@" + GENSRC + "/list.txt", "--server:portfile=testserver,background=false");
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/javac_state",
- "bin/alfa/omega/A.class",
- "bin/beta/B.class");
+ BIN + "/javac_state",
+ BIN + "/alfa/omega/A.class",
+ BIN + "/beta/B.class");
clean(GENSRC, BIN);
}
}
--- a/langtools/test/tools/sjavac/CompileWithInvisibleSources.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java Fri Jun 12 16:40:05 2015 -0400
@@ -51,35 +51,45 @@
// gensrc2 contains broken code in beta.B, thus exclude that package
// gensrc3 contains a proper beta.B
void test() throws Exception {
- Files.createDirectory(BIN);
+ clean(TEST_ROOT);
+ Files.createDirectories(BIN);
clean(GENSRC, GENSRC2, GENSRC3, BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }");
+ "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }");
tb.writeFile(GENSRC2.resolve("beta/B.java"),
- "package beta; public class B { broken");
+ "package beta; public class B { broken");
tb.writeFile(GENSRC2.resolve("gamma/C.java"),
- "package gamma; public class C { }");
+ "package gamma; public class C { }");
tb.writeFile(GENSRC3.resolve("beta/B.java"),
- "package beta; public class B { }");
+ "package beta; public class B { }");
- compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2",
- "-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1",
+ compile(GENSRC.toString(),
+ "-x", "beta",
+ "-sourcepath", GENSRC2.toString(),
+ "-sourcepath", GENSRC3.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
SERVER_ARG);
System.out.println("The first compile went well!");
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/javac_state");
System.out.println("----- Compile with exluded beta went well!");
clean(BIN);
- compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3",
- "-d", "bin", "-h", "headers", "-j", "1",
+ compileExpectFailure(GENSRC.toString(),
+ "-sourcepath", GENSRC2.toString(),
+ "-sourcepath", GENSRC3.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
SERVER_ARG);
System.out.println("----- Compile without exluded beta failed, as expected! Good!");
--- a/langtools/test/tools/sjavac/CompileWithOverrideSources.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/CompileWithOverrideSources.java Fri Jun 12 16:40:05 2015 -0400
@@ -50,33 +50,43 @@
// Compile gensrc and gensrc2. However do not compile broken beta.B in gensrc,
// only compile ok beta.B in gensrc2
void test() throws Exception {
- Files.createDirectory(BIN);
+ clean(TEST_ROOT);
+ Files.createDirectories(BIN);
clean(GENSRC, GENSRC2, GENSRC3, BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }");
+ "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; public class B { broken");
+ "package beta; public class B { broken");
tb.writeFile(GENSRC.resolve("gamma/C.java"),
- "package gamma; public class C { }");
+ "package gamma; public class C { }");
tb.writeFile(GENSRC2.resolve("beta/B.java"),
- "package beta; public class B { }");
+ "package beta; public class B { }");
- compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
+ compile("-x", "beta",
+ GENSRC.toString(),
+ GENSRC2.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
SERVER_ARG);
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/beta/B.class",
- "bin/gamma/C.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/beta/B.class",
+ BIN + "/gamma/C.class",
+ BIN + "/javac_state");
System.out.println("----- Compile with exluded beta went well!");
clean(BIN);
- compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
+ compileExpectFailure(GENSRC.toString(),
+ GENSRC2.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
SERVER_ARG);
System.out.println("----- Compile without exluded beta failed, as expected! Good!");
--- a/langtools/test/tools/sjavac/DependencyCollection.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-/*
- * @test
- * @bug 8056258 8048609
- * @summary Ensures that the DependencyCollector covers various cases.
- * @library /tools/lib
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.code
- * jdk.compiler/com.sun.tools.javac.file
- * jdk.compiler/com.sun.tools.javac.main
- * jdk.compiler/com.sun.tools.javac.util
- * jdk.compiler/com.sun.tools.sjavac.comp
- * jdk.compiler/com.sun.tools.sjavac.comp.dependencies
- * @build Wrapper ToolBox
- * @run main Wrapper DependencyCollection
- */
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.sjavac.comp.SmartFileManager;
-import com.sun.tools.sjavac.comp.dependencies.DependencyCollector;
-
-public class DependencyCollection {
-
- public static void main(String[] args) throws IOException {
- Path src = Paths.get(ToolBox.testSrc, "test-input", "src");
-
- JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
- try (StandardJavaFileManager fileManager = javac.getStandardFileManager(null, null, null)) {
- SmartFileManager smartFileManager = new SmartFileManager(fileManager);
- smartFileManager.setSymbolFileEnabled(false);
- Iterable<? extends JavaFileObject> fileObjects =
- fileManager.getJavaFileObjectsFromFiles(Arrays.asList(src.resolve("pkg/Test.java").toFile()));
- JavacTaskImpl task = (JavacTaskImpl) javac.getTask(new PrintWriter(System.out),
- smartFileManager,
- null,
- Arrays.asList("-d", "classes",
- "-sourcepath", src.toAbsolutePath().toString()),
- null,
- fileObjects);
- DependencyCollector depsCollector = new DependencyCollector();
- task.addTaskListener(depsCollector);
- task.doCall();
-
- // Find pkg symbol
- PackageSymbol pkg = findPkgSymbolWithName(depsCollector.getSourcePackages(), "pkg");
- Set<PackageSymbol> foundDependencies = depsCollector.getDependenciesForPkg(pkg);
-
- // Print dependencies
- System.out.println("Found dependencies:");
- foundDependencies.stream()
- .sorted(Comparator.comparing(DependencyCollection::extractNumber))
- .forEach(p -> System.out.println(" " + p));
-
- // Check result
- Set<Integer> found = foundDependencies.stream()
- .map(DependencyCollection::extractNumber)
- .collect(Collectors.toSet());
- found.remove(-1); // Dependencies with no number (java.lang etc)
- Set<Integer> expected = new HashSet<>();
- for (int i = 2; i <= 30; i++) {
- if (i == 15) continue; // Case 15 correspond to the type of a throw-away return value.
- expected.add(i);
- }
-
- Set<Integer> missing = new HashSet<>(expected);
- missing.removeAll(found);
- if (missing.size() > 0) {
- System.out.println("Missing dependencies:");
- missing.forEach(i -> System.out.println(" Dependency " + i));
- }
-
- Set<Integer> unexpected = new HashSet<>(found);
- unexpected.removeAll(expected);
- if (unexpected.size() > 0) {
- System.out.println("Unexpected dependencies found:");
- unexpected.forEach(i -> System.out.println(" Dependency " + i));
- }
-
- if (missing.size() > 0 || unexpected.size() > 0)
- throw new AssertionError("Missing and/or unexpected dependencies found.");
- }
- }
-
- private static PackageSymbol findPkgSymbolWithName(Set<PackageSymbol> syms, String name) {
- for (PackageSymbol ps : syms)
- if (ps.fullname.toString().equals("pkg"))
- return ps;
- throw new AssertionError("Could not find package named \"pkg\".");
- }
-
- public static int extractNumber(PackageSymbol p) {
- Matcher m = Pattern.compile("\\d+").matcher(p.fullname.toString());
- if (!m.find())
- return -1;
- return Integer.parseInt(m.group());
- }
-}
--- a/langtools/test/tools/sjavac/IncCompInheritance.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompInheritance.java Fri Jun 12 16:40:05 2015 -0400
@@ -60,6 +60,7 @@
throw new AssertionError("Compilation failed unexpectedly");
// Remove method A.m
+ Thread.sleep(2500); // Make sure we get a new timestamp
String aModified = "package pkga; public class A { }";
toolbox.writeFile(src.resolve("pkga/A.java"), aModified);
--- a/langtools/test/tools/sjavac/IncCompileChangeNative.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileChangeNative.java Fri Jun 12 16:40:05 2015 -0400
@@ -51,9 +51,10 @@
ToolBox tb = new ToolBox();
void test() throws Exception {
- Files.createDirectory(GENSRC);
- Files.createDirectory(BIN);
- Files.createDirectory(HEADERS);
+ clean(TEST_ROOT);
+ Files.createDirectories(GENSRC);
+ Files.createDirectories(BIN);
+ Files.createDirectories(HEADERS);
initialCompile();
incrementalCompileDropAllNatives();
@@ -70,21 +71,25 @@
System.out.println("\nIn incrementalCompileDropAllNatives() ");
System.out.println("Verify that beta_B.h is removed");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; import alfa.omega.A; public class B {"+
- "private int b() { return A.DEFINITION; } }");
+ "package beta; import alfa.omega.A; " +
+ "public class B { private int b() { return A.DEFINITION; } }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyNewerFiles(previous_bin_state, new_bin_state,
- "bin/beta/B.class",
- "bin/beta/BINT.class",
- "bin/javac_state");
+ BIN + "/beta/B.class",
+ BIN + "/beta/BINT.class",
+ BIN + "/javac_state");
previous_bin_state = new_bin_state;
Map<String,Long> new_headers_state = collectState(HEADERS);
verifyThatFilesHaveBeenRemoved(previous_headers_state, new_headers_state,
- "headers/beta_B.h");
+ HEADERS + "/beta_B.h");
previous_headers_state = new_headers_state;
}
@@ -94,22 +99,26 @@
System.out.println("\nIn incrementalCompileAddNative() ");
System.out.println("Verify that beta_B.h is added again");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; import alfa.omega.A; public class B {"+
- "private int b() { return A.DEFINITION; } "+
- "@java.lang.annotation.Native final static int alfa = 42; }");
+ "package beta; import alfa.omega.A; public class B {"+
+ "private int b() { return A.DEFINITION; } "+
+ "@java.lang.annotation.Native final static int alfa = 42; }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyNewerFiles(previous_bin_state, new_bin_state,
- "bin/beta/B.class",
- "bin/beta/BINT.class",
- "bin/javac_state");
+ BIN + "/beta/B.class",
+ BIN + "/beta/BINT.class",
+ BIN + "/javac_state");
previous_bin_state = new_bin_state;
Map<String,Long> new_headers_state = collectState(HEADERS);
verifyThatFilesHaveBeenAdded(previous_headers_state, new_headers_state,
- "headers/beta_B.h");
+ HEADERS + "/beta_B.h");
previous_headers_state = new_headers_state;
}
}
--- a/langtools/test/tools/sjavac/IncCompileDropClasses.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileDropClasses.java Fri Jun 12 16:40:05 2015 -0400
@@ -51,9 +51,10 @@
ToolBox tb = new ToolBox();
void test() throws Exception {
- Files.createDirectory(GENSRC);
- Files.createDirectory(BIN);
- Files.createDirectory(HEADERS);
+ clean(TEST_ROOT);
+ Files.createDirectories(GENSRC);
+ Files.createDirectories(BIN);
+ Files.createDirectories(HEADERS);
initialCompile();
incrementalCompileDroppingClasses();
@@ -68,15 +69,19 @@
System.out.println("\nIn incrementalCompileDroppingClasses() ");
System.out.println("Testing that deleting AA.java deletes all generated inner class including AA.class");
removeFrom(GENSRC, "alfa/omega/AA.java");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state,
- "bin/alfa/omega/AA$1.class",
- "bin/alfa/omega/AA$AAAA.class",
- "bin/alfa/omega/AA$AAA.class",
- "bin/alfa/omega/AAAAA.class",
- "bin/alfa/omega/AA.class");
+ BIN + "/alfa/omega/AA$1.class",
+ BIN + "/alfa/omega/AA$AAAA.class",
+ BIN + "/alfa/omega/AA$AAA.class",
+ BIN + "/alfa/omega/AAAAA.class",
+ BIN + "/alfa/omega/AA.class");
previous_bin_state = new_bin_state;
Map<String,Long> new_headers_state = collectState(HEADERS);
--- a/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java Fri Jun 12 16:40:05 2015 -0400
@@ -27,6 +27,7 @@
* @test
* @summary Verify that "alfa.omega.A a" does create a proper dependency
* @bug 8054689
+ * @ignore Requires dependency code to deal with in-method dependencies.
* @author Fredrik O
* @author sogoel (rewrite)
* @library /tools/lib
@@ -38,8 +39,7 @@
* @run main Wrapper IncCompileFullyQualifiedRef
*/
-import java.util.*;
-import java.nio.file.*;
+import java.util.Map;
public class IncCompileFullyQualifiedRef extends SJavacTester {
public static void main(String... args) throws Exception {
@@ -48,36 +48,43 @@
}
void test() throws Exception {
+ clean(TEST_ROOT);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A { "+
- " public final static int DEFINITION = 18; "+
- " public void hello() { }"+
- "}");
+ "package alfa.omega; public class A { "+
+ " public final static int DEFINITION = 18; "+
+ " public void hello() { }"+
+ "}");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; public class B { "+
- " public void world() { alfa.omega.A a; }"+
- "}");
+ "package beta; public class B { "+
+ " public void world() { alfa.omega.A a; }"+
+ "}");
- compile("gensrc", "-d", "bin", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> previous_bin_state = collectState(BIN);
// Change pubapi of A, this should trigger a recompile of B.
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A { "+
- " public final static int DEFINITION = 19; "+
- " public void hello() { }"+
- "}");
+ "package alfa.omega; public class A { "+
+ " public final static int DEFINITION = 19; "+
+ " public void hello() { }"+
+ "}");
- compile("gensrc", "-d", "bin", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyNewerFiles(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/beta/B.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/beta/B.class",
+ BIN + "/javac_state");
clean(GENSRC,BIN);
}
}
--- a/langtools/test/tools/sjavac/IncCompileNoChanges.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileNoChanges.java Fri Jun 12 16:40:05 2015 -0400
@@ -50,9 +50,10 @@
Map<String,Long> previous_headers_state;
void test() throws Exception {
- Files.createDirectory(GENSRC);
- Files.createDirectory(BIN);
- Files.createDirectory(HEADERS);
+ clean(Paths.get(getClass().getSimpleName()));
+ Files.createDirectories(GENSRC);
+ Files.createDirectories(BIN);
+ Files.createDirectories(HEADERS);
initialCompile();
incrementalCompileNoChanges();
@@ -66,8 +67,12 @@
previous_headers_state = collectState(HEADERS);
System.out.println("\nIn incrementalCompileNoChanges() ");
System.out.println("Testing that no change in sources implies no change in binaries");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyEqual(new_bin_state, previous_bin_state);
Map<String,Long> new_headers_state = collectState(HEADERS);
--- a/langtools/test/tools/sjavac/IncCompileUpdateNative.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileUpdateNative.java Fri Jun 12 16:40:05 2015 -0400
@@ -51,9 +51,10 @@
ToolBox tb = new ToolBox();
void test() throws Exception {
- Files.createDirectory(GENSRC);
- Files.createDirectory(BIN);
- Files.createDirectory(HEADERS);
+ clean(TEST_ROOT);
+ Files.createDirectories(GENSRC);
+ Files.createDirectories(BIN);
+ Files.createDirectories(HEADERS);
initialCompile();
incrementalCompileChangeNative();
@@ -69,22 +70,26 @@
System.out.println("\nIn incrementalCompileChangeNative() ");
System.out.println("Verify that beta_B.h is rewritten again");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; import alfa.omega.A; public class B {"+
- "private int b() { return A.DEFINITION; } "+
- "@java.lang.annotation.Native final static int alfa = 43; }");
+ "package beta; import alfa.omega.A; public class B {"+
+ "private int b() { return A.DEFINITION; } "+
+ "@java.lang.annotation.Native final static int alfa = 43; }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyNewerFiles(previous_bin_state, new_bin_state,
- "bin/beta/B.class",
- "bin/beta/BINT.class",
- "bin/javac_state");
+ BIN + "/beta/B.class",
+ BIN + "/beta/BINT.class",
+ BIN + "/javac_state");
previous_bin_state = new_bin_state;
Map<String,Long> new_headers_state = collectState(HEADERS);
verifyNewerFiles(previous_headers_state, new_headers_state,
- "headers/beta_B.h");
+ HEADERS + "/beta_B.h");
previous_headers_state = new_headers_state;
}
}
--- a/langtools/test/tools/sjavac/IncCompileWithChanges.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/IncCompileWithChanges.java Fri Jun 12 16:40:05 2015 -0400
@@ -24,6 +24,7 @@
/*
* @test
* @summary Verify incremental changes in gensrc are handled as expected
+ * @ignore Requires dependency code to deal with in-method dependencies.
* @bug 8054689
* @author Fredrik O
* @author sogoel (rewrite)
@@ -51,14 +52,13 @@
ToolBox tb = new ToolBox();
void test() throws Exception {
- Files.createDirectory(GENSRC);
- Files.createDirectory(BIN);
- Files.createDirectory(HEADERS);
+ clean(TEST_ROOT);
+ Files.createDirectories(GENSRC);
+ Files.createDirectories(BIN);
+ Files.createDirectories(HEADERS);
initialCompile();
incrementalCompileWithChange();
-
- clean(GENSRC, BIN, HEADERS);
}
/* Update A.java with a new timestamp and new final static definition.
@@ -72,24 +72,29 @@
System.out.println("A.java updated to trigger a recompile");
System.out.println("Generated native header should not be updated since native api of B was not modified");
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A implements AINT { "+
- "public final static int DEFINITION = 18; public void aint() { } private void foo() { } }");
+ "package alfa.omega; public class A implements AINT { " +
+ "public final static int DEFINITION = 18;" +
+ "public void aint() { } private void foo() { } }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
Map<String,Long> new_bin_state = collectState(BIN);
verifyNewerFiles(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/alfa/omega/AINT.class",
- "bin/alfa/omega/AA$AAAA.class",
- "bin/alfa/omega/AAAAA.class",
- "bin/alfa/omega/AA$AAA.class",
- "bin/alfa/omega/AA.class",
- "bin/alfa/omega/AA$1.class",
- "bin/beta/B.class",
- "bin/beta/BINT.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/alfa/omega/AINT.class",
+ BIN + "/alfa/omega/AA$AAAA.class",
+ BIN + "/alfa/omega/AAAAA.class",
+ BIN + "/alfa/omega/AA$AAA.class",
+ BIN + "/alfa/omega/AA.class",
+ BIN + "/alfa/omega/AA$1.class",
+ BIN + "/beta/B.class",
+ BIN + "/beta/BINT.class",
+ BIN + "/javac_state");
previous_bin_state = new_bin_state;
Map<String,Long> new_headers_state = collectState(HEADERS);
--- a/langtools/test/tools/sjavac/JavacOptionPrep.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/JavacOptionPrep.java Fri Jun 12 16:40:05 2015 -0400
@@ -83,6 +83,7 @@
// Check the result
boolean destDirFound = false;
+ boolean userPathsFirst = false;
boolean headerDirFound = false;
boolean gensrcDirFound = false;
boolean classPathFound = false;
@@ -95,6 +96,11 @@
String option = javacArgIter.next();
+ // Ignore this option for now. When the file=... requirement goes
+ // away, this will be easier to handle.
+ if (option.startsWith("-XDcompletionDeps"))
+ continue;
+
switch (option) {
case "-classpath":
case "-cp":
@@ -166,7 +172,6 @@
if (!implicitNoneFound)
throw new AssertionError("\"-implicit:none\" not found.");
-
}
static void assertEquals(Object expected, Object actual) {
--- a/langtools/test/tools/sjavac/PermittedArtifact.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/PermittedArtifact.java Fri Jun 12 16:40:05 2015 -0400
@@ -38,12 +38,8 @@
* @run main Wrapper PermittedArtifact
*/
-import java.lang.reflect.Method;
-import java.util.*;
-import java.io.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.nio.charset.*;
+import java.nio.file.Files;
+import java.util.Map;
public class PermittedArtifact extends SJavacTester {
public static void main(String... args) throws Exception {
@@ -53,26 +49,31 @@
//Verify that --permit-artifact=bin works
void test() throws Exception {
- Files.createDirectory(BIN);
+ clean(TEST_ROOT);
+ Files.createDirectories(BIN);
clean(GENSRC, BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
- new ToolBox().writeFile(GENSRC+"/alfa/omega/A.java",
- "package alfa.omega; public class A { }");
+ ToolBox tb = new ToolBox();
+ tb.writeFile(GENSRC + "/alfa/omega/A.java",
+ "package alfa.omega; public class A { }");
- new ToolBox().writeFile(BIN+"/alfa/omega/AA.class",
- "Ugh, a messy build system (tobefixed) wrote this class file, "
- + "sjavac must not delete it.");
+ tb.writeFile(BIN + "/alfa/omega/AA.class",
+ "Ugh, a messy build system (tobefixed) wrote this class file, " +
+ "sjavac must not delete it.");
- compile("--log=debug", "--permit-artifact=bin/alfa/omega/AA.class",
- "-src", "gensrc", "-d", "bin", SERVER_ARG);
+ compile("--log=debug",
+ "--permit-artifact=" + BIN + "/alfa/omega/AA.class",
+ "-src", GENSRC.toString(),
+ "-d", BIN.toString(),
+ SERVER_ARG);
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class",
- "bin/alfa/omega/AA.class",
- "bin/javac_state");
+ BIN + "/alfa/omega/A.class",
+ BIN + "/alfa/omega/AA.class",
+ BIN + "/javac_state");
clean(GENSRC, BIN);
}
}
--- a/langtools/test/tools/sjavac/SJavacTester.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/SJavacTester.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -25,7 +25,6 @@
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
-import java.nio.charset.*;
import com.sun.tools.sjavac.Main;
@@ -35,16 +34,18 @@
+ "portfile=testportfile,"
+ "background=false";
+ final Path TEST_ROOT = Paths.get(getClass().getSimpleName());
+
// Generated sources that will test aspects of sjavac
- static final Path GENSRC = Paths.get("gensrc");
+ final Path GENSRC = TEST_ROOT.resolve("gensrc");
// Gensrc dirs used to test merging of serveral source roots.
- static final Path GENSRC2 = Paths.get("gensrc2");
- static final Path GENSRC3= Paths.get("gensrc3");
+ final Path GENSRC2 = TEST_ROOT.resolve("gensrc2");
+ final Path GENSRC3 = TEST_ROOT.resolve("gensrc3");
// Dir for compiled classes.
- static final Path BIN = Paths.get("bin");
+ final Path BIN = TEST_ROOT.resolve("bin");
// Dir for c-header files.
- Path HEADERS = Paths.get("headers");
+ final Path HEADERS = TEST_ROOT.resolve("headers");
// Remember the previous bin and headers state here.
Map<String,Long> previous_bin_state;
@@ -54,10 +55,10 @@
System.out.println("\nInitial compile of gensrc.");
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/AINT.java"),
- "package alfa.omega; public interface AINT { void aint(); }");
+ "package alfa.omega; public interface AINT { void aint(); }");
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A implements AINT { "+
- "public final static int DEFINITION = 17; public void aint() { } }");
+ "package alfa.omega; public class A implements AINT { "+
+ "public final static int DEFINITION = 17; public void aint() { } }");
tb.writeFile(GENSRC.resolve("alfa/omega/AA.java"),
"package alfa.omega;"+
"// A package private class, not contributing to the public api.\n"+
@@ -79,13 +80,17 @@
" // from outside of this source file, therefore it is ok.\n"+
"}\n");
tb.writeFile(GENSRC.resolve("beta/BINT.java"),
- "package beta;public interface BINT { void foo(); }");
+ "package beta;public interface BINT { void foo(); }");
tb.writeFile(GENSRC.resolve("beta/B.java"),
- "package beta; import alfa.omega.A; public class B {"+
- "private int b() { return A.DEFINITION; } native void foo(); }");
+ "package beta; import alfa.omega.A; public class B {"+
+ "private int b() { return A.DEFINITION; } native void foo(); }");
- compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
- SERVER_ARG, "--log=debug");
+ compile(GENSRC.toString(),
+ "-d", BIN.toString(),
+ "-h", HEADERS.toString(),
+ "-j", "1",
+ SERVER_ARG,
+ "--log=debug");
}
void removeFrom(Path dir, String... args) throws IOException {
--- a/langtools/test/tools/sjavac/SjavacBase.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/SjavacBase.java Fri Jun 12 16:40:05 2015 -0400
@@ -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
@@ -37,7 +37,7 @@
*/
public static int compile(Object... args) throws ReflectiveOperationException {
// Use reflection to avoid a compile-time dependency on sjavac Main
- System.err.println("compile: " + Arrays.toString(args));
+ System.out.println("compile: " + Arrays.toString(args));
Class<?> c = Class.forName("com.sun.tools.sjavac.Main");
Method m = c.getDeclaredMethod("go", String[].class);
String[] strArgs = new String[args.length];
--- a/langtools/test/tools/sjavac/StateDir.java Fri Jun 12 16:36:33 2015 -0400
+++ b/langtools/test/tools/sjavac/StateDir.java Fri Jun 12 16:40:05 2015 -0400
@@ -48,28 +48,29 @@
}
void test() throws Exception {
- Path bar = Paths.get("bar");
- Files.createDirectory(bar);
- Files.createDirectory(BIN);
-
- clean(GENSRC, BIN, bar);
+ clean(TEST_ROOT);
+ Path BAR = TEST_ROOT.resolve("bar");
+ Files.createDirectories(BAR);
+ Files.createDirectories(BIN);
Map<String,Long> previous_bin_state = collectState(BIN);
- Map<String,Long> previous_bar_state = collectState(bar);
+ Map<String,Long> previous_bar_state = collectState(BAR);
ToolBox tb = new ToolBox();
tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
- "package alfa.omega; public class A { }");
+ "package alfa.omega; public class A { }");
- compile("--state-dir=bar", "-src", "gensrc", "-d", "bin",
+ compile("--state-dir=" + BAR,
+ "-src", GENSRC.toString(),
+ "-d", BIN.toString(),
SJavacTester.SERVER_ARG);
Map<String,Long> new_bin_state = collectState(BIN);
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
- "bin/alfa/omega/A.class");
- Map<String,Long> new_bar_state = collectState(bar);
+ BIN + "/alfa/omega/A.class");
+ Map<String,Long> new_bar_state = collectState(BAR);
verifyThatFilesHaveBeenAdded(previous_bar_state, new_bar_state,
- "bar/javac_state");
- clean(GENSRC, BIN, bar);
+ BAR + "/javac_state");
+ clean(GENSRC, BIN, BAR);
}
}
--- a/langtools/test/tools/sjavac/test-input/src/nondependency/pkg26/Cls26.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 nondependency.pkg26;
-
-public class Cls26 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg/Test.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-// Use fully qualified names to avoid accidentally capturing dependencies in import statements.
-
-package pkg;
-
-import pkg2.*; // pkg2 as a whole
-import pkg3.Cls3; // pkg3.Cls3
-import pkg25.Cls25; // pkg25.Cls25
-import nondependency.pkg26.Cls26; // pkg26.Cls26 (but not nondependency)
-import pkg28.Cls28.Inner28; // pkg29.Cls28, pkg29.Cls28.Inner28
-import static pkg29.Cls29.Inner29; // pkg29.Cls29, pkg29.Cls29.Inner29
-import static pkg30.Cls30.*; // pkg30.Cls30 as a whole
-
-@pkg5.Anno5 // pkg5.Anno5
-public class Test<S extends pkg23.Cls23> // pkg23.Cls23
- extends pkg4.Cls4/*extends pkg11.Cls11*/<pkg6.Cls6/*extends pkg12.Cls12*/> // pkg4.Cls4, pkg11.Cls11, pkg6.Cls6, pkg12.Cls12
- implements pkg7.Cls7, pkg8.Cls8<pkg9.Cls9> { // pkg7.Cls7, pkg8.Cls8, pkg9.Cls9
-
- pkg27.Cls27 cls27[][][] = new pkg27.Cls27[0][0][0]; // pkg27.Cls27
-
- pkg2.Cls2 cls2;
- pkg19.Cls19 f19; // pkg19.Cls19
-
- public static void main(String[] args) { // java.lang.String
- pkg10.Cls10 o = new pkg10.Cls10(); // pkg10.Cls10
-
- o.getCls13().getCls14().getCls15(); // pkg13.Cls13, pkg14.Cls14, pkg15.Cls15
- pkg23.Cls23.f24 = null; // pkg23.Cls23, pkg24.Cls24
- }
-
- static pkg16.Cls16 m1(pkg17.Cls17 o) { // pkg16.Cls16, pkg17.Cls17
- return null;
- }
-
- public <T extends pkg18.Cls18> void m2() { // pkg18.Cls18
- }
-
- public <T> T m3() {
- T t;
- t = null;
- return t;
- }
-
- @pkg20.Anno20(pkg21.Cls21.class) // pkg20.Anno20, pkg21.Cls21
- private void m3(@pkg22.Anno22 String s) { // pkg22.Anno22
- Runnable r = () -> { System.out.println("hello"); };
- }
-
- private void m4() throws Cls25 { // pkg25.Cls25
- }
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg10/Cls10.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * 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 pkg10;
-public class Cls10 {
- public pkg13.Cls13 getCls13() {
- return null;
- }
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg11/Cls11.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg11; public class Cls11 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg12/Cls12.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg12; public class Cls12 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg13/Cls13.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * 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 pkg13;
-public class Cls13 {
- public pkg14.Cls14 getCls14() {
- return null;
- }
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg14/Cls14.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * 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 pkg14;
-public class Cls14 {
- public int[] getCls15() {
- return null;
- }
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg15/Cls15.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg15; public class Cls15 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg16/Cls16.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg16; public class Cls16 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg17/Cls17.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg17; public class Cls17 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg18/Cls18.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg18; public class Cls18 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg19/Cls19.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg19; public class Cls19 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg2/Cls2.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg2; public class Cls2 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg20/Anno20.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg20;
-public @interface Anno20 {
- Class<?> value();
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg21/Cls21.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg21; public class Cls21 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg22/Anno22.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg22;
-public @interface Anno22 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg23/Cls23.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg23;
-public class Cls23 {
- public static pkg24.Cls24 f24;
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg24/Cls24.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg24; public class Cls24 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg25/Cls25.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg25;
-
-public class Cls25 extends Throwable {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg27/Cls27.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * 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 pkg27;
-public class Cls27 {}
--- a/langtools/test/tools/sjavac/test-input/src/pkg28/Cls28.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg28;
-public class Cls28 {
- public static class Inner28 {}
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg29/Cls29.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg29;
-public class Cls29 {
- public static class Inner29 {}
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg3/Cls3.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg3; public class Cls3 { }
--- a/langtools/test/tools/sjavac/test-input/src/pkg30/Cls30.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * 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 pkg30;
-
-public class Cls30 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg4/Cls4.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg4;
-public class Cls4<T> extends pkg11.Cls11 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg5/Anno5.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg5;
-public @interface Anno5 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg6/Cls6.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg6;
-public class Cls6 extends pkg12.Cls12 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg7/Cls7.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg7;
-public interface Cls7 {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg8/Cls8.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * 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 pkg8;
-public interface Cls8<T> {
-}
--- a/langtools/test/tools/sjavac/test-input/src/pkg9/Cls9.java Fri Jun 12 16:36:33 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * 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 pkg9; public class Cls9 { }
--- a/make/CompileJavaModules.gmk Fri Jun 12 16:36:33 2015 -0400
+++ b/make/CompileJavaModules.gmk Fri Jun 12 16:40:05 2015 -0400
@@ -507,6 +507,10 @@
# space separated list.
JDK_USER_DEFINED_FILTER := $(strip $(subst $(COMMA),$(SPACE), $(JDK_FILTER)))
+# Create an empty directory to set the bootclasspath to.
+EMPTY_BOOTCLASSPATH := $(SUPPORT_OUTPUTDIR)/empty-dir
+$(call MakeDir, $(EMPTY_BOOTCLASSPATH))
+
# This macro sets up compilation of a module and declares dependencies for it.
# Param 1 - module name
define SetupModuleCompilation
@@ -525,7 +529,7 @@
$1_CLASSPATH := $$($1_CLASSPATH) $$(addprefix $(JDK_OUTPUTDIR)/modules/,jdk.hotspot.agent)
endif
$1_CLASSPATH := $$(subst $$(SPACE),$$(PATH_SEP),$$($1_CLASSPATH))
- $1_JAVAC_FLAGS := -bootclasspath "$$($1_CLASSPATH)" $$($1_ADD_JAVAC_FLAGS)
+ $1_JAVAC_FLAGS := -bootclasspath $(EMPTY_BOOTCLASSPATH) -classpath "$$($1_CLASSPATH)" $$($1_ADD_JAVAC_FLAGS)
$$(eval $$(call SetupJavaCompilation,$1, \
SETUP := $$(if $$($1_SETUP), $$($1_SETUP), GENERATE_JDKBYTECODE), \
--- a/make/common/JavaCompilation.gmk Fri Jun 12 16:36:33 2015 -0400
+++ b/make/common/JavaCompilation.gmk Fri Jun 12 16:40:05 2015 -0400
@@ -561,10 +561,6 @@
$$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
- # As a workaround for sjavac not tracking api changed from the classpath, force full
- # recompile if an external dependency, which is something other than a source
- # change, triggered this compilation.
- $$(if $$(filter-out $$($1_SRCS), $$?), $(FIND) $$(@D) -name "*.class" $(FIND_DELETE))
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling $1
($$($1_JVM) $$($1_SJAVAC) \
--- a/make/common/NativeCompilation.gmk Fri Jun 12 16:36:33 2015 -0400
+++ b/make/common/NativeCompilation.gmk Fri Jun 12 16:40:05 2015 -0400
@@ -449,6 +449,16 @@
$1_EXTRA_CXXFLAGS+=$$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release)
endif
+ # If no C++ flags are explicitly set, default to using the C flags.
+ # After that, we can set additional C++ flags that should not interfere
+ # with the mechanism for copying the C flags by default.
+ ifeq ($$($1_CXXFLAGS),)
+ $1_CXXFLAGS:=$$($1_CFLAGS)
+ endif
+ ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)),)
+ $1_EXTRA_CXXFLAGS:=$$($1_EXTRA_CFLAGS)
+ endif
+
ifeq ($$($1_DEBUG_SYMBOLS), true)
ifeq ($(ENABLE_DEBUG_SYMBOLS), true)
ifdef OPENJDK
@@ -466,16 +476,6 @@
endif
endif
- # If no C++ flags are explicitly set, default to using the C flags.
- # After that, we can set additional C++ flags that should not interfere
- # with the mechanism for copying the C flags by default.
- ifeq ($$($1_CXXFLAGS),)
- $1_CXXFLAGS:=$$($1_CFLAGS)
- endif
- ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)),)
- $1_EXTRA_CXXFLAGS:=$$($1_EXTRA_CFLAGS)
- endif
-
ifneq (,$$($1_REORDER))
$1_EXTRA_CFLAGS += $$(C_FLAG_REORDER)
$1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER)
--- a/nashorn/.hgtags Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/.hgtags Fri Jun 12 16:40:05 2015 -0400
@@ -301,3 +301,4 @@
2054d01ae32649d3179e93d14108fdd6259c1c0d jdk9-b65
9dd95cff9dae897e8dee712f1f0303c460262288 jdk9-b66
f822b749821e364cae0b7bd7c8f667d9437e6d83 jdk9-b67
+dd6dd848b854dbd3f3cc422668276b1ae0834179 jdk9-b68
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/autoimports.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,151 @@
+# autoimports script requires -scripting mode
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * It is tedious to import Java classes used in a script. Sometimes it is easier
+ * use simple names of java classes and have a script auto import Java classes.
+ * You can load this script at the start of an interactive jjs session or at the
+ * start of your script. This script defines a __noSuchProperty__ hook to auto
+ * import Java classes as needed and when they are referred to for the first time
+ * in your script. You can also call the "autoimports" function to print script
+ * statements that you need to use in your script, i.e., have the function generate
+ * a script to import Java classes used by your script so far. After running your
+ * script, you can call autoimports to get the exact Java imports you need and replace
+ * the autoimports load with the generated import statements (to avoid costly init of
+ * the autoimports script).
+ */
+
+(function() {
+ var ArrayList = Java.type("java.util.ArrayList");
+ var HashMap = Java.type("java.util.HashMap");
+ var Files = Java.type("java.nio.file.Files");
+ var FileSystems = Java.type("java.nio.file.FileSystems");
+ var URI = Java.type("java.net.URI");
+
+ // initialize a class to package map by iterating all
+ // classes available in the system by walking through "jrt fs"
+ var fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+ var root = fs.getPath('/');
+
+ var clsToPkg = new HashMap();
+
+ function addToClsToPkg(c, p) {
+ if (clsToPkg.containsKey(c)) {
+ var val = clsToPkg.get(c);
+ if (val instanceof ArrayList) {
+ val.add(p);
+ } else {
+ var al = new ArrayList();
+ al.add(val);
+ al.add(p);
+ clsToPkg.put(c, al);
+ }
+ } else {
+ clsToPkg.put(c, p);
+ }
+ }
+
+ // handle collision and allow user to choose package
+ function getPkgOfCls(c) {
+ var val = clsToPkg.get(c);
+ if (val instanceof ArrayList) {
+ var count = 1;
+ print("Multiple matches for " + c + ", choose package:");
+ for each (var v in val) {
+ print(count + ". " + v);
+ count++;
+ }
+ var choice = parseInt(readLine());
+ if (isNaN(choice) || choice < 1 || choice > val.size()) {
+ print("invalid choice: " + choice);
+ return undefined;
+ }
+ return val.get(choice - 1);
+ } else {
+ return val;
+ }
+ }
+
+ Files.walk(root).forEach(function(p) {
+ if (Files.isRegularFile(p)) {
+ var str = p.toString();
+ if (str.endsWith(".class")) {
+ str = str.substring(1);
+ var idx = str.indexOf('/');
+ if (idx != -1) {
+ str = str.substring(idx + 1);
+ if (str.startsWith("java") ||
+ str.startsWith("javax") ||
+ str.startsWith("org")) {
+ var lastIdx = str.lastIndexOf('/');
+ if (lastIdx != -1) {
+ var pkg = str.substring(0, lastIdx).replaceAll('/', '.');
+ var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class"));
+ addToClsToPkg(cls, pkg);
+ }
+ }
+ }
+ }
+ }
+ });
+
+ var imports = new ArrayList();
+ var global = this;
+ var oldNoSuchProp = global.__noSuchProperty__;
+ this.__noSuchProperty__ = function(name) {
+ 'use strict';
+
+ if (clsToPkg.containsKey(name)) {
+ var pkg = getPkgOfCls(name);
+ if (pkg) {
+ var clsName = pkg + "." + name;
+ imports.add("var " + name + " = Java.type('" + clsName + "');");
+ return global[name] = Java.type(clsName);
+ }
+ } else if (typeof oldNoSuchProp == 'function') {
+ return oldNoSuchProp.call(this, name);
+ }
+
+ if (typeof this == 'undefined') {
+ throw new ReferenceError(name);
+ } else {
+ return undefined;
+ }
+ }
+
+ this.autoimports = function() {
+ for each (var im in imports) {
+ print(im);
+ }
+ }
+})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/dateconversion.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Converting between #javascript Date and #java8 LocalDateTime with #nashorn
+
+// JavaScript Date with current time
+var d = new Date();
+print(d);
+
+// Java 8 java.time classes used
+var Instant = java.time.Instant;
+var LocalDateTime = java.time.LocalDateTime;
+var ZoneId = java.time.ZoneId;
+
+// Date.prototype.getTime
+
+// getTime() method returns the numeric value corresponding to the time
+// for the specified date according to universal time. The value returned
+// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
+// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
+
+// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long-
+
+var instant = Instant.ofEpochMilli(d.getTime());
+
+// Instant to LocalDateTime using LocalDateTime.ofInstant
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId-
+
+var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+print(ldt);
+
+// converting a LocalDateTime to JavaScript Date
+// convert LocalDateTime to Instant first
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId-
+
+var instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
+
+// instant to to epoch milliseconds
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli--
+// and then to JavaScript Date from time in milliseconds
+// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
+
+var d1 = new Date(instant.toEpochMilli());
+print(d1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/exec.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,50 @@
+# exec script requires -scripting mode
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// The $EXEC builtin function can be used to run external commands:
+$EXEC("ls")
+$EXEC("ls -la")
+
+// It can also be given a string to use as stdin:
+$EXEC("cat", "Hello, world!")
+
+// Additional arguments can be passed after the stdin argument, as an array of
+// strings, or a sequence of varargs:
+$EXEC("ls", "" /* no stdin */, "-l", "-a")
+$EXEC("ls", "" /* no stdin */, ["-l", "-a"])
+
+// Output of running external commands is returned from $EXEC:
+print($EXEC("ls"))
+
+// apply on $EXEC
+print($EXEC.apply(this, ["ls"]));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/javahelp.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// script helpers to print meta info on Java instances and classes
+
+// print instance methods info on a Java object or static methods info of a Java class
+function methods(jobj) {
+ if (! Java.isJavaObject(jobj)) {
+ throw new TypeError("not a Java object");
+ }
+
+ var isStatic = Java.isType(jobj);
+ var obj = Object.bindProperties({}, jobj);
+ for each (var i in obj) {
+ if (Java.isJavaMethod(i)) {
+ var str = String(i);
+ var idx = str.indexOf(' ');
+ var overloaded = str.substring(0, idx).endsWith("OverloadedDynamicMethod");
+ var lastIdx = isStatic? str.lastIndexOf('] on') : str.lastIndexOf(']');
+ print(str.substring(idx + 1, lastIdx) + (overloaded? "*" : ""))
+ }
+ }
+}
+
+// print instance field names of a Java object or static field names of a Java class
+function fields(jobj) {
+ if (! Java.isJavaObject(jobj)) {
+ throw new TypeError("not a Java object");
+ }
+
+ var obj = Object.bindProperties({}, jobj);
+ for (var i in obj) {
+ if (! Java.isJavaMethod(obj[i])) {
+ print(i);
+ }
+ }
+}
+
+undefined;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/secondssince.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,43 @@
+# usage: jjs secondssince.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Number of seconds elapsed since the specified Instance #nashorn #javascript #java
+// Input date and time in ISO 8601 format
+// Example: 2001-01-01T00:00:00Z for 1 Jan 2001, 0 GMT
+
+var Instant = java.time.Instant;
+var ChronoUnit = java.time.temporal.ChronoUnit;
+print("Enter date time:");
+var sec = Instant.parse(readLine()).
+ until(Instant.now(), ChronoUnit.SECONDS);
+print(sec);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Fri Jun 12 16:40:05 2015 -0400
@@ -99,10 +99,12 @@
import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
/**
- * The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
- * create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
- * methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class
- * per language runtime to contain one linker instance as:
+ * The linker for {@link RelinkableCallSite} objects. Users of it (scripting
+ * frameworks and language runtimes) have to create a linker using the
+ * {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic
+ * bootstrap methods to set the target of all the call sites in the code they
+ * generate. Usual usage would be to create one class per language runtime to
+ * contain one linker instance as:
*
* <pre>
* class MyLanguageRuntime {
@@ -123,19 +125,27 @@
*
* Note how there are three components you will need to provide here:
* <ul>
- * <li>You're expected to provide a {@link GuardingDynamicLinker} for your own language. If your runtime doesn't
- * have its own language and/or object model (i.e. it's a generic scripting shell), you don't need to implement a
- * dynamic linker; you would simply not invoke the {@code setPrioritizedLinker} method on the factory, or even better,
- * simply use {@link DefaultBootstrapper}.</li>
- * <li>The performance of the programs can depend on your choice of the class to represent call sites. The above
- * example used {@link MonomorphicCallSite}, but you might want to use {@link ChainedCallSite} instead. You'll need to
- * experiment and decide what fits your language runtime the best. You can subclass either of these or roll your own if
- * you need to.</li>
- * <li>You also need to provide {@link CallSiteDescriptor}s to your call sites. They are immutable objects that contain
- * all the information about the call site: the class performing the lookups, the name of the method being invoked, and
- * the method signature. The library has a default {@link CallSiteDescriptorFactory} for descriptors that you can use,
- * or you can create your own descriptor classes, especially if you need to add further information (values passed in
+ *
+ * <li>You're expected to provide a {@link GuardingDynamicLinker} for your own
+ * language. If your runtime doesn't have its own language and/or object model
+ * (i.e., it's a generic scripting shell), you don't need to implement a dynamic
+ * linker; you would simply not invoke the {@code setPrioritizedLinker} method
+ * on the factory, or even better, simply use {@link DefaultBootstrapper}.</li>
+ *
+ * <li>The performance of the programs can depend on your choice of the class to
+ * represent call sites. The above example used {@link MonomorphicCallSite}, but
+ * you might want to use {@link ChainedCallSite} instead. You'll need to
+ * experiment and decide what fits your language runtime the best. You can
+ * subclass either of these or roll your own if you need to.</li>
+ *
+ * <li>You also need to provide {@link CallSiteDescriptor}s to your call sites.
+ * They are immutable objects that contain all the information about the call
+ * site: the class performing the lookups, the name of the method being invoked,
+ * and the method signature. The library has a default {@link CallSiteDescriptorFactory}
+ * for descriptors that you can use, or you can create your own descriptor
+ * classes, especially if you need to add further information (values passed in
* additional parameters to the bootstrap method) to them.</li>
+ *
* </ul>
*
* @author Attila Szegedi
@@ -176,11 +186,15 @@
}
/**
- * Links an invokedynamic call site. It will install a method handle into the call site that invokes the relinking
- * mechanism of this linker. Next time the call site is invoked, it will be linked for the actual arguments it was
- * invoked with.
+ * Links an invokedynamic call site. It will install a method handle into
+ * the call site that invokes the relinking mechanism of this linker. Next
+ * time the call site is invoked, it will be linked for the actual arguments
+ * it was invoked with.
*
+ * @param <T> the particular subclass of {@link RelinkableCallSite} for
+ * which to create a link.
* @param callSite the call site to link.
+ *
* @return the callSite, for easy call chaining.
*/
public <T extends RelinkableCallSite> T link(final T callSite) {
@@ -189,10 +203,13 @@
}
/**
- * Returns the object representing the lower level linker services of this class that are normally exposed to
- * individual language-specific linkers. While as a user of this class you normally only care about the
- * {@link #link(RelinkableCallSite)} method, in certain circumstances you might want to use the lower level services
- * directly; either to lookup specific method handles, to access the type converters, and so on.
+ * Returns the object representing the lower level linker services of this
+ * class that are normally exposed to individual language-specific linkers.
+ * While as a user of this class you normally only care about the
+ * {@link #link(RelinkableCallSite)} method, in certain circumstances you
+ * might want to use the lower level services directly; either to lookup
+ * specific method handles, to access the type converters, and so on.
+ *
* @return the object representing the linker services of this class.
*/
public LinkerServices getLinkerServices() {
@@ -218,7 +235,9 @@
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
+ *
* @return return the method handle for the invocation
+ *
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
@@ -272,11 +291,15 @@
}
/**
- * Returns a stack trace element describing the location of the call site currently being linked on the current
- * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially
- * expensive. The recommended usage for it is in writing diagnostics code.
- * @return a stack trace element describing the location of the call site currently being linked, or null if it is
- * not invoked while a call site is being linked.
+ * Returns a stack trace element describing the location of the call site
+ * currently being linked on the current thread. The operation internally
+ * creates a Throwable object and inspects its stack trace, so it's
+ * potentially expensive. The recommended usage for it is in writing
+ * diagnostics code.
+ *
+ * @return a stack trace element describing the location of the call site
+ * currently being linked, or null if it is not invoked while a call
+ * site is being linked.
*/
public static StackTraceElement getLinkedCallSiteLocation() {
final StackTraceElement[] trace = new Throwable().getStackTrace();
@@ -290,8 +313,10 @@
}
/**
- * Deprecated because of not precise name.
+ * Deprecated because of imprecise name.
+ *
* @deprecated Use {@link #getLinkedCallSiteLocation()} instead.
+ *
* @return see non-deprecated method
*/
@Deprecated
@@ -300,20 +325,26 @@
}
/**
- * Returns true if the frame represents {@code MethodHandleNatives.linkCallSite()}, the frame immediately on top of
- * the call site frame when the call site is being linked for the first time.
+ * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()},
+ * the frame immediately on top of the call site frame when the call site is
+ * being linked for the first time.
+ *
* @param frame the frame
- * @return true if this frame represents {@code MethodHandleNatives.linkCallSite()}
+ *
+ * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}.
*/
private static boolean isInitialLinkFrame(final StackTraceElement frame) {
return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME);
}
/**
- * Returns true if the frame represents {@code DynamicLinker.relink()}, the frame immediately on top of the call
- * site frame when the call site is being relinked (linked for second and subsequent times).
+ * Returns {@code true} if the frame represents {@code DynamicLinker.relink()},
+ * the frame immediately on top of the call site frame when the call site is
+ * being relinked (linked for second and subsequent times).
+ *
* @param frame the frame
- * @return true if this frame represents {@code DynamicLinker.relink()}
+ *
+ * @return {@code true} if this frame represents {@code DynamicLinker.relink()}.
*/
private static boolean isRelinkFrame(final StackTraceElement frame) {
return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Fri Jun 12 16:40:05 2015 -0400
@@ -178,8 +178,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
- Objects.requireNonNull(classFilter);
- return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter);
+ return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), Objects.requireNonNull(classFilter));
}
/**
@@ -193,8 +192,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String... args) {
- Objects.requireNonNull(args);
- return newEngine(args, getAppClassLoader(), null);
+ return newEngine(Objects.requireNonNull(args), getAppClassLoader(), null);
}
/**
@@ -209,8 +207,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
- Objects.requireNonNull(args);
- return newEngine(args, appLoader, null);
+ return newEngine(Objects.requireNonNull(args), appLoader, null);
}
/**
@@ -226,9 +223,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
- Objects.requireNonNull(args);
- Objects.requireNonNull(classFilter);
- return newEngine(args, appLoader, classFilter);
+ return newEngine(Objects.requireNonNull(args), appLoader, Objects.requireNonNull(classFilter));
}
private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Jun 12 16:40:05 2015 -0400
@@ -255,14 +255,12 @@
@Override
public void removeMember(final String name) {
- Objects.requireNonNull(name);
- remove(name);
+ remove(Objects.requireNonNull(name));
}
@Override
public void setMember(final String name, final Object value) {
- Objects.requireNonNull(name);
- put(name, value);
+ put(Objects.requireNonNull(name), value);
}
@Override
@@ -429,7 +427,7 @@
@Override
public void putAll(final Map<? extends String, ? extends Object> map) {
- Objects.requireNonNull(map, "map is null");
+ Objects.requireNonNull(map);
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
inGlobal(new Callable<Object>() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/URLReader.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/URLReader.java Fri Jun 12 16:40:05 2015 -0400
@@ -78,8 +78,7 @@
* @throws NullPointerException if url is null
*/
public URLReader(final URL url, final Charset cs) {
- Objects.requireNonNull(url);
- this.url = url;
+ this.url = Objects.requireNonNull(url);
this.cs = cs;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java Fri Jun 12 16:40:05 2015 -0400
@@ -58,15 +58,13 @@
@Override
public CompilationUnitTree parse(final File file, final DiagnosticListener listener) throws IOException, NashornException {
- Objects.requireNonNull(file);
- final Source src = Source.sourceFor(file.getName(), file);
+ final Source src = Source.sourceFor(Objects.requireNonNull(file).getName(), file);
return translate(makeParser(src, listener).parse());
}
@Override
public CompilationUnitTree parse(final Path path, final DiagnosticListener listener) throws IOException, NashornException {
- Objects.requireNonNull(path);
- final Source src = Source.sourceFor(path.toString(), path);
+ final Source src = Source.sourceFor(Objects.requireNonNull(path).toString(), path);
return translate(makeParser(src, listener).parse());
}
@@ -78,9 +76,7 @@
@Override
public CompilationUnitTree parse(final String name, final Reader reader, final DiagnosticListener listener) throws IOException, NashornException {
- Objects.requireNonNull(name);
- Objects.requireNonNull(reader);
- final Source src = Source.sourceFor(name, reader);
+ final Source src = Source.sourceFor(Objects.requireNonNull(name), Objects.requireNonNull(reader));
return translate(makeParser(src, listener).parse());
}
@@ -92,8 +88,7 @@
@Override
public CompilationUnitTree parse(final ScriptObjectMirror scriptObj, final DiagnosticListener listener) throws NashornException {
- Objects.requireNonNull(scriptObj);
- final Map<?,?> map = scriptObj;
+ final Map<?,?> map = Objects.requireNonNull(scriptObj);
if (map.containsKey("script") && map.containsKey("name")) {
final String script = JSType.toString(map.get("script"));
final String name = JSType.toString(map.get("name"));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java Fri Jun 12 16:40:05 2015 -0400
@@ -100,7 +100,6 @@
* There is also a very nice debug interface that can emit formatted
* bytecodes that have been written. This is enabled by setting the
* environment "nashorn.codegen.debug" to true, or --log=codegen:{@literal <level>}
- * <p>
*
* @see Compiler
*/
@@ -144,7 +143,7 @@
/**
* Constructor - only used internally in this class as it breaks
- * abstraction towards ASM or other code generator below
+ * abstraction towards ASM or other code generator below.
*
* @param env script environment
* @param cw ASM classwriter
@@ -157,7 +156,8 @@
}
/**
- * Return the method names encountered
+ * Return the method names encountered.
+ *
* @return method names
*/
public Set<String> getMethodNames() {
@@ -165,12 +165,13 @@
}
/**
- * Constructor
+ * Constructor.
*
* @param env script environment
* @param className name of class to weave
* @param superClassName super class name for class
- * @param interfaceNames names of interfaces implemented by this class, or null if none
+ * @param interfaceNames names of interfaces implemented by this class, or
+ * {@code null} if none
*/
ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) {
this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
@@ -178,7 +179,7 @@
}
/**
- * Constructor from the compiler
+ * Constructor from the compiler.
*
* @param env Script environment
* @param sourceName Source name
@@ -217,7 +218,6 @@
}
/**
- * Returns the name of the compile unit class name.
* @return the name of the compile unit class name.
*/
String getUnitClassName() {
@@ -225,7 +225,8 @@
}
/**
- * Get the method count, including init and clinit methods
+ * Get the method count, including init and clinit methods.
+ *
* @return method count
*/
public int getMethodCount() {
@@ -233,7 +234,8 @@
}
/**
- * Get the clinit count
+ * Get the clinit count.
+ *
* @return clinit count
*/
public int getClinitCount() {
@@ -241,7 +243,8 @@
}
/**
- * Get the init count
+ * Get the init count.
+ *
* @return init count
*/
public int getInitCount() {
@@ -249,7 +252,8 @@
}
/**
- * Get the field count
+ * Get the field count.
+ *
* @return field count
*/
public int getFieldCount() {
@@ -260,6 +264,7 @@
* Convert a binary name to a package/class name.
*
* @param name Binary name.
+ *
* @return Package/class name.
*/
private static String pathName(final String name) {
@@ -268,6 +273,7 @@
/**
* Define the static fields common in all scripts.
+ *
* @param strictMode Should we generate this method in strict mode
*/
private void defineCommonStatics(final boolean strictMode) {
@@ -284,8 +290,8 @@
}
/**
- * Define static utilities common needed in scripts. These are per compile unit
- * and therefore have to be defined here and not in code gen.
+ * Define static utilities common needed in scripts. These are per compile
+ * unit and therefore have to be defined here and not in code gen.
*/
private void defineCommonUtilities() {
assert unitClassName != null;
@@ -333,7 +339,9 @@
}
/**
- * Constructs a primitive specific method for getting the ith entry from the constants table as an array.
+ * Constructs a primitive specific method for getting the ith entry from the
+ * constants table as an array.
+ *
* @param clazz Array class.
*/
private void defineGetArrayMethod(final Class<?> clazz) {
@@ -356,7 +364,9 @@
/**
* Generate the name of a get array from constant pool method.
+ *
* @param clazz Name of array class.
+ *
* @return Method name.
*/
static String getArrayMethodName(final Class<?> clazz) {
@@ -366,6 +376,7 @@
/**
* Ensure a get constant method is issued for the class.
+ *
* @param clazz Class of constant.
*/
void needGetConstantMethod(final Class<?> clazz) {
@@ -373,12 +384,12 @@
}
/**
- * Inspect class name and decide whether we are generating a ScriptObject class
+ * Inspect class name and decide whether we are generating a ScriptObject class.
*
* @param scriptPrefix the script class prefix for the current script
* @param type the type to check
*
- * @return true if type is ScriptObject
+ * @return {@code true} if type is ScriptObject
*/
private static boolean isScriptObject(final String scriptPrefix, final String type) {
if (type.startsWith(scriptPrefix)) {
@@ -393,14 +404,14 @@
}
/**
- * Call at beginning of class emission
+ * Call at beginning of class emission.
*/
public void begin() {
classStarted = true;
}
/**
- * Call at end of class emission
+ * Call at end of class emission.
*/
public void end() {
assert classStarted : "class not started for " + unitClassName;
@@ -424,7 +435,9 @@
/**
* Disassemble an array of byte code.
+ *
* @param bytecode byte array representing bytecode
+ *
* @return disassembly as human readable string
*/
static String disassemble(final byte[] bytecode) {
@@ -446,7 +459,7 @@
}
/**
- * Call back from MethodEmitter for method start
+ * Call back from MethodEmitter for method start.
*
* @see MethodEmitter
*
@@ -458,7 +471,7 @@
}
/**
- * Call back from MethodEmitter for method end
+ * Call back from MethodEmitter for method end.
*
* @see MethodEmitter
*
@@ -470,7 +483,7 @@
}
/**
- * Add a new method to the class - defaults to public method
+ * Add a new method to the class - defaults to public method.
*
* @param methodName name of method
* @param rtype return type of the method
@@ -483,7 +496,7 @@
}
/**
- * Add a new method to the class - defaults to public method
+ * Add a new method to the class - defaults to public method.
*
* @param methodFlags access flags for the method
* @param methodName name of method
@@ -499,7 +512,7 @@
}
/**
- * Add a new method to the class - defaults to public method
+ * Add a new method to the class - defaults to public method.
*
* @param methodName name of method
* @param descriptor descriptor of method
@@ -511,7 +524,7 @@
}
/**
- * Add a new method to the class - defaults to public method
+ * Add a new method to the class - defaults to public method.
*
* @param methodFlags access flags for the method
* @param methodName name of method
@@ -526,9 +539,10 @@
}
/**
- * Add a new method to the class, representing a function node
+ * Add a new method to the class, representing a function node.
*
* @param functionNode the function node to generate a method for
+ *
* @return method emitter to use for weaving this method
*/
MethodEmitter method(final FunctionNode functionNode) {
@@ -546,9 +560,11 @@
}
/**
- * Add a new method to the class, representing a rest-of version of the function node
+ * Add a new method to the class, representing a rest-of version of the
+ * function node.
*
* @param functionNode the function node to generate a method for
+ *
* @return method emitter to use for weaving this method
*/
MethodEmitter restOfMethod(final FunctionNode functionNode) {
@@ -566,7 +582,7 @@
/**
- * Start generating the <clinit> method in the class
+ * Start generating the <clinit> method in the class.
*
* @return method emitter to use for weaving <clinit>
*/
@@ -576,7 +592,7 @@
}
/**
- * Start generating an <init>()V method in the class
+ * Start generating an <init>()V method in the class.
*
* @return method emitter to use for weaving <init>()V
*/
@@ -586,7 +602,7 @@
}
/**
- * Start generating an <init>()V method in the class
+ * Start generating an <init>()V method in the class.
*
* @param ptypes parameter types for constructor
* @return method emitter to use for weaving <init>()V
@@ -597,7 +613,7 @@
}
/**
- * Start generating an <init>(...)V method in the class
+ * Start generating an <init>(...)V method in the class.
*
* @param flags access flags for the constructor
* @param ptypes parameter types for the constructor
@@ -610,7 +626,7 @@
}
/**
- * Add a field to the class, initialized to a value
+ * Add a field to the class, initialized to a value.
*
* @param fieldFlags flags, e.g. should it be static or public etc
* @param fieldName name of field
@@ -625,7 +641,7 @@
}
/**
- * Add a field to the class
+ * Add a field to the class.
*
* @param fieldFlags access flags for the field
* @param fieldName name of field
@@ -638,7 +654,7 @@
}
/**
- * Add a field to the class - defaults to public
+ * Add a field to the class - defaults to public.
*
* @param fieldName name of field
* @param fieldType type of field
@@ -651,7 +667,8 @@
* Return a bytecode array from this ClassEmitter. The ClassEmitter must
* have been ended (having its end function called) for this to work.
*
- * @return byte code array for generated class, null if class generation hasn't been ended with {@link ClassEmitter#end()}
+ * @return byte code array for generated class, {@code null} if class
+ * generation hasn't been ended with {@link ClassEmitter#end()}.
*/
byte[] toByteArray() {
assert classEnded;
@@ -663,13 +680,9 @@
}
/**
- * Abstraction for flags used in class emission
- *
- * We provide abstraction separating these from the underlying bytecode
- * emitter.
- *
- * Flags are provided for method handles, protection levels, static/virtual
- * fields/methods.
+ * Abstraction for flags used in class emission. We provide abstraction
+ * separating these from the underlying bytecode emitter. Flags are provided
+ * for method handles, protection levels, static/virtual fields/methods.
*/
static enum Flag {
/** method handle with static access */
@@ -707,10 +720,12 @@
}
/**
- * Return the corresponding ASM flag value for an enum set of flags
+ * Return the corresponding ASM flag value for an enum set of flags.
*
* @param flags enum set of flags
- * @return an integer value representing the flags intrinsic values or:ed together
+ *
+ * @return an integer value representing the flags intrinsic values
+ * or:ed together
*/
static int getValue(final EnumSet<Flag> flags) {
int v = 0;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Fri Jun 12 16:40:05 2015 -0400
@@ -122,8 +122,7 @@
* @param clazz class with code for this compile unit
*/
void setCode(final Class<?> clazz) {
- Objects.requireNonNull(clazz);
- this.clazz = clazz;
+ this.clazz = Objects.requireNonNull(clazz);
// Revisit this - refactor to avoid null-ed out non-final fields
// null out emitter
this.classEmitter = null;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,11 +31,13 @@
import jdk.nashorn.internal.runtime.Source;
/**
- * A class that tracks the current lexical context of node visitation as a stack of {@link Block} nodes. Has special
- * methods to retrieve useful subsets of the context.
+ * A class that tracks the current lexical context of node visitation as a stack
+ * of {@link Block} nodes. Has special methods to retrieve useful subsets of the
+ * context.
*
- * This is implemented with a primitive array and a stack pointer, because it really makes a difference
- * performance wise. None of the collection classes were optimal
+ * This is implemented with a primitive array and a stack pointer, because it
+ * really makes a difference performance-wise. None of the collection classes
+ * were optimal.
*/
public class LexicalContext {
private LexicalContextNode[] stack;
@@ -79,6 +81,7 @@
* {@link Block#NEEDS_SCOPE} because it atomically also sets the
* {@link FunctionNode#HAS_SCOPE_BLOCK} flag on the block's containing
* function.
+ *
* @param block the block that needs to be marked as creating a scope.
*/
public void setBlockNeedsScope(final Block block) {
@@ -97,8 +100,10 @@
}
/**
- * Get the flags for a lexical context node on the stack
+ * Get the flags for a lexical context node on the stack.
+ *
* @param node node
+ *
* @return the flags for the node
*/
public int getFlags(final LexicalContextNode node) {
@@ -112,8 +117,10 @@
/**
* Get the function body of a function node on the lexical context
- * stack. This will trigger an assertion if node isn't present
+ * stack. This will trigger an assertion if node isn't present.
+ *
* @param functionNode function node
+ *
* @return body of function node
*/
public Block getFunctionBody(final FunctionNode functionNode) {
@@ -126,15 +133,16 @@
}
/**
- * Return all nodes in the LexicalContext
- * @return all nodes
+ * @return all nodes in the LexicalContext.
*/
public Iterator<LexicalContextNode> getAllNodes() {
return new NodeIterator<>(LexicalContextNode.class);
}
/**
- * Returns the outermost function in this context. It is either the program, or a lazily compiled function.
+ * Returns the outermost function in this context. It is either the program,
+ * or a lazily compiled function.
+ *
* @return the outermost function in this context.
*/
public FunctionNode getOutermostFunction() {
@@ -142,8 +150,12 @@
}
/**
- * Pushes a new block on top of the context, making it the innermost open block.
+ * Pushes a new block on top of the context, making it the innermost open
+ * block.
+ *
+ * @param <T> the type of the new node
* @param node the new node
+ *
* @return the node that was pushed
*/
public <T extends LexicalContextNode> T push(final T node) {
@@ -168,25 +180,28 @@
/**
* Is the context empty?
- * @return true if empty
+ *
+ * @return {@code true} if empty
*/
public boolean isEmpty() {
return sp == 0;
}
/**
- * The depth of the lexical context
- * @return depth
+ * @return the depth of the lexical context.
*/
public int size() {
return sp;
}
/**
- * Pops the innermost block off the context and all nodes that has been contributed
- * since it was put there
+ * Pops the innermost block off the context and all nodes that has been
+ * contributed since it was put there.
*
- * @param node the node expected to be popped, used to detect unbalanced pushes/pops
+ * @param <T> the type of the node to be popped
+ * @param node the node expected to be popped, used to detect unbalanced
+ * pushes/pops
+ *
* @return the node that was popped
*/
@SuppressWarnings("unchecked")
@@ -202,11 +217,17 @@
}
/**
- * Explicitly apply flags to the topmost element on the stack. This is only valid to use from a
- * {@code NodeVisitor.leaveXxx()} method and only on the node being exited at the time. It is not mandatory to use,
- * as {@link #pop(Node)} will apply the flags automatically, but this method can be used to apply them
- * during the {@code leaveXxx()} method in case its logic depends on the value of the flags.
- * @param node the node to apply the flags to. Must be the topmost node on the stack.
+ * Explicitly apply flags to the topmost element on the stack. This is only
+ * valid to use from a {@code NodeVisitor.leaveXxx()} method and only on the
+ * node being exited at the time. It is not mandatory to use, as
+ * {@link #pop(Node)} will apply the flags automatically, but this method
+ * can be used to apply them during the {@code leaveXxx()} method in case
+ * its logic depends on the value of the flags.
+ *
+ * @param <T> the type of the node to apply the flags to.
+ * @param node the node to apply the flags to. Must be the topmost node on
+ * the stack.
+ *
* @return the passed in node, or a modified node (if any flags were modified)
*/
public <T extends LexicalContextNode & Flags<T>> T applyTopFlags(final T node) {
@@ -215,7 +236,8 @@
}
/**
- * Return the top element in the context
+ * Return the top element in the context.
+ *
* @return the node that was pushed last
*/
public LexicalContextNode peek() {
@@ -223,9 +245,11 @@
}
/**
- * Check if a node is in the lexical context
+ * Check if a node is in the lexical context.
+ *
* @param node node to check for
- * @return true if in the context
+ *
+ * @return {@code true} if in the context
*/
public boolean contains(final LexicalContextNode node) {
for (int i = 0; i < sp; i++) {
@@ -242,6 +266,7 @@
*
* @param oldNode old node
* @param newNode new node
+ *
* @return the new node
*/
public LexicalContextNode replace(final LexicalContextNode oldNode, final LexicalContextNode newNode) {
@@ -256,7 +281,9 @@
}
/**
- * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first.
+ * Returns an iterator over all blocks in the context, with the top block
+ * (innermost lexical context) first.
+ *
* @return an iterator over all blocks in the context.
*/
public Iterator<Block> getBlocks() {
@@ -264,7 +291,9 @@
}
/**
- * Returns an iterator over all functions in the context, with the top (innermost open) function first.
+ * Returns an iterator over all functions in the context, with the top
+ * (innermost open) function first.
+ *
* @return an iterator over all functions in the context.
*/
public Iterator<FunctionNode> getFunctions() {
@@ -273,6 +302,7 @@
/**
* Get the parent block for the current lexical context block
+ *
* @return parent block
*/
public Block getParentBlock() {
@@ -283,7 +313,9 @@
/**
* Gets the label node of the current block.
- * @return the label node of the current block, if it is labeled. Otherwise returns null.
+ *
+ * @return the label node of the current block, if it is labeled. Otherwise
+ * returns {@code null}.
*/
public LabelNode getCurrentBlockLabelNode() {
assert stack[sp - 1] instanceof Block;
@@ -294,21 +326,12 @@
return parent instanceof LabelNode ? (LabelNode)parent : null;
}
-
- /*
- public FunctionNode getProgram() {
- final Iterator<FunctionNode> iter = getFunctions();
- FunctionNode last = null;
- while (iter.hasNext()) {
- last = iter.next();
- }
- assert last != null;
- return last;
- }*/
-
/**
- * Returns an iterator over all ancestors block of the given block, with its parent block first.
+ * Returns an iterator over all ancestors block of the given block, with its
+ * parent block first.
+ *
* @param block the block whose ancestors are returned
+ *
* @return an iterator over all ancestors block of the given block.
*/
public Iterator<Block> getAncestorBlocks(final Block block) {
@@ -323,8 +346,11 @@
}
/**
- * Returns an iterator over a block and all its ancestors blocks, with the block first.
+ * Returns an iterator over a block and all its ancestors blocks, with the
+ * block first.
+ *
* @param block the block that is the starting point of the iteration.
+ *
* @return an iterator over a block and all its ancestors.
*/
public Iterator<Block> getBlocks(final Block block) {
@@ -352,7 +378,9 @@
/**
* Get the function for this block.
+ *
* @param block block for which to get function
+ *
* @return function for block
*/
public FunctionNode getFunction(final Block block) {
@@ -373,7 +401,6 @@
}
/**
- * Returns the innermost block in the context.
* @return the innermost block in the context.
*/
public Block getCurrentBlock() {
@@ -381,7 +408,6 @@
}
/**
- * Returns the innermost function in the context.
* @return the innermost function in the context.
*/
public FunctionNode getCurrentFunction() {
@@ -394,9 +420,12 @@
}
/**
- * Get the block in which a symbol is defined
+ * Get the block in which a symbol is defined.
+ *
* @param symbol symbol
- * @return block in which the symbol is defined, assert if no such block in context
+ *
+ * @return block in which the symbol is defined, assert if no such block in
+ * context.
*/
public Block getDefiningBlock(final Symbol symbol) {
final String name = symbol.getName();
@@ -410,9 +439,12 @@
}
/**
- * Get the function in which a symbol is defined
+ * Get the function in which a symbol is defined.
+ *
* @param symbol symbol
- * @return function node in which this symbol is defined, assert if no such symbol exists in context
+ *
+ * @return function node in which this symbol is defined, assert if no such
+ * symbol exists in context.
*/
public FunctionNode getDefiningFunction(final Symbol symbol) {
final String name = symbol.getName();
@@ -433,7 +465,8 @@
/**
* Is the topmost lexical context element a function body?
- * @return true if function body
+ *
+ * @return {@code true} if function body.
*/
public boolean isFunctionBody() {
return getParentBlock() == null;
@@ -441,16 +474,20 @@
/**
* Is the topmost lexical context element body of a SplitNode?
- * @return true if it's the body of a split node.
+ *
+ * @return {@code true} if it's the body of a split node.
*/
public boolean isSplitBody() {
return sp >= 2 && stack[sp - 1] instanceof Block && stack[sp - 2] instanceof SplitNode;
}
/**
- * Get the parent function for a function in the lexical context
+ * Get the parent function for a function in the lexical context.
+ *
* @param functionNode function for which to get parent
- * @return parent function of functionNode or null if none (e.g. if functionNode is the program)
+ *
+ * @return parent function of functionNode or {@code null} if none (e.g., if
+ * functionNode is the program).
*/
public FunctionNode getParentFunction(final FunctionNode functionNode) {
final Iterator<FunctionNode> iter = new NodeIterator<>(FunctionNode.class);
@@ -465,12 +502,16 @@
}
/**
- * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of
- * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode
- * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location
- * and the break/continue target.
- * @param until node to stop counting at. Must be within the current function
- * @return number of with scopes encountered in the context
+ * Count the number of scopes until a given node. Note that this method is
+ * solely used to figure out the number of scopes that need to be explicitly
+ * popped in order to perform a break or continue jump within the current
+ * bytecode method. For this reason, the method returns 0 if it encounters a
+ * {@code SplitNode} between the current location and the break/continue
+ * target.
+ *
+ * @param until node to stop counting at. Must be within the current function.
+ *
+ * @return number of with scopes encountered in the context.
*/
public int getScopeNestingLevelTo(final LexicalContextNode until) {
assert until != null;
@@ -500,16 +541,17 @@
}
/**
- * Check whether the lexical context is currently inside a loop
- * @return true if inside a loop
+ * Check whether the lexical context is currently inside a loop.
+ *
+ * @return {@code true} if inside a loop
*/
public boolean inLoop() {
return getCurrentLoop() != null;
}
/**
- * Returns the loop header of the current loop, or null if not inside a loop
- * @return loop header
+ * @return the loop header of the current loop, or {@code null} if not
+ * inside a loop.
*/
public LoopNode getCurrentLoop() {
final Iterator<LoopNode> iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
@@ -518,9 +560,12 @@
/**
* Find the breakable node corresponding to this label.
- * @param labelName name of the label to search for. If null, the closest breakable node will be returned
- * unconditionally, e.g. a while loop with no label
- * @return closest breakable node
+ *
+ * @param labelName name of the label to search for. If {@code null}, the
+ * closest breakable node will be returned unconditionally, e.g., a
+ * while loop with no label.
+ *
+ * @return closest breakable node.
*/
public BreakableNode getBreakable(final String labelName) {
if (labelName != null) {
@@ -544,9 +589,12 @@
/**
* Find the continue target node corresponding to this label.
- * @param labelName label name to search for. If null the closest loop node will be returned unconditionally, e.g. a
- * while loop with no label
- * @return closest continue target node
+ *
+ * @param labelName label name to search for. If {@code null} the closest
+ * loop node will be returned unconditionally, e.g., a while loop
+ * with no label.
+ *
+ * @return closest continue target node.
*/
public LoopNode getContinueTo(final String labelName) {
if (labelName != null) {
@@ -566,8 +614,10 @@
/**
* Find the inlined finally block node corresponding to this label.
- * @param labelName label name to search for. Must not be null.
- * @return closest inlined finally block with the given label
+ *
+ * @param labelName label name to search for. Must not be {@code null}.
+ *
+ * @return closest inlined finally block with the given label.
*/
public Block getInlinedFinally(final String labelName) {
for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
@@ -581,7 +631,9 @@
/**
* Find the try node for an inlined finally block corresponding to this label.
- * @param labelName label name to search for. Must not be null.
+ *
+ * @param labelName label name to search for. Must not be {@code null}.
+ *
* @return the try node to which the labelled inlined finally block belongs.
*/
public TryNode getTryNodeForInlinedFinally(final String labelName) {
@@ -595,9 +647,11 @@
}
/**
- * Check the lexical context for a given label node by name
- * @param name name of the label
- * @return LabelNode if found, null otherwise
+ * Check the lexical context for a given label node by name.
+ *
+ * @param name name of the label.
+ *
+ * @return LabelNode if found, {@code null} otherwise.
*/
private LabelNode findLabel(final String name) {
for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
@@ -610,10 +664,13 @@
}
/**
- * Checks whether a given target is a jump destination that lies outside a given split node
- * @param splitNode the split node
- * @param target the target node
- * @return true if target resides outside the split node
+ * Checks whether a given target is a jump destination that lies outside a
+ * given split node.
+ *
+ * @param splitNode the split node.
+ * @param target the target node.
+ *
+ * @return {@code true} if target resides outside the split node.
*/
public boolean isExternalTarget(final SplitNode splitNode, final BreakableNode target) {
for (int i = sp; i-- > 0;) {
@@ -634,8 +691,10 @@
}
/**
- * Checks whether the current context is inside a switch statement without explicit blocks (curly braces).
- * @return true if in unprotected switch statement
+ * Checks whether the current context is inside a switch statement without
+ * explicit blocks (curly braces).
+ *
+ * @return {@code true} if in unprotected switch statement.
*/
public boolean inUnprotectedSwitchContext() {
for (int i = sp; i > 0; i--) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Fri Jun 12 16:40:05 2015 -0400
@@ -1005,9 +1005,7 @@
* @return the global singleton
*/
public static Global instance() {
- final Global global = Context.getGlobal();
- Objects.requireNonNull(global);
- return global;
+ return Objects.requireNonNull(Context.getGlobal());
}
private static Global instanceFrom(final Object self) {
@@ -2712,6 +2710,14 @@
// Retrieve current state of ENV variables.
final ScriptObject env = newObject();
env.putAll(System.getenv(), scriptEnv._strict);
+
+ // Some platforms, e.g., Windows, do not define the PWD environment
+ // variable, so that the $ENV.PWD property needs to be explicitly
+ // set.
+ if (!env.containsKey(ScriptingFunctions.PWD_NAME)) {
+ env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
+ }
+
addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
} else {
addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Constructor.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Constructor.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -37,13 +37,15 @@
@Target(ElementType.METHOD)
public @interface Constructor {
/**
- * Name of the constructor function. If empty, the name is inferred.
+ * @return the name of the constructor function. If empty, the name is
+ * inferred.
*/
public String name() default "";
/**
- * The arity of the function. By default computed from the method signature.
- * Note that -1 means varargs. So, -2 is used as invalid arity.
+ * @return the arity of the function. By default computed from the method
+ * signature. Note that -1 means varargs. So, -2 is used as invalid
+ * arity.
*/
public int arity() default -2;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Function.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Function.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,22 +41,23 @@
@Target(ElementType.METHOD)
public @interface Function {
/**
- * Name of the property. If empty, the name is inferred.
+ * @return the name of the property. If empty, the name is inferred.
*/
public String name() default "";
/**
- * Attribute flags for this function.
+ * @return the attribute flags for this function.
*/
public int attributes() default DEFAULT_ATTRIBUTES;
/**
- * The arity of the function. By default computed from the method signature
+ * @return the arity of the function. By default computed from the method
+ * signature.
*/
public int arity() default -2;
/**
- * where this function lives
+ * @return where this function lives.
*/
public Where where() default Where.PROTOTYPE;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Getter.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Getter.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,17 +39,17 @@
@Target(ElementType.METHOD)
public @interface Getter {
/**
- * Name of the property. If empty, the name is inferred.
+ * @return the name of the property. If empty, the name is inferred.
*/
public String name() default "";
/**
- * Attribute flags for this setter.
+ * @return the attribute flags for this setter.
*/
public int attributes() default DEFAULT_ATTRIBUTES;
/**
- * Where this getter lives?
+ * @return where this getter lives.
*/
public Where where() default Where.INSTANCE;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/ScriptClass.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/ScriptClass.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -37,8 +37,8 @@
@Target(ElementType.TYPE)
public @interface ScriptClass {
/**
- * Name of the script class. By default, the name is derived from
- * the Java class name.
+ * @return the name of the script class. By default, the name is derived
+ * from the Java class name.
*/
public String value() default "";
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Setter.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Setter.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,17 +39,17 @@
@Target(ElementType.METHOD)
public @interface Setter {
/**
- * Name of the script property. If empty, the name is inferred.
+ * @return the name of the script property. If empty, the name is inferred.
*/
public String name() default "";
/**
- * Attribute flags for this setter.
+ * @return the attribute flags for this setter.
*/
public int attributes() default DEFAULT_ATTRIBUTES;
/**
- * Where this setter lives?
+ * @return where this setter lives.
*/
public Where where() default Where.INSTANCE;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -33,10 +33,11 @@
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* The SpecializedFunction annotation is used to flag more type specific
- * functions than the standard one in the native objects
+ * functions than the standard one in the native objects.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@@ -45,23 +46,23 @@
/**
* Functionality for testing if we are allowed to link a specialized
* function the first time we encounter it. Then the guard will handle the
- * rest of the invocations
+ * rest of the invocations.
*
- * This is the same for all callsites in Nashorn, the first time callsite is
+ * This is the same for all callsites in Nashorn; the first time a callsite is
* linked, we have to manually check that the linkage is OK. Even if we add
* a guard and it fails upon the first try, this is not good enough.
- * (Symmetrical to how it works everywhere else in the Nashorn runtime).
+ * (Symmetrical to how it works everywhere else in the Nashorn runtime.)
*
* Here we abstract out a few of the most common link guard checks.
*/
public static abstract class LinkLogic {
/**
- * Empty link logic instance - this is the default
+ * Empty link logic instance - this is the default.
* "no special linking or runtime guard behavior"
*/
public static final LinkLogic EMPTY_INSTANCE = new Empty();
- /** Empty link logic class - allow all linking, no guards */
+ /** Empty link logic class - allow all linking, no guards. */
private static final class Empty extends LinkLogic {
@Override
public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
@@ -75,7 +76,8 @@
}
/**
- * Get the class representing the empty link logic
+ * Get the class representing the empty link logic.
+ *
* @return class representing empty link logic
*/
public static Class<? extends LinkLogic> getEmptyLinkLogicClass() {
@@ -83,31 +85,31 @@
}
/**
- * Should this callsite relink when an exception is thrown
+ * Should this callsite relink when an exception is thrown?
*
- * @return the relink exception, or null if none
+ * @return the relink exception, or {@code null} if none
*/
public Class<? extends Throwable> getRelinkException() {
return null;
}
/**
- * Is this link logic class empty - i.e. no special linking logic
- * supplied
+ * Is this link logic class empty - i.e., no special linking logic
+ * supplied?
*
* @param clazz class to check
*
- * @return true if this link logic is empty
+ * @return {@code true} if this link logic is empty
*/
public static boolean isEmpty(final Class<? extends LinkLogic> clazz) {
return clazz == Empty.class;
}
/**
- * Is this link logic instance empty - i.e. no special linking logic
- * supplied
+ * Is this link logic instance empty - i.e., no special linking logic
+ * supplied?
*
- * @return true if this link logic instance is empty
+ * @return {@code true} if this link logic instance is empty
*/
public boolean isEmpty() {
return false;
@@ -121,7 +123,7 @@
* @param desc callsite descriptor
* @param request link request
*
- * @return true if we can link this callsite at this time
+ * @return {@code true} if we can link this callsite at this time
*/
public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request);
@@ -131,7 +133,7 @@
*
* @param self receiver
*
- * @return true if a guard is to be woven into the callsite
+ * @return {@code true} if a guard is to be woven into the callsite
*/
public boolean needsGuard(final Object self) {
return true;
@@ -139,13 +141,13 @@
/**
* Given a callsite, and optional arguments, do we need an extra guard
- * for specialization to go through - this guard can be a function of
- * the arguments too
+ * for specialization to go through? This guard can be a function of
+ * the arguments too.
*
* @param self receiver
* @param args arguments
*
- * @return true if a guard is to be woven into the callsite
+ * @return {@code true} if a guard is to be woven into the callsite
*/
public boolean needsGuard(final Object self, final Object... args) {
return true;
@@ -169,9 +171,9 @@
* @param self receiver
* @param desc callsite descriptor
* @param request link request
-
- * @return true if we can link, false otherwise - that means we have to
- * pick a non specialized target
+ *
+ * @return {@code true} if we can link, {@code false} otherwise - that
+ * means we have to pick a non specialized target
*/
public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
// check the link guard, if it says we can link, go ahead
@@ -180,11 +182,11 @@
}
/**
- * name override for return value polymorphism, for example we can't have
+ * Name override for return value polymorphism, for example we can't have
* pop(V)I and pop(V)D in the same Java class, so they need to be named,
- * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their
+ * e.g., popInt(V)I and popDouble(V)D for disambiguation, however, their
* names still need to resolve to "pop" to JavaScript so we can still
- * specialize on return values and so that the linker can find them
+ * specialize on return values and so that the linker can find them.
*
* @return name, "" means no override, use the Java function name, e.g.
* "push"
@@ -199,16 +201,18 @@
Class<?> linkLogic() default LinkLogic.Empty.class;
/**
- * Is this a specialized constructor?
+ * @return whether this is a specialized constructor.
*/
boolean isConstructor() default false;
/**
- * Can this function throw UnwarrantedOptimismExceptions? This works just
- * like the normal functions, but we need the function to be
+ * Can this function throw {@link UnwarrantedOptimismException}s? This works
+ * just like the normal functions, but we need the function to be
* immutable/non-state modifying, as we can't generate continuations for
* native code. Luckily a lot of the methods we want to specialize have this
- * property
+ * property.
+ *
+ * @return whether this function can throw {@link UnwarrantedOptimismException}.
*/
boolean isOptimistic() default false;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Fri Jun 12 16:40:05 2015 -0400
@@ -47,7 +47,8 @@
import static jdk.nashorn.internal.parser.TokenType.STRING;
/**
- * Parses JSON text and returns the corresponding IR node. This is derived from the objectLiteral production of the main parser.
+ * Parses JSON text and returns the corresponding IR node. This is derived from
+ * the objectLiteral production of the main parser.
*
* See: 15.12.1.2 The JSON Syntactic Grammar
*/
@@ -70,9 +71,11 @@
private static final int STATE_COMMA_PARSED = 2;
/**
- * Constructor
- * @param source the source
- * @param global the global object
+ * Constructor.
+ *
+ * @param source the source
+ * @param global the global object
+ * @param dualFields whether the parser should regard dual field representation
*/
public JSONParser(final String source, final Global global, final boolean dualFields) {
this.source = source;
@@ -82,8 +85,9 @@
}
/**
- * Implementation of the Quote(value) operation as defined in the ECMA script spec
- * It wraps a String value in double quotes and escapes characters within in
+ * Implementation of the Quote(value) operation as defined in the ECMAscript
+ * spec. It wraps a String value in double quotes and escapes characters
+ * within.
*
* @param value string to quote
*
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri Jun 12 16:40:05 2015 -0400
@@ -2668,8 +2668,12 @@
name = getIdent();
verifyStrictIdent(name, "function name");
} else if (isStatement) {
- // Nashorn extension: anonymous function statements
- if (env._no_syntax_extensions) {
+ // Nashorn extension: anonymous function statements.
+ // Do not allow anonymous function statement if extensions
+ // are now allowed. But if we are reparsing then anon function
+ // statement is possible - because it was used as function
+ // expression in surrounding code.
+ if (env._no_syntax_extensions && reparsedFunction == null) {
expect(IDENT);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -222,9 +222,11 @@
/**
* Determines if the token has greater precedence than other.
+ *
* @param other Compare token.
* @param isLeft Is to the left of the other.
- * @return True if greater precedence.
+ *
+ * @return {@code true} if greater precedence.
*/
public boolean needsParens(final TokenType other, final boolean isLeft) {
return other.precedence != 0 &&
@@ -234,16 +236,16 @@
/**
* Determines if the type is a valid operator.
- * @param noIn TRUE if IN operator should be ignored.
- * @return TRUE if valid operator.
+ *
+ * @param noIn {@code true} if IN operator should be ignored.
+ *
+ * @return {@code true} if valid operator.
*/
public boolean isOperator(final boolean noIn) {
return kind == BINARY && (!noIn || this != IN) && precedence != 0;
}
- /**
- * Accessors.
- */
+
public int getLength() {
assert name != null : "Token name not set";
return name.length();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Fri Jun 12 16:40:05 2015 -0400
@@ -70,7 +70,6 @@
* @return Installed class.
*/
synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) {
- Objects.requireNonNull(cs);
- return defineClass(name, data, 0, data.length, cs);
+ return defineClass(name, data, 0, data.length, Objects.requireNonNull(cs));
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jun 12 16:40:05 2015 -0400
@@ -2582,7 +2582,7 @@
final int callCount = callType.parameterCount();
final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
- final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 &&
+ final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
callType.parameterType(callCount - 1).isArray();
if (isCalleeVarArg) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Fri Jun 12 16:40:05 2015 -0400
@@ -39,8 +39,10 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import jdk.nashorn.internal.objects.NativeArray;
/**
* Global functions supported only in scripting mode.
@@ -54,7 +56,7 @@
public static final MethodHandle READFULLY = findOwnMH("readFully", Object.class, Object.class, Object.class);
/** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */
- public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object.class, Object.class);
+ public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object[].class);
/** EXEC name - special property used by $EXEC API. */
public static final String EXEC_NAME = "$EXEC";
@@ -71,7 +73,8 @@
/** Names of special properties used by $ENV API. */
public static final String ENV_NAME = "$ENV";
- private static final String PWD_NAME = "PWD";
+ /** Name of the environment variable for the current working directory. */
+ public static final String PWD_NAME = "PWD";
private ScriptingFunctions() {
}
@@ -125,19 +128,32 @@
* Nashorn extension: exec a string in a separate process.
*
* @param self self reference
- * @param string string to execute
- * @param input input
+ * @param args string to execute, input and additional arguments, to be appended to {@code string}. Additional arguments can be passed as
+ * either one JavaScript array, whose elements will be converted to strings; or as a sequence of
+ * varargs, each of which will be converted to a string.
*
* @return output string from the request
+ *
* @throws IOException if any stream access fails
* @throws InterruptedException if execution is interrupted
*/
- public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
+ public static Object exec(final Object self, final Object... args) throws IOException, InterruptedException {
// Current global is need to fetch additional inputs and for additional results.
final ScriptObject global = Context.getGlobal();
+ final Object string = args.length > 0? args[0] : UNDEFINED;
+ final Object input = args.length > 1? args[1] : UNDEFINED;
+ final Object[] argv = (args.length > 2)? Arrays.copyOfRange(args, 2, args.length) : ScriptRuntime.EMPTY_ARRAY;
+ // Assemble command line, process additional arguments.
+ final List<String> cmdLine = tokenizeString(JSType.toString(string));
+ final Object[] additionalArgs = argv.length == 1 && argv[0] instanceof NativeArray ?
+ ((NativeArray) argv[0]).asObjectArray() :
+ argv;
+ for (Object arg : additionalArgs) {
+ cmdLine.add(JSType.toString(arg));
+ }
// Set up initial process.
- final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeString(JSType.toString(string)));
+ final ProcessBuilder processBuilder = new ProcessBuilder(cmdLine);
// Current ENV property state.
final Object env = global.get(ENV_NAME);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Fri Jun 12 16:40:05 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -54,23 +54,28 @@
import jdk.nashorn.internal.runtime.ScriptObject;
/**
- * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
- * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
- * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
- * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.)
- * </p><p>
- * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either
- * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader
- * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have
- * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has
- * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to
- * generate the adapter class itself; see its documentation for details about the generated class.
- * </p><p>
- * You normally don't use this class directly, but rather either create adapters from script using
- * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
- * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
- * types.
- * </p>
+ * A factory class that generates adapter classes. Adapter classes allow
+ * implementation of Java interfaces and extending of Java classes from
+ * JavaScript. For every combination of a superclass to extend and interfaces to
+ * implement (collectively: "original types"), exactly one adapter class is
+ * generated that extends the specified superclass and implements the specified
+ * interfaces. (But see the discussion of class-based overrides for exceptions.)
+ * <p>
+ * The adapter class is generated in a new secure class loader that inherits
+ * Nashorn's protection domain, and has either one of the original types' class
+ * loader or the Nashorn's class loader as its parent - the parent class loader
+ * is chosen so that all the original types and the Nashorn core classes are
+ * visible from it (as the adapter will have constant pool references to
+ * ScriptObject and ScriptFunction classes). In case none of the candidate class
+ * loaders has visibility of all the required types, an error is thrown. The
+ * class uses {@link JavaAdapterBytecodeGenerator} to generate the adapter class
+ * itself; see its documentation for details about the generated class.
+ * <p>
+ * You normally don't use this class directly, but rather either create adapters
+ * from script using {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)},
+ * using the {@code new} operator on abstract classes and interfaces (see
+ * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or
+ * implicitly when passing script functions to Java methods expecting SAM types.
*/
@SuppressWarnings("javadoc")
@@ -93,25 +98,39 @@
};
/**
- * Returns an adapter class for the specified original types. The adapter class extends/implements the original
- * class/interfaces.
- * @param types the original types. The caller must pass at least one Java type representing either a public
- * interface or a non-final public class with at least one public or protected constructor. If more than one type is
- * specified, at most one can be a class and the rest have to be interfaces. The class can be in any position in the
- * array. Invoking the method twice with exactly the same types in the same order will return the same adapter
- * class, any reordering of types or even addition or removal of redundant types (i.e. interfaces that other types
- * in the list already implement/extend, or {@code java.lang.Object} in a list of types consisting purely of
- * interfaces) will result in a different adapter class, even though those adapter classes are functionally
- * identical; we deliberately don't want to incur the additional processing cost of canonicalizing type lists.
- * @param classOverrides a JavaScript object with functions serving as the class-level overrides and
- * implementations. These overrides are defined for all instances of the class, and can be further overridden on a
- * per-instance basis by passing additional objects in the constructor.
- * @param lookup the lookup object identifying the caller class. The generated adapter class will have the
- * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely
- * unprivileged.
- * @return an adapter class. See this class' documentation for details on the generated adapter class.
- * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is
- * final, non-public, or has no public or protected constructors.
+ * Returns an adapter class for the specified original types. The adapter
+ * class extends/implements the original class/interfaces.
+ *
+ * @param types the original types. The caller must pass at least one Java
+ * type representing either a public interface or a non-final public
+ * class with at least one public or protected constructor. If more
+ * than one type is specified, at most one can be a class and the
+ * rest have to be interfaces. The class can be in any position in
+ * the array. Invoking the method twice with exactly the same types
+ * in the same order will return the same adapter class, any
+ * reordering of types or even addition or removal of redundant types
+ * (i.e., interfaces that other types in the list already
+ * implement/extend, or {@code java.lang.Object} in a list of types
+ * consisting purely of interfaces) will result in a different
+ * adapter class, even though those adapter classes are functionally
+ * identical; we deliberately don't want to incur the additional
+ * processing cost of canonicalizing type lists.
+ * @param classOverrides a JavaScript object with functions serving as the
+ * class-level overrides and implementations. These overrides are
+ * defined for all instances of the class, and can be further
+ * overridden on a per-instance basis by passing additional objects
+ * in the constructor.
+ * @param lookup the lookup object identifying the caller class. The
+ * generated adapter class will have the protection domain of the
+ * caller class iff the lookup object is full-strength, otherwise it
+ * will be completely unprivileged.
+ *
+ * @return an adapter class. See this class' documentation for details on
+ * the generated adapter class.
+ *
+ * @throws ECMAException with a TypeError if the adapter class can not be
+ * generated because the original class is final, non-public, or has
+ * no public or protected constructors.
*/
public static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
@@ -148,15 +167,23 @@
}
/**
- * Returns a method handle representing a constructor that takes a single argument of the source type (which,
- * really, should be one of {@link ScriptObject}, {@link ScriptFunction}, or {@link Object}, and returns an instance
- * of the adapter for the target type. Used to implement the function autoconverters as well as the Nashorn's
- * JSR-223 script engine's {@code getInterface()} method.
- * @param sourceType the source type; should be either {@link ScriptObject}, {@link ScriptFunction}, or
- * {@link Object}. In case of {@code Object}, it will return a method handle that dispatches to either the script
- * object or function constructor at invocation based on the actual argument.
+ * Returns a method handle representing a constructor that takes a single
+ * argument of the source type (which, really, should be one of {@link ScriptObject},
+ * {@link ScriptFunction}, or {@link Object}, and returns an instance of the
+ * adapter for the target type. Used to implement the function autoconverters
+ * as well as the Nashorn JSR-223 script engine's {@code getInterface()}
+ * method.
+ *
+ * @param sourceType the source type; should be either {@link ScriptObject},
+ * {@link ScriptFunction}, or {@link Object}. In case of {@code Object},
+ * it will return a method handle that dispatches to either the script
+ * object or function constructor at invocation based on the actual
+ * argument.
* @param targetType the target type, for which adapter instances will be created
+ * @param lookup method handle lookup to use
+ *
* @return the constructor method handle.
+ *
* @throws Exception if anything goes wrong
*/
public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception {
@@ -168,13 +195,18 @@
}
/**
- * Returns whether an instance of the specified class/interface can be generated from a ScriptFunction. Returns true
- * iff: the adapter for the class/interface can be created, it is abstract (this includes interfaces), it has at
- * least one abstract method, all the abstract methods share the same name, and it has a public or protected default
- * constructor. Note that invoking this class will most likely result in the adapter class being defined in the JVM
- * if it hasn't been already.
+ * Returns whether an instance of the specified class/interface can be
+ * generated from a ScriptFunction. Returns {@code true} iff: the adapter
+ * for the class/interface can be created, it is abstract (this includes
+ * interfaces), it has at least one abstract method, all the abstract
+ * methods share the same name, and it has a public or protected default
+ * constructor. Note that invoking this class will most likely result in the
+ * adapter class being defined in the JVM if it hasn't been already.
+ *
* @param clazz the inspected class
- * @return true iff an instance of the specified class/interface can be generated from a ScriptFunction.
+ *
+ * @return {@code true} iff an instance of the specified class/interface can
+ * be generated from a ScriptFunction.
*/
static boolean isAutoConvertibleFromFunction(final Class<?> clazz) {
return getAdapterInfo(new Class<?>[] { clazz }).autoConvertibleFromFunction;
@@ -198,7 +230,9 @@
/**
* For a given class, create its adapter class and associated info.
+ *
* @param type the class for which the adapter is created
+ *
* @return the adapter info for the class.
*/
private static AdapterInfo createAdapterInfo(final Class<?>[] types, final ClassAndLoader definingClassAndLoader) {
@@ -311,11 +345,14 @@
}
/**
- * Choose between the passed class loader and the class loader that defines the ScriptObject class, based on which
- * of the two can see the classes in both.
- * @param classAndLoader the loader and a representative class from it that will be used to add the generated
- * adapter to its ADAPTER_INFO_MAPS.
+ * Choose between the passed class loader and the class loader that defines the
+ * ScriptObject class, based on which of the two can see the classes in both.
+ *
+ * @param classAndLoader the loader and a representative class from it that will
+ * be used to add the generated adapter to its ADAPTER_INFO_MAPS.
+ *
* @return the class loader that sees both the specified class and Nashorn classes.
+ *
* @throws IllegalStateException if no such class loader is found.
*/
private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Fri Jun 12 16:40:05 2015 -0400
@@ -36,8 +36,7 @@
private final Object adapter;
JavaSuperAdapter(final Object adapter) {
- Objects.requireNonNull(adapter);
- this.adapter = adapter;
+ this.adapter = Objects.requireNonNull(adapter);
}
public Object getAdapter() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java Fri Jun 12 16:40:05 2015 -0400
@@ -136,6 +136,12 @@
return options.toString();
}
+ private static void checkPropertyName(final String name) {
+ if (! Objects.requireNonNull(name).startsWith("nashorn.")) {
+ throw new IllegalArgumentException(name);
+ }
+ }
+
/**
* Convenience function for getting system properties in a safe way
@@ -144,11 +150,7 @@
* @return true if set to true, default value if unset or set to false
*/
public static boolean getBooleanProperty(final String name, final Boolean defValue) {
- Objects.requireNonNull(name);
- if (!name.startsWith("nashorn.")) {
- throw new IllegalArgumentException(name);
- }
-
+ checkPropertyName(name);
return AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
@Override
@@ -185,11 +187,7 @@
* @return string property if set or default value
*/
public static String getStringProperty(final String name, final String defValue) {
- Objects.requireNonNull(name);
- if (! name.startsWith("nashorn.")) {
- throw new IllegalArgumentException(name);
- }
-
+ checkPropertyName(name);
return AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
@@ -212,11 +210,7 @@
* @return integer property if set or default value
*/
public static int getIntProperty(final String name, final int defValue) {
- Objects.requireNonNull(name);
- if (! name.startsWith("nashorn.")) {
- throw new IllegalArgumentException(name);
- }
-
+ checkPropertyName(name);
return AccessController.doPrivileged(
new PrivilegedAction<Integer>() {
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java Fri Jun 12 16:40:05 2015 -0400
@@ -229,6 +229,11 @@
/**
* @see <a href="http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt">http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt</a>
+ *
+ * @param code code
+ * @param ctype ctype
+ *
+ * @return isCodeCType
*/
public static boolean isCodeCType(final int code, final int ctype) {
int type;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Fri Jun 12 16:36:33 2015 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Fri Jun 12 16:40:05 2015 -0400
@@ -57,10 +57,10 @@
}
}
- /**
- * OP
- *
- */
+ //
+ // OP
+ //
+
protected boolean isOp(final int opm) {
return (op & opm) != 0;
}
@@ -189,11 +189,10 @@
return isOp(OP_ESC_X_BRACE_HEX8);
}
+ //
+ // OP2
+ //
- /**
- * OP
- *
- */
protected boolean isOp2(final int opm) {
return (op2 & opm) != 0;
}
@@ -278,10 +277,10 @@
return isOp2(OP2_INEFFECTIVE_ESCAPE);
}
- /**
- * BEHAVIOR
- *
- */
+ //
+ // BEHAVIOR
+ //
+
protected boolean isBehavior(final int bvm) {
return (behavior & bvm) != 0;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8085802.js Fri Jun 12 16:40:05 2015 -0400
@@ -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.
+ */
+
+/**
+ * JDK-8085802: Nashorn -nse option causes parse error on anonymous function definition
+ *
+ * @test
+ * @run
+ * @option -nse
+ */
+
+// even with -nse passed, the following should run fine
+// because anonymous function is used as expression here
+
+(function (){})()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/anon_func_stat_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Anonymous function statement should result in error in -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
+
+function() {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/anon_func_stat_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,3 @@
+test/script/error/anon_func_stat_nse.js:31:8 Expected ident but found (
+function() {}
+ ^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/backquote_string_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/**
+ * Backquote string should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
+
+`ls -l`;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/backquote_string_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,3 @@
+test/script/error/backquote_string_nse.js:32:0 Expected an operand but found error
+`ls -l`;
+^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/conditional_catch_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * conditional catch should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
+
+try {
+ func();
+} catch (e if e instanceof ReferenceError) {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/conditional_catch_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,6 @@
+test/script/error/conditional_catch_nse.js:33:11 Expected ) but found if
+} catch (e if e instanceof ReferenceError) {
+ ^
+test/script/error/conditional_catch_nse.js:34:0 Expected eof but found }
+}
+^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/expr_closure_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Expression closures should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
+
+function square(x) x*x;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/expr_closure_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,3 @@
+test/script/error/expr_closure_nse.js:31:19 Expected { but found x
+function square(x) x*x;
+ ^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/for_each_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * for..each should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
+
+for each (var x in [3, 454, 4]) {
+ print(x);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/for_each_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,6 @@
+test/script/error/for_each_nse.js:31:4 Expected ( but found each
+for each (var x in [3, 454, 4]) {
+ ^
+test/script/error/for_each_nse.js:33:0 Expected eof but found }
+}
+^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/hash_comment_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/**
+ * Hash comment should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
+
+# this is a comment
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/hash_comment_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,3 @@
+test/script/error/hash_comment_nse.js:32:0 Expected an operand but found error
+# this is a comment
+^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/heredoc_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -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.
+ */
+
+/**
+ * Heredoc string should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
+
+var str = <<EOF
+This is a multiple line string
+inside a heredoc
+EOF;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/heredoc_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,9 @@
+test/script/error/heredoc_nse.js:32:10 Expected an operand but found <<
+var str = <<EOF
+ ^
+test/script/error/heredoc_nse.js:33:5 Expected ; but found is
+This is a multiple line string
+ ^
+test/script/error/heredoc_nse.js:34:7 Expected ; but found a
+inside a heredoc
+ ^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/object_literal_in_new_nse.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * Object literal outside 'new' should result in error in -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
+
+var r = new java.lang.Runnable() {
+ run: function() { print("hello"); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/object_literal_in_new_nse.js.EXPECTED Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,9 @@
+test/script/error/object_literal_in_new_nse.js:31:33 Expected ; but found {
+var r = new java.lang.Runnable() {
+ ^
+test/script/error/object_literal_in_new_nse.js:32:15 Expected ident but found (
+ run: function() { print("hello"); }
+ ^
+test/script/error/object_literal_in_new_nse.js:32:36 Expected eof but found }
+ run: function() { print("hello"); }
+ ^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/JDK-8080087.js Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8080087: Nashorn $ENV.PWD is originally undefined
+ *
+ * This is to ensure that $ENV.PWD is correctly set on Windows as well as on all
+ * other platforms.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+if (typeof($ENV.PWD) === 'undefined') {
+ fail('$ENV.PWD is undefined')
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,72 @@
+/*
+ * 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 Unit test for LingeredApp
+ * @compile LingeredAppTest.java
+ * @compile LingeredApp.java
+ * @run main LingeredAppTest
+ */
+
+package jdk.test.lib.apps;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class LingeredAppTest {
+
+ public static void main(String[] args) {
+ try {
+ System.out.println("Starting LingeredApp with default parameters");
+
+ ArrayList<String> cmd = new ArrayList<String>();
+
+ // Propagate test.vm.options to LingeredApp, filter out possible empty options
+ String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+ for (String s : testVmOpts) {
+ if (!s.equals("")) {
+ cmd.add(s);
+ }
+ }
+
+ cmd.add("-XX:+PrintFlagsFinal");
+
+ LingeredApp a = LingeredApp.startApp(cmd);
+ System.out.printf("App pid: %d\n", a.getPid());
+ a.stopApp();
+
+ System.out.println("App output:");
+ int count = 0;
+ for (String line : a.getAppOutput()) {
+ count += 1;
+ }
+ System.out.println("Found " + count + " lines in VM output");
+ System.out.println("Test PASSED");
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ System.out.println("Test ERROR");
+ System.exit(3);
+ }
+ }
+}
--- a/test/lib/Makefile Fri Jun 12 16:36:33 2015 -0400
+++ b/test/lib/Makefile Fri Jun 12 16:40:05 2015 -0400
@@ -42,7 +42,8 @@
JAR = $(JDK_HOME)/bin/jar
WB_SRC_FILES = $(shell find $(SRC_DIR)/sun/hotspot -name '*.java')
-SHARE_SRC_FILES = $(shell find $(SRC_DIR)/share/classes -name '*.java')
+# test-lib.jar will contain only hprof classes until JDK-8081381 is resolved
+SHARE_SRC_FILES = $(shell find $(SRC_DIR)/share/classes/jdk/test/lib/hprof -name '*.java')
.PHONY: wb.filelist share.filelist clean cleantmp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/apps/LingeredApp.java Fri Jun 12 16:40:05 2015 -0400
@@ -0,0 +1,434 @@
+/*
+ * 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.
+ */
+
+package jdk.test.lib.apps;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This is a framework to launch an app that could be synchronized with caller
+ * to make further attach actions reliable across supported platforms
+
+ * Caller example:
+ * SmartTestApp a = SmartTestApp.startApp(cmd);
+ * // do something
+ * a.stopApp();
+ *
+ * or fine grained control
+ *
+ * a = new SmartTestApp("MyLock.lck");
+ * a.createLock();
+ * a.runApp();
+ * a.waitAppReady();
+ * // do something
+ * a.deleteLock();
+ * a.waitAppTerminate();
+ *
+ * Then you can work with app output and process object
+ *
+ * output = a.getAppOutput();
+ * process = a.getProcess();
+ *
+ */
+public class LingeredApp {
+
+ private static final long spinDelay = 1000;
+
+ private final String lockFileName;
+ private long lockCreationTime;
+ private Process appProcess;
+ private final ArrayList<String> storedAppOutput;
+
+ /*
+ * Drain child process output, store it into string array
+ */
+ class InputGobbler extends Thread {
+
+ InputStream is;
+ List<String> astr;
+
+ InputGobbler(InputStream is, List<String> astr) {
+ this.is = is;
+ this.astr = astr;
+ }
+
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ astr.add(line);
+ }
+ } catch (IOException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Create LingeredApp object on caller side. Lock file have be a valid filename
+ * at writable location
+ *
+ * @param lockFileName - the name of lock file
+ */
+ public LingeredApp(String lockFileName) {
+ this.lockFileName = lockFileName;
+ this.storedAppOutput = new ArrayList<String>();
+ }
+
+ /**
+ *
+ * @return name of lock file
+ */
+ public String getLockFileName() {
+ return this.lockFileName;
+ }
+
+ /**
+ *
+ * @return name of testapp
+ */
+ public String getAppName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ *
+ * @return pid of java process running testapp
+ */
+ public long getPid() {
+ if (appProcess == null) {
+ throw new RuntimeException("Process is not alive");
+ }
+ return appProcess.getPid();
+ }
+
+ /**
+ *
+ * @return process object
+ */
+ public Process getProcess() {
+ return appProcess;
+ }
+
+ /**
+ *
+ * @return application output as string array. Empty array if application produced no output
+ */
+ public List<String> getAppOutput() {
+ if (appProcess.isAlive()) {
+ throw new RuntimeException("Process is still alive. Can't get its output.");
+ }
+ return storedAppOutput;
+ }
+
+ /* Make sure all part of the app use the same method to get dates,
+ as different methods could produce different results
+ */
+ private static long epoch() {
+ return new Date().getTime();
+ }
+
+ private static long lastModified(String fileName) throws IOException {
+ Path path = Paths.get(fileName);
+ BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+ return attr.lastModifiedTime().toMillis();
+ }
+
+ private static void setLastModified(String fileName, long newTime) throws IOException {
+ Path path = Paths.get(fileName);
+ FileTime fileTime = FileTime.fromMillis(newTime);
+ Files.setLastModifiedTime(path, fileTime);
+ }
+
+ /**
+ * create lock
+ *
+ * @throws IOException
+ */
+ public void createLock() throws IOException {
+ Path path = Paths.get(lockFileName);
+ // Files.deleteIfExists(path);
+ Files.createFile(path);
+ lockCreationTime = lastModified(lockFileName);
+ }
+
+ /**
+ * Delete lock
+ *
+ * @throws IOException
+ */
+ public void deleteLock() throws IOException {
+ try {
+ Path path = Paths.get(lockFileName);
+ Files.delete(path);
+ } catch (NoSuchFileException ex) {
+ // Lock already deleted. Ignore error
+ }
+ }
+
+ public void waitAppTerminate() {
+ while (true) {
+ try {
+ appProcess.waitFor();
+ break;
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * The app touches the lock file when it's started
+ * wait while it happens. Caller have to delete lock on wait error.
+ *
+ * @param timeout
+ * @throws java.io.IOException
+ */
+ public void waitAppReady(long timeout) throws IOException {
+ long here = epoch();
+ while (true) {
+ long epoch = epoch();
+ if (epoch - here > (timeout * 1000)) {
+ throw new IOException("App waiting timeout");
+ }
+
+ // Live process should touch lock file every second
+ long lm = lastModified(lockFileName);
+ if (lm > lockCreationTime) {
+ break;
+ }
+
+ // Make sure process didn't already exit
+ if (!appProcess.isAlive()) {
+ throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
+ }
+
+ try {
+ Thread.sleep(spinDelay);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Run the app
+ *
+ * @param vmArguments
+ * @throws IOException
+ */
+ public void runApp(List<String> vmArguments)
+ throws IOException {
+
+ // We should always use testjava or throw an exception,
+ // so we can't use JDKToolFinder.getJDKTool("java");
+ // that falls back to compile java on error
+ String jdkPath = System.getProperty("test.jdk");
+ if (jdkPath == null) {
+ // we are not under jtreg, try env
+ Map<String, String> env = System.getenv();
+ jdkPath = env.get("TESTJAVA");
+ }
+
+ if (jdkPath == null) {
+ throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
+ }
+
+ String osname = System.getProperty("os.name");
+ String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
+
+ List<String> cmd = new ArrayList<String>();
+ cmd.add(javapath);
+
+
+ if (vmArguments == null) {
+ // Propagate test.vm.options to LingeredApp, filter out possible empty options
+ String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+ for (String s : testVmOpts) {
+ if (!s.equals("")) {
+ cmd.add(s);
+ }
+ }
+ }
+ else{
+ // Lets user manage LingerApp options
+ cmd.addAll(vmArguments);
+ }
+
+ // Make sure we set correct classpath to run the app
+ cmd.add("-cp");
+ String classpath = System.getProperty("test.class.path");
+ cmd.add((classpath == null) ? "." : classpath);
+
+ cmd.add(this.getAppName());
+ cmd.add(lockFileName);
+
+ // Reporting
+ StringBuilder cmdLine = new StringBuilder();
+ for (String strCmd : cmd) {
+ cmdLine.append("'").append(strCmd).append("' ");
+ }
+
+ // A bit of verbosity
+ System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ // we don't expect any error output but make sure we are not stuck on pipe
+ // pb.redirectErrorStream(false);
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+ appProcess = pb.start();
+
+ // Create pipe reader for process, and read stdin and stderr to array of strings
+ InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
+ gb.start();
+ }
+
+ /**
+ * High level interface for test writers
+ */
+ /**
+ * Factory method that creates SmartAppTest object with ready to use application
+ * lock name is autogenerated, wait timeout is hardcoded
+ * @param cmd - vm options, could be null to auto add testvm.options
+ * @return LingeredApp object
+ * @throws IOException
+ */
+ public static LingeredApp startApp(List<String> cmd) throws IOException {
+ final String lockName = UUID.randomUUID().toString() + ".lck";
+ final int waitTime = 10;
+
+ LingeredApp a = new LingeredApp(lockName);
+ a.createLock();
+ try {
+ a.runApp(cmd);
+ a.waitAppReady(waitTime);
+ } catch (Exception ex) {
+ a.deleteLock();
+ throw ex;
+ }
+
+ return a;
+ }
+
+ public static LingeredApp startApp() throws IOException {
+ return startApp(null);
+ }
+
+ /**
+ * Delete lock file that signal app to terminate, then
+ * waits until app is actually terminated.
+ * @throws IOException
+ */
+ public void stopApp() throws IOException {
+ deleteLock();
+ waitAppTerminate();
+ int exitcode = appProcess.exitValue();
+ if (exitcode != 0) {
+ throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
+ }
+ }
+
+ /**
+ * LastModified time might not work correctly in some cases it might
+ * cause later failures
+ */
+
+ public static boolean isLastModifiedWorking() {
+ boolean sane = true;
+ try {
+ long lm = lastModified(".");
+ if (lm == 0) {
+ System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
+ sane = false;
+ }
+
+ long now = epoch();
+ if (lm > now) {
+ System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
+ sane = false;
+ }
+
+ setLastModified(".", epoch());
+ long lm1 = lastModified(".");
+ if (lm1 <= lm) {
+ System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
+ sane = false;
+ }
+ }
+ catch(IOException e) {
+ System.err.println("SANITY Warning! IOException during sanity check " + e);
+ sane = false;
+ }
+
+ return sane;
+ }
+
+ /**
+ * This part is the application it self
+ */
+ public static void main(String args[]) {
+
+ if (args.length != 1) {
+ System.err.println("Lock file name is not specified");
+ System.exit(7);
+ }
+
+ String theLockFileName = args[0];
+
+ try {
+ Path path = Paths.get(theLockFileName);
+
+ while (Files.exists(path)) {
+ // Touch the lock to indicate our readiness
+ setLastModified(theLockFileName, epoch());
+ Thread.sleep(spinDelay);
+ }
+ } catch (NoSuchFileException ex) {
+ // Lock deleted while we are setting last modified time.
+ // Ignore error and lets the app exits
+ } catch (Exception ex) {
+ System.err.println("LingeredApp ERROR: " + ex);
+ // Leave exit_code = 1 to Java launcher
+ System.exit(3);
+ }
+
+ System.exit(0);
+ }
+}