--- a/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -318,3 +318,4 @@
9b3a9d72f07b40c648de79961679f42283af1bb5 jdk9-b73
7c577fda1855d03c04546694d514678f596508c9 jdk9-b74
f55df5cfe11c97e4b58998b76f5bd00a73cde12d jdk9-b75
+eeea9adfd1e3d075ef82148c00a4847a1aab4d26 jdk9-b76
--- a/.hgtags-top-repo Thu Aug 06 13:00:45 2015 -0700
+++ b/.hgtags-top-repo Mon Aug 10 18:58:25 2015 -0700
@@ -318,3 +318,4 @@
4c2cbaae528bce970dabbb5676005d379357f4b6 jdk9-b73
57f3134853ecdd4a3ee2d4d26f22ba981d653d79 jdk9-b74
8fd6eeb878606e39c908f12535f34ebbfd225a4a jdk9-b75
+d82072b699b880a1f647a5e2d7c0f86cec958941 jdk9-b76
--- a/corba/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/corba/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -318,3 +318,4 @@
29096b78d93b01a2f8882509cd40755e3d6b8cd9 jdk9-b73
622fe934e351e89107edf3c667d6b57f543f58f1 jdk9-b74
960b56805abd8460598897481820bd6a75f979e7 jdk9-b75
+d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
--- a/hotspot/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -478,3 +478,4 @@
e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73
fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74
2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
+0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SAGetopt {
+
+ private String[] _argv;
+
+ private int _optind; // index in arguments array
+ private int _optopt; // index within an argument
+ private String _optarg; // last option argument
+ private boolean _optreset; // special handling of first call
+
+ public SAGetopt(String[] args) {
+ _argv = args;
+ _optind = 0;
+ _optopt = 1;
+ _optarg = null;
+ _optreset = true;
+ }
+
+ public String getOptarg() {
+ return _optarg;
+ }
+
+ public int getOptind() {
+ return _optind;
+ }
+
+ private void extractOptarg(String opt) {
+ // Argument expected
+ if (_optind > _argv.length) {
+ throw new RuntimeException("Not enough arguments for '" + opt + "'");
+ }
+
+ if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') {
+ throw new RuntimeException("Argument is expected for '" + opt + "'");
+ }
+
+ _optarg = _argv[_optind];
+ _optind += 1;
+ }
+
+ private String processLongOptions(String carg, String[] longOptStr) {
+ List<String> los = Arrays.asList(longOptStr);
+ String[] ca = carg.split("=", 2);
+
+ if (los.contains(ca[0])) {
+ if (ca.length > 1) {
+ throw new RuntimeException("Argument is not expected for '" + ca[0] + "'");
+ }
+ return carg;
+ }
+
+ if (los.contains(ca[0] + "=")) {
+ if (ca.length > 1) {
+ // GNU style options --file=name
+ _optarg = ca[1];
+ }
+ else {
+ // Mixed style options --file name
+ extractOptarg(ca[0]);
+ }
+
+ return ca[0];
+ }
+
+ throw new RuntimeException("Invalid option '" + ca[0] + "'");
+ }
+
+ public String next(String optStr, String[] longOptStr) {
+
+ if (_optind >= _argv.length || _argv[_optind] == null) {
+ // All arguments processed
+ return null;
+ }
+
+ String carg = _argv[_optind];
+ _optarg = null;
+
+ if (_optreset) {
+ // End of option batch like '-abc' reached, expect option to start from '-'
+
+ if (carg.isEmpty() || carg.charAt(0) != '-' || carg.equals("--")) {
+ // Stop processing on -- or first non-option argument;
+ return null;
+ }
+
+ if (carg.startsWith("--")) {
+ // Handle long options, it can't be combined so it's simple
+ if (longOptStr == null || longOptStr.length == 0) {
+ // No long options expected, stop options processing
+ return null;
+ }
+ ++ _optind;
+
+ // at this point carg contains at least one character besides --
+ carg = carg.substring(2);
+ return processLongOptions(carg, longOptStr);
+ }
+
+ if (optStr == null || optStr.length() == 0) {
+ // No short options
+ return null;
+ }
+
+ // At this point carg[0] contains '-'
+ _optreset = false;
+ _optopt = 1;
+ }
+
+ char ch = carg.charAt(_optopt);
+
+ // adjust pointer to next character
+ _optopt += 1;
+
+ // Okay, ready to process options like
+ // -abc -d bla -ef
+
+ int chIndex = optStr.indexOf(ch);
+ if (chIndex == -1) {
+ throw new RuntimeException("Invalid option '" + ch + "'");
+ }
+
+ if (_optopt >= carg.length()) {
+ _optind += 1;
+ _optreset = true;
+ }
+
+ if (chIndex < optStr.length()-1 && optStr.charAt(chIndex+1) == ':') {
+ // Argument expected
+ extractOptarg(String.valueOf(ch));
+ }
+
+ return String.valueOf(ch);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,359 @@
+/*
+ * 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 sun.jvm.hotspot;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import sun.jvm.hotspot.tools.JStack;
+import sun.jvm.hotspot.tools.JMap;
+import sun.jvm.hotspot.tools.JInfo;
+
+public class SALauncher {
+
+ private static boolean launcherHelp() {
+ System.out.println(" clhsdb \tcommand line debugger");
+ System.out.println(" hsdb \tui debugger");
+ System.out.println(" jstack --help\tto get more information");
+ System.out.println(" jmap --help\tto get more information");
+ System.out.println(" jinfo --help\tto get more information");
+ return false;
+ }
+
+ private static boolean commonHelp() {
+ // --pid <pid>
+ // --exe <exe>
+ // --core <core>
+ System.out.println(" --exe\texecutable image name");
+ System.out.println(" --core\tpath to coredump");
+ System.out.println(" --pid\tpid of process to attach");
+ return false;
+ }
+
+ private static boolean jinfoHelp() {
+ // --flags -> -flags
+ // --sysprops -> -sysprops
+ System.out.println(" --flags\tto print VM flags");
+ System.out.println(" --sysprops\tto print Java System properties");
+ System.out.println(" <no option>\tto print both of the above");
+ return commonHelp();
+ }
+
+ private static boolean jmapHelp() {
+ // --heap -> -heap
+ // --binaryheap -> -heap:format=b
+ // --histo -> -histo
+ // --clstats -> -clstats
+ // --finalizerinfo -> -finalizerinfo
+
+ System.out.println(" <no option>\tto print same info as Solaris pmap");
+ System.out.println(" --heap\tto print java heap summary");
+ System.out.println(" --binaryheap\tto dump java heap in hprof binary format");
+ System.out.println(" --histo\tto print histogram of java object heap");
+ System.out.println(" --clstats\tto print class loader statistics");
+ System.out.println(" --finalizerinfo\tto print information on objects awaiting finalization");
+ return commonHelp();
+ }
+
+ private static boolean jstackHelp() {
+ // --locks -> -l
+ // --mixed -> -m
+ System.out.println(" --locks\tto print java.util.concurrent locks");
+ System.out.println(" --mixed\tto print both java and native frames (mixed mode)");
+ return commonHelp();
+ }
+
+ private static boolean toolHelp(String toolName) {
+ if (toolName.equals("jstack")) {
+ return jstackHelp();
+ }
+ if (toolName.equals("jinfo")) {
+ return jinfoHelp();
+ }
+ if (toolName.equals("jmap")) {
+ return jmapHelp();
+ }
+ if (toolName.equals("hsdb") || toolName.equals("clhsdb")) {
+ return commonHelp();
+ }
+ return launcherHelp();
+ }
+
+ private static void runCLHSDB(String[] oldArgs) {
+ SAGetopt sg = new SAGetopt(oldArgs);
+ String[] longOpts = {"exe=", "core=", "pid="};
+
+ ArrayList<String> newArgs = new ArrayList();
+ String exeORpid = null;
+ String core = null;
+ String s = null;
+
+ while((s = sg.next(null, longOpts)) != null) {
+ if (s.equals("exe")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("core")) {
+ core = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("pid")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ }
+
+ if (exeORpid != null) {
+ newArgs.add(exeORpid);
+ if (core != null) {
+ newArgs.add(core);
+ }
+ }
+ CLHSDB.main(newArgs.toArray(new String[newArgs.size()]));
+ }
+
+ private static void runHSDB(String[] oldArgs) {
+ SAGetopt sg = new SAGetopt(oldArgs);
+ String[] longOpts = {"exe=", "core=", "pid="};
+
+ ArrayList<String> newArgs = new ArrayList();
+ String exeORpid = null;
+ String core = null;
+ String s = null;
+
+ while((s = sg.next(null, longOpts)) != null) {
+ if (s.equals("exe")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("core")) {
+ core = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("pid")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ }
+
+ if (exeORpid != null) {
+ newArgs.add(exeORpid);
+ if (core != null) {
+ newArgs.add(core);
+ }
+ }
+ HSDB.main(newArgs.toArray(new String[newArgs.size()]));
+ }
+
+ private static void runJSTACK(String[] oldArgs) {
+ SAGetopt sg = new SAGetopt(oldArgs);
+ String[] longOpts = {"exe=", "core=", "pid=",
+ "mixed", "locks"};
+
+ ArrayList<String> newArgs = new ArrayList();
+ String exeORpid = null;
+ String core = null;
+ String s = null;
+
+ while((s = sg.next(null, longOpts)) != null) {
+ if (s.equals("exe")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("core")) {
+ core = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("pid")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("mixed")) {
+ newArgs.add("-m");
+ continue;
+ }
+ if (s.equals("locks")) {
+ newArgs.add("-l");
+ continue;
+ }
+ }
+
+ if (exeORpid != null) {
+ newArgs.add(exeORpid);
+ if (core != null) {
+ newArgs.add(core);
+ }
+ }
+
+ JStack.main(newArgs.toArray(new String[newArgs.size()]));
+ }
+
+ private static void runJMAP(String[] oldArgs) {
+ SAGetopt sg = new SAGetopt(oldArgs);
+ String[] longOpts = {"exe=", "core=", "pid=",
+ "heap", "binaryheap", "histo", "clstats", "finalizerinfo"};
+
+ ArrayList<String> newArgs = new ArrayList();
+ String exeORpid = null;
+ String core = null;
+ String s = null;
+
+ while((s = sg.next(null, longOpts)) != null) {
+ if (s.equals("exe")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("core")) {
+ core = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("pid")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("heap")) {
+ newArgs.add("-heap");
+ continue;
+ }
+ if (s.equals("binaryheap")) {
+ newArgs.add("-heap:format=b");
+ continue;
+ }
+ if (s.equals("histo")) {
+ newArgs.add("-histo");
+ continue;
+ }
+ if (s.equals("clstats")) {
+ newArgs.add("-clstats");
+ continue;
+ }
+ if (s.equals("finalizerinfo")) {
+ newArgs.add("-finalizerinfo");
+ continue;
+ }
+ }
+
+ if (exeORpid != null) {
+ newArgs.add(exeORpid);
+ if (core != null) {
+ newArgs.add(core);
+ }
+ }
+
+ JMap.main(newArgs.toArray(new String[newArgs.size()]));
+ }
+
+ private static void runJINFO(String[] oldArgs) {
+ SAGetopt sg = new SAGetopt(oldArgs);
+ String[] longOpts = {"exe=", "core=", "pid=",
+ "flags", "sysprops"};
+
+ ArrayList<String> newArgs = new ArrayList();
+ String exeORpid = null;
+ String core = null;
+ String s = null;
+
+ while((s = sg.next(null, longOpts)) != null) {
+ if (s.equals("exe")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("core")) {
+ core = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("pid")) {
+ exeORpid = sg.getOptarg();
+ continue;
+ }
+ if (s.equals("flags")) {
+ newArgs.add("-flags");
+ continue;
+ }
+ if (s.equals("sysprops")) {
+ newArgs.add("-sysprops");
+ continue;
+ }
+ }
+
+ if (exeORpid != null) {
+ newArgs.add(exeORpid);
+ if (core != null) {
+ newArgs.add(core);
+ }
+ }
+
+ JInfo.main(newArgs.toArray(new String[newArgs.size()]));
+ }
+
+ public static void main(String[] args) {
+ // Provide a help
+ if (args.length == 0) {
+ launcherHelp();
+ return;
+ }
+ // No arguments imply help for jstack, jmap, jinfo but launch clhsdb and hsdb
+ if (args.length == 1 && !args[0].equals("clhsdb") && !args[0].equals("hsdb")) {
+ toolHelp(args[0]);
+ return;
+ }
+
+ for (String arg : args) {
+ if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) {
+ toolHelp(args[0]);
+ return;
+ }
+ }
+
+ String[] oldArgs = Arrays.copyOfRange(args, 1, args.length);
+
+ // Run SA interactive mode
+ if (args[0].equals("clhsdb")) {
+ runCLHSDB(oldArgs);
+ return;
+ }
+
+ if (args[0].equals("hsdb")) {
+ runHSDB(oldArgs);
+ return;
+ }
+
+ // Run SA tmtools mode
+ if (args[0].equals("jstack")) {
+ runJSTACK(oldArgs);
+ return;
+ }
+
+ if (args[0].equals("jmap")) {
+ runJMAP(oldArgs);
+ return;
+ }
+
+ if (args[0].equals("jinfo")) {
+ runJINFO(oldArgs);
+ return;
+ }
+ }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java Mon Aug 10 18:58:25 2015 -0700
@@ -37,6 +37,21 @@
public abstract class AARCH64ThreadContext implements ThreadContext {
// Taken from /usr/include/asm/sigcontext.h on Linux/AARCH64.
+ // /*
+ // * Signal context structure - contains all info to do with the state
+ // * before the signal handler was invoked.
+ // */
+ // struct sigcontext {
+ // __u64 fault_address;
+ // /* AArch64 registers */
+ // __u64 regs[31];
+ // __u64 sp;
+ // __u64 pc;
+ // __u64 pstate;
+ // /* 4K reserved for FP/SIMD state and future expansion */
+ // __u8 __reserved[4096] __attribute__((__aligned__(16)));
+ // };
+
// NOTE: the indices for the various registers must be maintained as
// listed across various operating systems. However, only a small
// subset of the registers' values are guaranteed to be present (and
@@ -78,8 +93,9 @@
public static final int LR = 30;
public static final int SP = 31;
public static final int PC = 32;
+ public static final int PSTATE = 33;
- public static final int NPRGREG = 33;
+ public static final int NPRGREG = 34;
private long[] data;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1Allocator.java Thu Aug 06 13:00:45 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-package sun.jvm.hotspot.gc.g1;
-
-import java.util.Observable;
-import java.util.Observer;
-
-import sun.jvm.hotspot.debugger.Address;
-import sun.jvm.hotspot.runtime.VM;
-import sun.jvm.hotspot.runtime.VMObject;
-import sun.jvm.hotspot.types.CIntegerField;
-import sun.jvm.hotspot.types.Type;
-import sun.jvm.hotspot.types.TypeDataBase;
-
-public class G1Allocator extends VMObject {
-
- //size_t _summary_bytes_used;
- static private CIntegerField summaryBytesUsedField;
-
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- static private synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("G1Allocator");
-
- summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
- }
-
- public long getSummaryBytes() {
- return summaryBytesUsedField.getValue(addr);
- }
-
- public G1Allocator(Address addr) {
- super(addr);
-
- }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java Mon Aug 10 18:58:25 2015 -0700
@@ -36,6 +36,7 @@
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.runtime.VMObjectFactory;
import sun.jvm.hotspot.types.AddressField;
+import sun.jvm.hotspot.types.CIntegerField;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
@@ -46,8 +47,8 @@
static private long hrmFieldOffset;
// MemRegion _g1_reserved;
static private long g1ReservedFieldOffset;
- // G1Allocator* _allocator
- static private AddressField g1Allocator;
+ // size_t _summary_bytes_used;
+ static private CIntegerField summaryBytesUsedField;
// G1MonitoringSupport* _g1mm;
static private AddressField g1mmField;
// HeapRegionSet _old_set;
@@ -67,7 +68,7 @@
Type type = db.lookupType("G1CollectedHeap");
hrmFieldOffset = type.getField("_hrm").getOffset();
- g1Allocator = type.getAddressField("_allocator");
+ summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
g1mmField = type.getAddressField("_g1mm");
oldSetFieldOffset = type.getField("_old_set").getOffset();
humongousSetFieldOffset = type.getField("_humongous_set").getOffset();
@@ -78,7 +79,7 @@
}
public long used() {
- return allocator().getSummaryBytes();
+ return summaryBytesUsedField.getValue(addr);
}
public long n_regions() {
@@ -96,11 +97,6 @@
return (G1MonitoringSupport) VMObjectFactory.newObject(G1MonitoringSupport.class, g1mmAddr);
}
- public G1Allocator allocator() {
- Address g1AllocatorAddr = g1Allocator.getValue(addr);
- return (G1Allocator) VMObjectFactory.newObject(G1Allocator.class, g1AllocatorAddr);
- }
-
public HeapRegionSetBase oldSet() {
Address oldSetAddr = addr.addOffsetTo(oldSetFieldOffset);
return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Aug 10 18:58:25 2015 -0700
@@ -2167,8 +2167,12 @@
return 0; // Self copy, no move.
}
+ bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi &&
+ (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi;
+ int src_offset = ra_->reg2offset(src_lo);
+ int dst_offset = ra_->reg2offset(dst_lo);
+
if (bottom_type()->isa_vect() != NULL) {
- uint len = 4;
uint ireg = ideal_reg();
assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector");
if (cbuf) {
@@ -2176,334 +2180,115 @@
assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity");
if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
// stack->stack
- int src_offset = ra_->reg2offset(src_lo);
- int dst_offset = ra_->reg2offset(dst_lo);
assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset");
- len = 8;
if (ireg == Op_VecD) {
- __ ldr(rscratch1, Address(sp, src_offset));
- __ str(rscratch1, Address(sp, dst_offset));
+ __ unspill(rscratch1, true, src_offset);
+ __ spill(rscratch1, true, dst_offset);
} else {
- if (src_offset < 512) {
- __ ldp(rscratch1, rscratch2, Address(sp, src_offset));
- } else {
- __ ldr(rscratch1, Address(sp, src_offset));
- __ ldr(rscratch2, Address(sp, src_offset+4));
- len += 4;
- }
- if (dst_offset < 512) {
- __ stp(rscratch1, rscratch2, Address(sp, dst_offset));
- } else {
- __ str(rscratch1, Address(sp, dst_offset));
- __ str(rscratch2, Address(sp, dst_offset+4));
- len += 4;
- }
+ __ spill_copy128(src_offset, dst_offset);
}
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
- __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ __ mov(as_FloatRegister(Matcher::_regEncode[dst_lo]),
ireg == Op_VecD ? __ T8B : __ T16B,
- as_FloatRegister(Matcher::_regEncode[src_lo]),
as_FloatRegister(Matcher::_regEncode[src_lo]));
} else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
- __ str(as_FloatRegister(Matcher::_regEncode[src_lo]),
- ireg == Op_VecD ? __ D : __ Q,
- Address(sp, ra_->reg2offset(dst_lo)));
+ __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
+ ireg == Op_VecD ? __ D : __ Q,
+ ra_->reg2offset(dst_lo));
} else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
- __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- ireg == Op_VecD ? __ D : __ Q,
- Address(sp, ra_->reg2offset(src_lo)));
+ __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ ireg == Op_VecD ? __ D : __ Q,
+ ra_->reg2offset(src_lo));
} else {
ShouldNotReachHere();
}
- } else if (st) {
- if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
- // stack->stack
- int src_offset = ra_->reg2offset(src_lo);
- int dst_offset = ra_->reg2offset(dst_lo);
- if (ireg == Op_VecD) {
- st->print("ldr rscratch1, [sp, #%d]", src_offset);
- st->print("str rscratch1, [sp, #%d]", dst_offset);
+ }
+ } else if (cbuf) {
+ MacroAssembler _masm(cbuf);
+ switch (src_lo_rc) {
+ case rc_int:
+ if (dst_lo_rc == rc_int) { // gpr --> gpr copy
+ if (is64) {
+ __ mov(as_Register(Matcher::_regEncode[dst_lo]),
+ as_Register(Matcher::_regEncode[src_lo]));
} else {
- if (src_offset < 512) {
- st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset);
- } else {
- st->print("ldr rscratch1, [sp, #%d]", src_offset);
- st->print("\nldr rscratch2, [sp, #%d]", src_offset+4);
- }
- if (dst_offset < 512) {
- st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset);
- } else {
- st->print("\nstr rscratch1, [sp, #%d]", dst_offset);
- st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4);
- }
- }
- st->print("\t# vector spill, stack to stack");
- } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
- st->print("mov %s, %s\t# vector spill, reg to reg",
- Matcher::regName[dst_lo], Matcher::regName[src_lo]);
- } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
- st->print("str %s, [sp, #%d]\t# vector spill, reg to stack",
- Matcher::regName[src_lo], ra_->reg2offset(dst_lo));
- } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
- st->print("ldr %s, [sp, #%d]\t# vector spill, stack to reg",
- Matcher::regName[dst_lo], ra_->reg2offset(src_lo));
- }
- }
- return len;
- }
-
- switch (src_lo_rc) {
- case rc_int:
- if (dst_lo_rc == rc_int) { // gpr --> gpr copy
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ mov(as_Register(Matcher::_regEncode[dst_lo]),
- as_Register(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("mov %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ movw(as_Register(Matcher::_regEncode[dst_lo]),
- as_Register(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("movw %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
+ MacroAssembler _masm(cbuf);
+ __ movw(as_Register(Matcher::_regEncode[dst_lo]),
+ as_Register(Matcher::_regEncode[src_lo]));
}
- }
- } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- as_Register(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovd %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- as_Register(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovs %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- }
- } else { // gpr --> stack spill
- assert(dst_lo_rc == rc_stack, "spill to bad register class");
- int dst_offset = ra_->reg2offset(dst_lo);
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ str(as_Register(Matcher::_regEncode[src_lo]),
- Address(sp, dst_offset));
- } else if (st) {
- st->print("str %s, [sp, #%d]\t# spill",
- Matcher::regName[src_lo],
- dst_offset);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ strw(as_Register(Matcher::_regEncode[src_lo]),
- Address(sp, dst_offset));
- } else if (st) {
- st->print("strw %s, [sp, #%d]\t# spill",
- Matcher::regName[src_lo],
- dst_offset);
- }
- }
- }
- return 4;
- case rc_float:
- if (dst_lo_rc == rc_int) { // fpr --> gpr copy
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
- as_FloatRegister(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovd %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
+ } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
+ if (is64) {
+ __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ as_Register(Matcher::_regEncode[src_lo]));
+ } else {
+ __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ as_Register(Matcher::_regEncode[src_lo]));
}
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
- as_FloatRegister(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovs %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- }
- } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- as_FloatRegister(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovd %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- as_FloatRegister(Matcher::_regEncode[src_lo]));
- } else if (st) {
- st->print("fmovs %s, %s\t# shuffle",
- Matcher::regName[dst_lo],
- Matcher::regName[src_lo]);
- }
- }
- } else { // fpr --> stack spill
- assert(dst_lo_rc == rc_stack, "spill to bad register class");
- int dst_offset = ra_->reg2offset(dst_lo);
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ strd(as_FloatRegister(Matcher::_regEncode[src_lo]),
- Address(sp, dst_offset));
- } else if (st) {
- st->print("strd %s, [sp, #%d]\t# spill",
- Matcher::regName[src_lo],
- dst_offset);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ strs(as_FloatRegister(Matcher::_regEncode[src_lo]),
- Address(sp, dst_offset));
- } else if (st) {
- st->print("strs %s, [sp, #%d]\t# spill",
- Matcher::regName[src_lo],
- dst_offset);
- }
+ } else { // gpr --> stack spill
+ assert(dst_lo_rc == rc_stack, "spill to bad register class");
+ __ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset);
}
- }
- return 4;
- case rc_stack:
- int src_offset = ra_->reg2offset(src_lo);
- if (dst_lo_rc == rc_int) { // stack --> gpr load
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldr(as_Register(Matcher::_regEncode[dst_lo]),
- Address(sp, src_offset));
- } else if (st) {
- st->print("ldr %s, [sp, %d]\t# restore",
- Matcher::regName[dst_lo],
- src_offset);
+ break;
+ case rc_float:
+ if (dst_lo_rc == rc_int) { // fpr --> gpr copy
+ if (is64) {
+ __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),
+ as_FloatRegister(Matcher::_regEncode[src_lo]));
+ } else {
+ __ fmovs(as_Register(Matcher::_regEncode[dst_lo]),
+ as_FloatRegister(Matcher::_regEncode[src_lo]));
}
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldrw(as_Register(Matcher::_regEncode[dst_lo]),
- Address(sp, src_offset));
- } else if (st) {
- st->print("ldr %s, [sp, %d]\t# restore",
- Matcher::regName[dst_lo],
- src_offset);
- }
- }
- return 4;
- } else if (dst_lo_rc == rc_float) { // stack --> fpr load
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldrd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- Address(sp, src_offset));
- } else if (st) {
- st->print("ldrd %s, [sp, %d]\t# restore",
- Matcher::regName[dst_lo],
- src_offset);
+ } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
+ if (cbuf) {
+ __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ as_FloatRegister(Matcher::_regEncode[src_lo]));
+ } else {
+ __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ as_FloatRegister(Matcher::_regEncode[src_lo]));
}
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldrs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
- Address(sp, src_offset));
- } else if (st) {
- st->print("ldrs %s, [sp, %d]\t# restore",
- Matcher::regName[dst_lo],
- src_offset);
- }
+ } else { // fpr --> stack spill
+ assert(dst_lo_rc == rc_stack, "spill to bad register class");
+ __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
+ is64 ? __ D : __ S, dst_offset);
}
- return 4;
- } else { // stack --> stack copy
- assert(dst_lo_rc == rc_stack, "spill to bad register class");
- int dst_offset = ra_->reg2offset(dst_lo);
- if (((src_lo & 1) == 0 && src_lo + 1 == src_hi) &&
- (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) {
- // 64 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldr(rscratch1, Address(sp, src_offset));
- __ str(rscratch1, Address(sp, dst_offset));
- } else if (st) {
- st->print("ldr rscratch1, [sp, %d]\t# mem-mem spill",
- src_offset);
- st->print("\n\t");
- st->print("str rscratch1, [sp, %d]",
- dst_offset);
- }
- } else {
- // 32 bit
- if (cbuf) {
- MacroAssembler _masm(cbuf);
- __ ldrw(rscratch1, Address(sp, src_offset));
- __ strw(rscratch1, Address(sp, dst_offset));
- } else if (st) {
- st->print("ldrw rscratch1, [sp, %d]\t# mem-mem spill",
- src_offset);
- st->print("\n\t");
- st->print("strw rscratch1, [sp, %d]",
- dst_offset);
- }
+ break;
+ case rc_stack:
+ if (dst_lo_rc == rc_int) { // stack --> gpr load
+ __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
+ } else if (dst_lo_rc == rc_float) { // stack --> fpr load
+ __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+ is64 ? __ D : __ S, src_offset);
+ } else { // stack --> stack copy
+ assert(dst_lo_rc == rc_stack, "spill to bad register class");
+ __ unspill(rscratch1, is64, src_offset);
+ __ spill(rscratch1, is64, dst_offset);
}
- return 8;
+ break;
+ default:
+ assert(false, "bad rc_class for spill");
+ ShouldNotReachHere();
}
}
- assert(false," bad rc_class for spill ");
- Unimplemented();
+ if (st) {
+ st->print("spill ");
+ if (src_lo_rc == rc_stack) {
+ st->print("[sp, #%d] -> ", ra_->reg2offset(src_lo));
+ } else {
+ st->print("%s -> ", Matcher::regName[src_lo]);
+ }
+ if (dst_lo_rc == rc_stack) {
+ st->print("[sp, #%d]", ra_->reg2offset(dst_lo));
+ } else {
+ st->print("%s", Matcher::regName[dst_lo]);
+ }
+ if (bottom_type()->isa_vect() != NULL) {
+ st->print("\t# vector spill size = %d", ideal_reg()==Op_VecD ? 64:128);
+ } else {
+ st->print("\t# spill size = %d", is64 ? 64:32);
+ }
+ }
+
return 0;
}
@@ -2522,7 +2307,7 @@
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation(NULL, ra_, true, NULL);
+ return MachNode::size(ra_);
}
//=============================================================================
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -1896,7 +1896,7 @@
public:
enum SIMD_Arrangement {
- T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D
+ T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
};
enum SIMD_RegVariant {
@@ -2225,14 +2225,16 @@
f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0);
}
- // We do not handle the 1Q arrangement.
void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
starti;
- assert(Ta == T8H && (Tb == T8B || Tb == T16B), "Invalid Size specifier");
- f(0, 31), f(Tb & 1, 30), f(0b001110001, 29, 21), rf(Vm, 16), f(0b111000, 15, 10);
- rf(Vn, 5), rf(Vd, 0);
+ assert((Ta == T1Q && (Tb == T1D || Tb == T2D)) ||
+ (Ta == T8H && (Tb == T8B || Tb == T16B)), "Invalid Size specifier");
+ int size = (Ta == T1Q) ? 0b11 : 0b00;
+ f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size, 23, 22);
+ f(1, 21), rf(Vm, 16), f(0b111000, 15, 10), rf(Vn, 5), rf(Vd, 0);
}
void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {
+ assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier");
pmull(Vd, Ta, Vn, Vm, Tb);
}
@@ -2245,15 +2247,6 @@
f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);
}
- void rev32(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn)
- {
- starti;
- assert(T <= T8H, "must be one of T8B, T16B, T4H, T8H");
- f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24);
- f(T <= T16B ? 0b00 : 0b01, 23, 22), f(0b100000000010, 21, 10);
- rf(Vn, 5), rf(Vd, 0);
- }
-
void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
{
starti;
@@ -2290,6 +2283,57 @@
#undef INSN
+ // Table vector lookup
+#define INSN(NAME, op) \
+ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) { \
+ starti; \
+ assert(T == T8B || T == T16B, "invalid arrangement"); \
+ assert(0 < registers && registers <= 4, "invalid number of registers"); \
+ f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15); \
+ f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0); \
+ }
+
+ INSN(tbl, 0);
+ INSN(tbx, 1);
+
+#undef INSN
+
+#define INSN(NAME, U, opcode) \
+ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
+ starti; \
+ assert((ASSERTION), MSG); \
+ f(0, 31), f((int)T & 1, 30), f(U, 29), f(0b01110, 28, 24); \
+ f((int)(T >> 1), 23, 22), f(0b10000, 21, 17), f(opcode, 16, 12); \
+ f(0b10, 11, 10), rf(Vn, 5), rf(Vd, 0); \
+ }
+
+#define MSG "invalid arrangement"
+
+#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H || T == T2S || T == T4S)
+ INSN(rev64, 0, 0b00000);
+#undef ASSERTION
+
+#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H)
+ INSN(rev32, 1, 0b00000);
+#undef ASSERTION
+
+#define ASSERTION (T == T8B || T == T16B)
+ INSN(rev16, 0, 0b00001);
+#undef ASSERTION
+
+#undef MSG
+
+#undef INSN
+
+void ext(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index)
+ {
+ starti;
+ assert(T == T8B || T == T16B, "invalid arrangement");
+ assert((T == T8B && index <= 0b0111) || (T == T16B && index <= 0b1111), "Invalid index value");
+ f(0, 31), f((int)T & 1, 30), f(0b101110000, 29, 21);
+ rf(Vm, 16), f(0, 15), f(index, 14, 11);
+ f(0, 10), rf(Vn, 5), rf(Vd, 0);
+ }
/* Simulator extensions to the ISA
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -2009,6 +2009,14 @@
}
}
+void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
+ if (decrement.is_register()) {
+ sub(Rd, Rn, decrement.as_register());
+ } else {
+ sub(Rd, Rn, decrement.as_constant());
+ }
+}
+
void MacroAssembler::reinit_heapbase()
{
if (UseCompressedOops) {
@@ -2307,6 +2315,28 @@
}
}
+Address MacroAssembler::spill_address(int size, int offset, Register tmp)
+{
+ assert(offset >= 0, "spill to negative address?");
+ // Offset reachable ?
+ // Not aligned - 9 bits signed offset
+ // Aligned - 12 bits unsigned offset shifted
+ Register base = sp;
+ if ((offset & (size-1)) && offset >= (1<<8)) {
+ add(tmp, base, offset & ((1<<12)-1));
+ base = tmp;
+ offset &= -1<<12;
+ }
+
+ if (offset >= (1<<12) * size) {
+ add(tmp, base, offset & (((1<<12)-1)<<12));
+ base = tmp;
+ offset &= ~(((1<<12)-1)<<12);
+ }
+
+ return Address(base, offset);
+}
+
/**
* Multiply 64 bit by 64 bit first loop.
*/
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -464,10 +464,21 @@
mov(dst, (long)i);
}
+ void mov(Register dst, RegisterOrConstant src) {
+ if (src.is_register())
+ mov(dst, src.as_register());
+ else
+ mov(dst, src.as_constant());
+ }
+
void movptr(Register r, uintptr_t imm64);
void mov(FloatRegister Vd, SIMD_Arrangement T, u_int32_t imm32);
+ void mov(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
+ orr(Vd, T, Vn, Vn);
+ }
+
// macro instructions for accessing and updating floating point
// status register
//
@@ -1045,6 +1056,7 @@
void add(Register Rd, Register Rn, RegisterOrConstant increment);
void addw(Register Rd, Register Rn, RegisterOrConstant increment);
+ void sub(Register Rd, Register Rn, RegisterOrConstant decrement);
void adrp(Register reg1, const Address &dest, unsigned long &byte_offset);
@@ -1161,6 +1173,46 @@
// Uses rscratch2.
Address offsetted_address(Register r, Register r1, Address::extend ext,
int offset, int size);
+
+private:
+ // Returns an address on the stack which is reachable with a ldr/str of size
+ // Uses rscratch2 if the address is not directly reachable
+ Address spill_address(int size, int offset, Register tmp=rscratch2);
+
+public:
+ void spill(Register Rx, bool is64, int offset) {
+ if (is64) {
+ str(Rx, spill_address(8, offset));
+ } else {
+ strw(Rx, spill_address(4, offset));
+ }
+ }
+ void spill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
+ str(Vx, T, spill_address(1 << (int)T, offset));
+ }
+ void unspill(Register Rx, bool is64, int offset) {
+ if (is64) {
+ ldr(Rx, spill_address(8, offset));
+ } else {
+ ldrw(Rx, spill_address(4, offset));
+ }
+ }
+ void unspill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
+ ldr(Vx, T, spill_address(1 << (int)T, offset));
+ }
+ void spill_copy128(int src_offset, int dst_offset,
+ Register tmp1=rscratch1, Register tmp2=rscratch2) {
+ if (src_offset < 512 && (src_offset & 7) == 0 &&
+ dst_offset < 512 && (dst_offset & 7) == 0) {
+ ldp(tmp1, tmp2, Address(sp, src_offset));
+ stp(tmp1, tmp2, Address(sp, dst_offset));
+ } else {
+ unspill(tmp1, true, src_offset);
+ spill(tmp1, true, dst_offset);
+ unspill(tmp1, true, src_offset+8);
+ spill(tmp1, true, dst_offset+8);
+ }
+ }
};
#ifdef ASSERT
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -120,10 +120,8 @@
// we save r19-r28 which Java uses as scratch registers and C
// expects to be callee-save
//
- // we don't save any FP registers since only v8-v15 are callee-save
- // (strictly only the f and d components) and Java uses them as
- // callee-save. v0-v7 are arg registers and C treats v16-v31 as
- // volatile (as does Java?)
+ // we save the bottom 64 bits of each value stored in v8-v15; it is
+ // the responsibility of the caller to preserve larger values.
//
// so the stub frame looks like this when we enter Java code
//
@@ -131,14 +129,14 @@
// [ argument word n ]
// ...
// -27 [ argument word 1 ]
- // -26 [ saved d15 ] <--- sp_after_call
- // -25 [ saved d14 ]
- // -24 [ saved d13 ]
- // -23 [ saved d12 ]
- // -22 [ saved d11 ]
- // -21 [ saved d10 ]
- // -20 [ saved d9 ]
- // -19 [ saved d8 ]
+ // -26 [ saved v15 ] <--- sp_after_call
+ // -25 [ saved v14 ]
+ // -24 [ saved v13 ]
+ // -23 [ saved v12 ]
+ // -22 [ saved v11 ]
+ // -21 [ saved v10 ]
+ // -20 [ saved v9 ]
+ // -19 [ saved v8 ]
// -18 [ saved r28 ]
// -17 [ saved r27 ]
// -16 [ saved r26 ]
@@ -2437,6 +2435,137 @@
return start;
}
+ /**
+ * Arguments:
+ *
+ * Input:
+ * c_rarg0 - current state address
+ * c_rarg1 - H key address
+ * c_rarg2 - data address
+ * c_rarg3 - number of blocks
+ *
+ * Output:
+ * Updated state at c_rarg0
+ */
+ address generate_ghash_processBlocks() {
+ __ align(CodeEntryAlignment);
+ Label L_ghash_loop, L_exit;
+
+ StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ address start = __ pc();
+
+ Register state = c_rarg0;
+ Register subkeyH = c_rarg1;
+ Register data = c_rarg2;
+ Register blocks = c_rarg3;
+
+ FloatRegister vzr = v30;
+ __ eor(vzr, __ T16B, vzr, vzr); // zero register
+
+ __ mov(v26, __ T16B, 1);
+ __ mov(v27, __ T16B, 63);
+ __ mov(v28, __ T16B, 62);
+ __ mov(v29, __ T16B, 57);
+
+ __ ldrq(v6, Address(state));
+ __ ldrq(v16, Address(subkeyH));
+
+ __ ext(v0, __ T16B, v6, v6, 0x08);
+ __ ext(v1, __ T16B, v16, v16, 0x08);
+ __ eor(v16, __ T16B, v16, v1);
+
+ __ bind(L_ghash_loop);
+
+ __ ldrq(v2, Address(__ post(data, 0x10)));
+ __ rev64(v2, __ T16B, v2); // swap data
+
+ __ ext(v6, __ T16B, v0, v0, 0x08);
+ __ eor(v6, __ T16B, v6, v2);
+ __ ext(v2, __ T16B, v6, v6, 0x08);
+
+ __ pmull2(v7, __ T1Q, v2, v1, __ T2D); // A1*B1
+ __ eor(v6, __ T16B, v6, v2);
+ __ pmull(v5, __ T1Q, v2, v1, __ T1D); // A0*B0
+ __ pmull(v20, __ T1Q, v6, v16, __ T1D); // (A1 + A0)(B1 + B0)
+
+ __ ext(v21, __ T16B, v5, v7, 0x08);
+ __ eor(v18, __ T16B, v7, v5); // A1*B1 xor A0*B0
+ __ eor(v20, __ T16B, v20, v21);
+ __ eor(v20, __ T16B, v20, v18);
+
+ // Registers pair <v7:v5> holds the result of carry-less multiplication
+ __ ins(v7, __ D, v20, 0, 1);
+ __ ins(v5, __ D, v20, 1, 0);
+
+ // Result of the multiplication is shifted by one bit position
+ // [X3:X2:X1:X0] = [X3:X2:X1:X0] << 1
+ __ ushr(v18, __ T2D, v5, -63 & 63);
+ __ ins(v25, __ D, v18, 1, 0);
+ __ ins(v25, __ D, vzr, 0, 0);
+ __ ushl(v5, __ T2D, v5, v26);
+ __ orr(v5, __ T16B, v5, v25);
+
+ __ ushr(v19, __ T2D, v7, -63 & 63);
+ __ ins(v19, __ D, v19, 1, 0);
+ __ ins(v19, __ D, v18, 0, 1);
+ __ ushl(v7, __ T2D, v7, v26);
+ __ orr(v6, __ T16B, v7, v19);
+
+ __ ins(v24, __ D, v5, 0, 1);
+
+ // A = X0 << 63
+ __ ushl(v21, __ T2D, v5, v27);
+
+ // A = X0 << 62
+ __ ushl(v22, __ T2D, v5, v28);
+
+ // A = X0 << 57
+ __ ushl(v23, __ T2D, v5, v29);
+
+ // D = X1^A^B^C
+ __ eor(v21, __ T16B, v21, v22);
+ __ eor(v21, __ T16B, v21, v23);
+ __ eor(v21, __ T16B, v21, v24);
+ __ ins(v5, __ D, v21, 1, 0);
+
+ // [E1:E0] = [D:X0] >> 1
+ __ ushr(v20, __ T2D, v5, -1 & 63);
+ __ ushl(v18, __ T2D, v5, v27);
+ __ ext(v25, __ T16B, v18, vzr, 0x08);
+ __ orr(v19, __ T16B, v20, v25);
+
+ __ eor(v7, __ T16B, v5, v19);
+
+ // [F1:F0] = [D:X0] >> 2
+ __ ushr(v20, __ T2D, v5, -2 & 63);
+ __ ushl(v18, __ T2D, v5, v28);
+ __ ins(v25, __ D, v18, 0, 1);
+ __ orr(v19, __ T16B, v20, v25);
+
+ __ eor(v7, __ T16B, v7, v19);
+
+ // [G1:G0] = [D:X0] >> 7
+ __ ushr(v20, __ T2D, v5, -7 & 63);
+ __ ushl(v18, __ T2D, v5, v29);
+ __ ins(v25, __ D, v18, 0, 1);
+ __ orr(v19, __ T16B, v20, v25);
+
+ // [H1:H0] = [D^E1^F1^G1:X0^E0^F0^G0]
+ __ eor(v7, __ T16B, v7, v19);
+
+ // Result = [H1:H0]^[X3:X2]
+ __ eor(v0, __ T16B, v7, v6);
+
+ __ subs(blocks, blocks, 1);
+ __ cbnz(blocks, L_ghash_loop);
+
+ __ ext(v1, __ T16B, v0, v0, 0x08);
+ __ st1(v1, __ T16B, state);
+ __ ret(lr);
+
+ return start;
+ }
+
// Continuation point for throwing of implicit exceptions that are
// not handled in the current activation. Fabricates an exception
// oop and initiates normal exception dispatching in this
@@ -2544,6 +2673,828 @@
return stub->entry_point();
}
+ class MontgomeryMultiplyGenerator : public MacroAssembler {
+
+ Register Pa_base, Pb_base, Pn_base, Pm_base, inv, Rlen, Ra, Rb, Rm, Rn,
+ Pa, Pb, Pn, Pm, Rhi_ab, Rlo_ab, Rhi_mn, Rlo_mn, t0, t1, t2, Ri, Rj;
+
+ RegSet _toSave;
+ bool _squaring;
+
+ public:
+ MontgomeryMultiplyGenerator (Assembler *as, bool squaring)
+ : MacroAssembler(as->code()), _squaring(squaring) {
+
+ // Register allocation
+
+ Register reg = c_rarg0;
+ Pa_base = reg; // Argument registers
+ if (squaring)
+ Pb_base = Pa_base;
+ else
+ Pb_base = ++reg;
+ Pn_base = ++reg;
+ Rlen= ++reg;
+ inv = ++reg;
+ Pm_base = ++reg;
+
+ // Working registers:
+ Ra = ++reg; // The current digit of a, b, n, and m.
+ Rb = ++reg;
+ Rm = ++reg;
+ Rn = ++reg;
+
+ Pa = ++reg; // Pointers to the current/next digit of a, b, n, and m.
+ Pb = ++reg;
+ Pm = ++reg;
+ Pn = ++reg;
+
+ t0 = ++reg; // Three registers which form a
+ t1 = ++reg; // triple-precision accumuator.
+ t2 = ++reg;
+
+ Ri = ++reg; // Inner and outer loop indexes.
+ Rj = ++reg;
+
+ Rhi_ab = ++reg; // Product registers: low and high parts
+ Rlo_ab = ++reg; // of a*b and m*n.
+ Rhi_mn = ++reg;
+ Rlo_mn = ++reg;
+
+ // r19 and up are callee-saved.
+ _toSave = RegSet::range(r19, reg) + Pm_base;
+ }
+
+ private:
+ void save_regs() {
+ push(_toSave, sp);
+ }
+
+ void restore_regs() {
+ pop(_toSave, sp);
+ }
+
+ template <typename T>
+ void unroll_2(Register count, T block) {
+ Label loop, end, odd;
+ tbnz(count, 0, odd);
+ cbz(count, end);
+ align(16);
+ bind(loop);
+ (this->*block)();
+ bind(odd);
+ (this->*block)();
+ subs(count, count, 2);
+ br(Assembler::GT, loop);
+ bind(end);
+ }
+
+ template <typename T>
+ void unroll_2(Register count, T block, Register d, Register s, Register tmp) {
+ Label loop, end, odd;
+ tbnz(count, 0, odd);
+ cbz(count, end);
+ align(16);
+ bind(loop);
+ (this->*block)(d, s, tmp);
+ bind(odd);
+ (this->*block)(d, s, tmp);
+ subs(count, count, 2);
+ br(Assembler::GT, loop);
+ bind(end);
+ }
+
+ void pre1(RegisterOrConstant i) {
+ block_comment("pre1");
+ // Pa = Pa_base;
+ // Pb = Pb_base + i;
+ // Pm = Pm_base;
+ // Pn = Pn_base + i;
+ // Ra = *Pa;
+ // Rb = *Pb;
+ // Rm = *Pm;
+ // Rn = *Pn;
+ ldr(Ra, Address(Pa_base));
+ ldr(Rb, Address(Pb_base, i, Address::uxtw(LogBytesPerWord)));
+ ldr(Rm, Address(Pm_base));
+ ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+ lea(Pa, Address(Pa_base));
+ lea(Pb, Address(Pb_base, i, Address::uxtw(LogBytesPerWord)));
+ lea(Pm, Address(Pm_base));
+ lea(Pn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+
+ // Zero the m*n result.
+ mov(Rhi_mn, zr);
+ mov(Rlo_mn, zr);
+ }
+
+ // The core multiply-accumulate step of a Montgomery
+ // multiplication. The idea is to schedule operations as a
+ // pipeline so that instructions with long latencies (loads and
+ // multiplies) have time to complete before their results are
+ // used. This most benefits in-order implementations of the
+ // architecture but out-of-order ones also benefit.
+ void step() {
+ block_comment("step");
+ // MACC(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ umulh(Rhi_ab, Ra, Rb);
+ mul(Rlo_ab, Ra, Rb);
+ ldr(Ra, pre(Pa, wordSize));
+ ldr(Rb, pre(Pb, -wordSize));
+ acc(Rhi_mn, Rlo_mn, t0, t1, t2); // The pending m*n from the
+ // previous iteration.
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ umulh(Rhi_mn, Rm, Rn);
+ mul(Rlo_mn, Rm, Rn);
+ ldr(Rm, pre(Pm, wordSize));
+ ldr(Rn, pre(Pn, -wordSize));
+ acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+ }
+
+ void post1() {
+ block_comment("post1");
+
+ // MACC(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ umulh(Rhi_ab, Ra, Rb);
+ mul(Rlo_ab, Ra, Rb);
+ acc(Rhi_mn, Rlo_mn, t0, t1, t2); // The pending m*n
+ acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+
+ // *Pm = Rm = t0 * inv;
+ mul(Rm, t0, inv);
+ str(Rm, Address(Pm));
+
+ // MACC(Rm, Rn, t0, t1, t2);
+ // t0 = t1; t1 = t2; t2 = 0;
+ umulh(Rhi_mn, Rm, Rn);
+
+#ifndef PRODUCT
+ // assert(m[i] * n[0] + t0 == 0, "broken Montgomery multiply");
+ {
+ mul(Rlo_mn, Rm, Rn);
+ add(Rlo_mn, t0, Rlo_mn);
+ Label ok;
+ cbz(Rlo_mn, ok); {
+ stop("broken Montgomery multiply");
+ } bind(ok);
+ }
+#endif
+ // We have very carefully set things up so that
+ // m[i]*n[0] + t0 == 0 (mod b), so we don't have to calculate
+ // the lower half of Rm * Rn because we know the result already:
+ // it must be -t0. t0 + (-t0) must generate a carry iff
+ // t0 != 0. So, rather than do a mul and an adds we just set
+ // the carry flag iff t0 is nonzero.
+ //
+ // mul(Rlo_mn, Rm, Rn);
+ // adds(zr, t0, Rlo_mn);
+ subs(zr, t0, 1); // Set carry iff t0 is nonzero
+ adcs(t0, t1, Rhi_mn);
+ adc(t1, t2, zr);
+ mov(t2, zr);
+ }
+
+ void pre2(RegisterOrConstant i, RegisterOrConstant len) {
+ block_comment("pre2");
+ // Pa = Pa_base + i-len;
+ // Pb = Pb_base + len;
+ // Pm = Pm_base + i-len;
+ // Pn = Pn_base + len;
+
+ if (i.is_register()) {
+ sub(Rj, i.as_register(), len);
+ } else {
+ mov(Rj, i.as_constant());
+ sub(Rj, Rj, len);
+ }
+ // Rj == i-len
+
+ lea(Pa, Address(Pa_base, Rj, Address::uxtw(LogBytesPerWord)));
+ lea(Pb, Address(Pb_base, len, Address::uxtw(LogBytesPerWord)));
+ lea(Pm, Address(Pm_base, Rj, Address::uxtw(LogBytesPerWord)));
+ lea(Pn, Address(Pn_base, len, Address::uxtw(LogBytesPerWord)));
+
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ ldr(Ra, pre(Pa, wordSize));
+ ldr(Rb, pre(Pb, -wordSize));
+ ldr(Rm, pre(Pm, wordSize));
+ ldr(Rn, pre(Pn, -wordSize));
+
+ mov(Rhi_mn, zr);
+ mov(Rlo_mn, zr);
+ }
+
+ void post2(RegisterOrConstant i, RegisterOrConstant len) {
+ block_comment("post2");
+ if (i.is_constant()) {
+ mov(Rj, i.as_constant()-len.as_constant());
+ } else {
+ sub(Rj, i.as_register(), len);
+ }
+
+ adds(t0, t0, Rlo_mn); // The pending m*n, low part
+
+ // As soon as we know the least significant digit of our result,
+ // store it.
+ // Pm_base[i-len] = t0;
+ str(t0, Address(Pm_base, Rj, Address::uxtw(LogBytesPerWord)));
+
+ // t0 = t1; t1 = t2; t2 = 0;
+ adcs(t0, t1, Rhi_mn); // The pending m*n, high part
+ adc(t1, t2, zr);
+ mov(t2, zr);
+ }
+
+ // A carry in t0 after Montgomery multiplication means that we
+ // should subtract multiples of n from our result in m. We'll
+ // keep doing that until there is no carry.
+ void normalize(RegisterOrConstant len) {
+ block_comment("normalize");
+ // while (t0)
+ // t0 = sub(Pm_base, Pn_base, t0, len);
+ Label loop, post, again;
+ Register cnt = t1, i = t2; // Re-use registers; we're done with them now
+ cbz(t0, post); {
+ bind(again); {
+ mov(i, zr);
+ mov(cnt, len);
+ ldr(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+ ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+ subs(zr, zr, zr); // set carry flag, i.e. no borrow
+ align(16);
+ bind(loop); {
+ sbcs(Rm, Rm, Rn);
+ str(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+ add(i, i, 1);
+ ldr(Rm, Address(Pm_base, i, Address::uxtw(LogBytesPerWord)));
+ ldr(Rn, Address(Pn_base, i, Address::uxtw(LogBytesPerWord)));
+ sub(cnt, cnt, 1);
+ } cbnz(cnt, loop);
+ sbc(t0, t0, zr);
+ } cbnz(t0, again);
+ } bind(post);
+ }
+
+ // Move memory at s to d, reversing words.
+ // Increments d to end of copied memory
+ // Destroys tmp1, tmp2
+ // Preserves len
+ // Leaves s pointing to the address which was in d at start
+ void reverse(Register d, Register s, Register len, Register tmp1, Register tmp2) {
+ assert(tmp1 < r19 && tmp2 < r19, "register corruption");
+
+ lea(s, Address(s, len, Address::uxtw(LogBytesPerWord)));
+ mov(tmp1, len);
+ unroll_2(tmp1, &MontgomeryMultiplyGenerator::reverse1, d, s, tmp2);
+ sub(s, d, len, ext::uxtw, LogBytesPerWord);
+ }
+ // where
+ void reverse1(Register d, Register s, Register tmp) {
+ ldr(tmp, pre(s, -wordSize));
+ ror(tmp, tmp, 32);
+ str(tmp, post(d, wordSize));
+ }
+
+ void step_squaring() {
+ // An extra ACC
+ step();
+ acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+ }
+
+ void last_squaring(RegisterOrConstant i) {
+ Label dont;
+ // if ((i & 1) == 0) {
+ tbnz(i.as_register(), 0, dont); {
+ // MACC(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ umulh(Rhi_ab, Ra, Rb);
+ mul(Rlo_ab, Ra, Rb);
+ acc(Rhi_ab, Rlo_ab, t0, t1, t2);
+ } bind(dont);
+ }
+
+ void extra_step_squaring() {
+ acc(Rhi_mn, Rlo_mn, t0, t1, t2); // The pending m*n
+
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ umulh(Rhi_mn, Rm, Rn);
+ mul(Rlo_mn, Rm, Rn);
+ ldr(Rm, pre(Pm, wordSize));
+ ldr(Rn, pre(Pn, -wordSize));
+ }
+
+ void post1_squaring() {
+ acc(Rhi_mn, Rlo_mn, t0, t1, t2); // The pending m*n
+
+ // *Pm = Rm = t0 * inv;
+ mul(Rm, t0, inv);
+ str(Rm, Address(Pm));
+
+ // MACC(Rm, Rn, t0, t1, t2);
+ // t0 = t1; t1 = t2; t2 = 0;
+ umulh(Rhi_mn, Rm, Rn);
+
+#ifndef PRODUCT
+ // assert(m[i] * n[0] + t0 == 0, "broken Montgomery multiply");
+ {
+ mul(Rlo_mn, Rm, Rn);
+ add(Rlo_mn, t0, Rlo_mn);
+ Label ok;
+ cbz(Rlo_mn, ok); {
+ stop("broken Montgomery multiply");
+ } bind(ok);
+ }
+#endif
+ // We have very carefully set things up so that
+ // m[i]*n[0] + t0 == 0 (mod b), so we don't have to calculate
+ // the lower half of Rm * Rn because we know the result already:
+ // it must be -t0. t0 + (-t0) must generate a carry iff
+ // t0 != 0. So, rather than do a mul and an adds we just set
+ // the carry flag iff t0 is nonzero.
+ //
+ // mul(Rlo_mn, Rm, Rn);
+ // adds(zr, t0, Rlo_mn);
+ subs(zr, t0, 1); // Set carry iff t0 is nonzero
+ adcs(t0, t1, Rhi_mn);
+ adc(t1, t2, zr);
+ mov(t2, zr);
+ }
+
+ void acc(Register Rhi, Register Rlo,
+ Register t0, Register t1, Register t2) {
+ adds(t0, t0, Rlo);
+ adcs(t1, t1, Rhi);
+ adc(t2, t2, zr);
+ }
+
+ public:
+ /**
+ * Fast Montgomery multiplication. The derivation of the
+ * algorithm is in A Cryptographic Library for the Motorola
+ * DSP56000, Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237.
+ *
+ * Arguments:
+ *
+ * Inputs for multiplication:
+ * c_rarg0 - int array elements a
+ * c_rarg1 - int array elements b
+ * c_rarg2 - int array elements n (the modulus)
+ * c_rarg3 - int length
+ * c_rarg4 - int inv
+ * c_rarg5 - int array elements m (the result)
+ *
+ * Inputs for squaring:
+ * c_rarg0 - int array elements a
+ * c_rarg1 - int array elements n (the modulus)
+ * c_rarg2 - int length
+ * c_rarg3 - int inv
+ * c_rarg4 - int array elements m (the result)
+ *
+ */
+ address generate_multiply() {
+ Label argh, nothing;
+ bind(argh);
+ stop("MontgomeryMultiply total_allocation must be <= 8192");
+
+ align(CodeEntryAlignment);
+ address entry = pc();
+
+ cbzw(Rlen, nothing);
+
+ enter();
+
+ // Make room.
+ cmpw(Rlen, 512);
+ br(Assembler::HI, argh);
+ sub(Ra, sp, Rlen, ext::uxtw, exact_log2(4 * sizeof (jint)));
+ andr(sp, Ra, -2 * wordSize);
+
+ lsrw(Rlen, Rlen, 1); // length in longwords = len/2
+
+ {
+ // Copy input args, reversing as we go. We use Ra as a
+ // temporary variable.
+ reverse(Ra, Pa_base, Rlen, t0, t1);
+ if (!_squaring)
+ reverse(Ra, Pb_base, Rlen, t0, t1);
+ reverse(Ra, Pn_base, Rlen, t0, t1);
+ }
+
+ // Push all call-saved registers and also Pm_base which we'll need
+ // at the end.
+ save_regs();
+
+#ifndef PRODUCT
+ // assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
+ {
+ ldr(Rn, Address(Pn_base, 0));
+ mul(Rlo_mn, Rn, inv);
+ cmp(Rlo_mn, -1);
+ Label ok;
+ br(EQ, ok); {
+ stop("broken inverse in Montgomery multiply");
+ } bind(ok);
+ }
+#endif
+
+ mov(Pm_base, Ra);
+
+ mov(t0, zr);
+ mov(t1, zr);
+ mov(t2, zr);
+
+ block_comment("for (int i = 0; i < len; i++) {");
+ mov(Ri, zr); {
+ Label loop, end;
+ cmpw(Ri, Rlen);
+ br(Assembler::GE, end);
+
+ bind(loop);
+ pre1(Ri);
+
+ block_comment(" for (j = i; j; j--) {"); {
+ movw(Rj, Ri);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::step);
+ } block_comment(" } // j");
+
+ post1();
+ addw(Ri, Ri, 1);
+ cmpw(Ri, Rlen);
+ br(Assembler::LT, loop);
+ bind(end);
+ block_comment("} // i");
+ }
+
+ block_comment("for (int i = len; i < 2*len; i++) {");
+ mov(Ri, Rlen); {
+ Label loop, end;
+ cmpw(Ri, Rlen, Assembler::LSL, 1);
+ br(Assembler::GE, end);
+
+ bind(loop);
+ pre2(Ri, Rlen);
+
+ block_comment(" for (j = len*2-i-1; j; j--) {"); {
+ lslw(Rj, Rlen, 1);
+ subw(Rj, Rj, Ri);
+ subw(Rj, Rj, 1);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::step);
+ } block_comment(" } // j");
+
+ post2(Ri, Rlen);
+ addw(Ri, Ri, 1);
+ cmpw(Ri, Rlen, Assembler::LSL, 1);
+ br(Assembler::LT, loop);
+ bind(end);
+ }
+ block_comment("} // i");
+
+ normalize(Rlen);
+
+ mov(Ra, Pm_base); // Save Pm_base in Ra
+ restore_regs(); // Restore caller's Pm_base
+
+ // Copy our result into caller's Pm_base
+ reverse(Pm_base, Ra, Rlen, t0, t1);
+
+ leave();
+ bind(nothing);
+ ret(lr);
+
+ return entry;
+ }
+ // In C, approximately:
+
+ // void
+ // montgomery_multiply(unsigned long Pa_base[], unsigned long Pb_base[],
+ // unsigned long Pn_base[], unsigned long Pm_base[],
+ // unsigned long inv, int len) {
+ // unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+ // unsigned long *Pa, *Pb, *Pn, *Pm;
+ // unsigned long Ra, Rb, Rn, Rm;
+
+ // int i;
+
+ // assert(inv * Pn_base[0] == -1UL, "broken inverse in Montgomery multiply");
+
+ // for (i = 0; i < len; i++) {
+ // int j;
+
+ // Pa = Pa_base;
+ // Pb = Pb_base + i;
+ // Pm = Pm_base;
+ // Pn = Pn_base + i;
+
+ // Ra = *Pa;
+ // Rb = *Pb;
+ // Rm = *Pm;
+ // Rn = *Pn;
+
+ // int iters = i;
+ // for (j = 0; iters--; j++) {
+ // assert(Ra == Pa_base[j] && Rb == Pb_base[i-j], "must be");
+ // MACC(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+
+ // assert(Ra == Pa_base[i] && Rb == Pb_base[0], "must be");
+ // MACC(Ra, Rb, t0, t1, t2);
+ // *Pm = Rm = t0 * inv;
+ // assert(Rm == Pm_base[i] && Rn == Pn_base[0], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+
+ // assert(t0 == 0, "broken Montgomery multiply");
+
+ // t0 = t1; t1 = t2; t2 = 0;
+ // }
+
+ // for (i = len; i < 2*len; i++) {
+ // int j;
+
+ // Pa = Pa_base + i-len;
+ // Pb = Pb_base + len;
+ // Pm = Pm_base + i-len;
+ // Pn = Pn_base + len;
+
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+
+ // int iters = len*2-i-1;
+ // for (j = i-len+1; iters--; j++) {
+ // assert(Ra == Pa_base[j] && Rb == Pb_base[i-j], "must be");
+ // MACC(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+
+ // Pm_base[i-len] = t0;
+ // t0 = t1; t1 = t2; t2 = 0;
+ // }
+
+ // while (t0)
+ // t0 = sub(Pm_base, Pn_base, t0, len);
+ // }
+
+ /**
+ * Fast Montgomery squaring. This uses asymptotically 25% fewer
+ * multiplies than Montgomery multiplication so it should be up to
+ * 25% faster. However, its loop control is more complex and it
+ * may actually run slower on some machines.
+ *
+ * Arguments:
+ *
+ * Inputs:
+ * c_rarg0 - int array elements a
+ * c_rarg1 - int array elements n (the modulus)
+ * c_rarg2 - int length
+ * c_rarg3 - int inv
+ * c_rarg4 - int array elements m (the result)
+ *
+ */
+ address generate_square() {
+ Label argh;
+ bind(argh);
+ stop("MontgomeryMultiply total_allocation must be <= 8192");
+
+ align(CodeEntryAlignment);
+ address entry = pc();
+
+ enter();
+
+ // Make room.
+ cmpw(Rlen, 512);
+ br(Assembler::HI, argh);
+ sub(Ra, sp, Rlen, ext::uxtw, exact_log2(4 * sizeof (jint)));
+ andr(sp, Ra, -2 * wordSize);
+
+ lsrw(Rlen, Rlen, 1); // length in longwords = len/2
+
+ {
+ // Copy input args, reversing as we go. We use Ra as a
+ // temporary variable.
+ reverse(Ra, Pa_base, Rlen, t0, t1);
+ reverse(Ra, Pn_base, Rlen, t0, t1);
+ }
+
+ // Push all call-saved registers and also Pm_base which we'll need
+ // at the end.
+ save_regs();
+
+ mov(Pm_base, Ra);
+
+ mov(t0, zr);
+ mov(t1, zr);
+ mov(t2, zr);
+
+ block_comment("for (int i = 0; i < len; i++) {");
+ mov(Ri, zr); {
+ Label loop, end;
+ bind(loop);
+ cmp(Ri, Rlen);
+ br(Assembler::GE, end);
+
+ pre1(Ri);
+
+ block_comment("for (j = (i+1)/2; j; j--) {"); {
+ add(Rj, Ri, 1);
+ lsr(Rj, Rj, 1);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring);
+ } block_comment(" } // j");
+
+ last_squaring(Ri);
+
+ block_comment(" for (j = i/2; j; j--) {"); {
+ lsr(Rj, Ri, 1);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring);
+ } block_comment(" } // j");
+
+ post1_squaring();
+ add(Ri, Ri, 1);
+ cmp(Ri, Rlen);
+ br(Assembler::LT, loop);
+
+ bind(end);
+ block_comment("} // i");
+ }
+
+ block_comment("for (int i = len; i < 2*len; i++) {");
+ mov(Ri, Rlen); {
+ Label loop, end;
+ bind(loop);
+ cmp(Ri, Rlen, Assembler::LSL, 1);
+ br(Assembler::GE, end);
+
+ pre2(Ri, Rlen);
+
+ block_comment(" for (j = (2*len-i-1)/2; j; j--) {"); {
+ lsl(Rj, Rlen, 1);
+ sub(Rj, Rj, Ri);
+ sub(Rj, Rj, 1);
+ lsr(Rj, Rj, 1);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::step_squaring);
+ } block_comment(" } // j");
+
+ last_squaring(Ri);
+
+ block_comment(" for (j = (2*len-i)/2; j; j--) {"); {
+ lsl(Rj, Rlen, 1);
+ sub(Rj, Rj, Ri);
+ lsr(Rj, Rj, 1);
+ unroll_2(Rj, &MontgomeryMultiplyGenerator::extra_step_squaring);
+ } block_comment(" } // j");
+
+ post2(Ri, Rlen);
+ add(Ri, Ri, 1);
+ cmp(Ri, Rlen, Assembler::LSL, 1);
+
+ br(Assembler::LT, loop);
+ bind(end);
+ block_comment("} // i");
+ }
+
+ normalize(Rlen);
+
+ mov(Ra, Pm_base); // Save Pm_base in Ra
+ restore_regs(); // Restore caller's Pm_base
+
+ // Copy our result into caller's Pm_base
+ reverse(Pm_base, Ra, Rlen, t0, t1);
+
+ leave();
+ ret(lr);
+
+ return entry;
+ }
+ // In C, approximately:
+
+ // void
+ // montgomery_square(unsigned long Pa_base[], unsigned long Pn_base[],
+ // unsigned long Pm_base[], unsigned long inv, int len) {
+ // unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+ // unsigned long *Pa, *Pb, *Pn, *Pm;
+ // unsigned long Ra, Rb, Rn, Rm;
+
+ // int i;
+
+ // assert(inv * Pn_base[0] == -1UL, "broken inverse in Montgomery multiply");
+
+ // for (i = 0; i < len; i++) {
+ // int j;
+
+ // Pa = Pa_base;
+ // Pb = Pa_base + i;
+ // Pm = Pm_base;
+ // Pn = Pn_base + i;
+
+ // Ra = *Pa;
+ // Rb = *Pb;
+ // Rm = *Pm;
+ // Rn = *Pn;
+
+ // int iters = (i+1)/2;
+ // for (j = 0; iters--; j++) {
+ // assert(Ra == Pa_base[j] && Rb == Pa_base[i-j], "must be");
+ // MACC2(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+ // if ((i & 1) == 0) {
+ // assert(Ra == Pa_base[j], "must be");
+ // MACC(Ra, Ra, t0, t1, t2);
+ // }
+ // iters = i/2;
+ // assert(iters == i-j, "must be");
+ // for (; iters--; j++) {
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+
+ // *Pm = Rm = t0 * inv;
+ // assert(Rm == Pm_base[i] && Rn == Pn_base[0], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+
+ // assert(t0 == 0, "broken Montgomery multiply");
+
+ // t0 = t1; t1 = t2; t2 = 0;
+ // }
+
+ // for (i = len; i < 2*len; i++) {
+ // int start = i-len+1;
+ // int end = start + (len - start)/2;
+ // int j;
+
+ // Pa = Pa_base + i-len;
+ // Pb = Pa_base + len;
+ // Pm = Pm_base + i-len;
+ // Pn = Pn_base + len;
+
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+
+ // int iters = (2*len-i-1)/2;
+ // assert(iters == end-start, "must be");
+ // for (j = start; iters--; j++) {
+ // assert(Ra == Pa_base[j] && Rb == Pa_base[i-j], "must be");
+ // MACC2(Ra, Rb, t0, t1, t2);
+ // Ra = *++Pa;
+ // Rb = *--Pb;
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+ // if ((i & 1) == 0) {
+ // assert(Ra == Pa_base[j], "must be");
+ // MACC(Ra, Ra, t0, t1, t2);
+ // }
+ // iters = (2*len-i)/2;
+ // assert(iters == len-j, "must be");
+ // for (; iters--; j++) {
+ // assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
+ // MACC(Rm, Rn, t0, t1, t2);
+ // Rm = *++Pm;
+ // Rn = *--Pn;
+ // }
+ // Pm_base[i-len] = t0;
+ // t0 = t1; t1 = t2; t2 = 0;
+ // }
+
+ // while (t0)
+ // t0 = sub(Pm_base, Pn_base, t0, len);
+ // }
+ };
+
// Initialization
void generate_initial() {
// Generate initial stubs and initializes the entry points
@@ -2603,7 +3554,26 @@
StubRoutines::_multiplyToLen = generate_multiplyToLen();
}
+ if (UseMontgomeryMultiplyIntrinsic) {
+ StubCodeMark mark(this, "StubRoutines", "montgomeryMultiply");
+ MontgomeryMultiplyGenerator g(_masm, /*squaring*/false);
+ StubRoutines::_montgomeryMultiply = g.generate_multiply();
+ }
+
+ if (UseMontgomerySquareIntrinsic) {
+ StubCodeMark mark(this, "StubRoutines", "montgomerySquare");
+ MontgomeryMultiplyGenerator g(_masm, /*squaring*/true);
+ // We use generate_multiply() rather than generate_square()
+ // because it's faster for the sizes of modulus we care about.
+ StubRoutines::_montgomerySquare = g.generate_multiply();
+ }
+
#ifndef BUILTIN_SIM
+ // generate GHASH intrinsics code
+ if (UseGHASHIntrinsics) {
+ StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+ }
+
if (UseAESIntrinsics) {
StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock();
StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock();
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -45,6 +45,10 @@
#define HWCAP_AES (1<<3)
#endif
+#ifndef HWCAP_PMULL
+#define HWCAP_PMULL (1<<4)
+#endif
+
#ifndef HWCAP_SHA1
#define HWCAP_SHA1 (1<<5)
#endif
@@ -190,11 +194,6 @@
}
}
- if (UseGHASHIntrinsics) {
- warning("GHASH intrinsics are not available on this CPU");
- FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
- }
-
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
UseCRC32Intrinsics = true;
}
@@ -232,7 +231,7 @@
}
} else if (UseSHA256Intrinsics) {
warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
- FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+ FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
if (UseSHA512Intrinsics) {
@@ -244,6 +243,15 @@
FLAG_SET_DEFAULT(UseSHA, false);
}
+ if (auxv & HWCAP_PMULL) {
+ if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, true);
+ }
+ } else if (UseGHASHIntrinsics) {
+ warning("GHASH intrinsics are not available on this CPU");
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
+ }
+
// This machine allows unaligned memory accesses
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
FLAG_SET_DEFAULT(UseUnalignedAccesses, true);
@@ -261,6 +269,13 @@
UsePopCountInstruction = true;
}
+ if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
+ UseMontgomeryMultiplyIntrinsic = true;
+ }
+ if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
+ UseMontgomerySquareIntrinsic = true;
+ }
+
#ifdef COMPILER2
if (FLAG_IS_DEFAULT(OptoScheduling)) {
OptoScheduling = true;
--- a/hotspot/src/os/aix/vm/os_aix.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -1550,6 +1550,13 @@
LoadedLibraries::print(st);
}
+void os::get_summary_os_info(char* buf, size_t buflen) {
+ // There might be something more readable than uname results for AIX.
+ struct utsname name;
+ uname(&name);
+ snprintf(buf, buflen, "%s %s", name.release, name.version);
+}
+
void os::print_os_info(outputStream* st) {
st->print("OS:");
@@ -1654,6 +1661,17 @@
}
}
+// Get a string for the cpuinfo that is a summary of the cpu type
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+ // This looks good
+ os::Aix::cpuinfo_t ci;
+ if (os::Aix::get_cpuinfo(&ci)) {
+ strncpy(buf, ci.version, buflen);
+ } else {
+ strncpy(buf, "AIX", buflen);
+ }
+}
+
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
}
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -1600,24 +1600,6 @@
return dlsym(handle, name);
}
-
-static bool _print_ascii_file(const char* filename, outputStream* st) {
- int fd = ::open(filename, O_RDONLY);
- if (fd == -1) {
- return false;
- }
-
- char buf[32];
- int bytes;
- while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
- st->print_raw(buf, bytes);
- }
-
- ::close(fd);
-
- return true;
-}
-
int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
outputStream * out = (outputStream *) param;
out->print_cr(PTR_FORMAT " \t%s", base_address, name);
@@ -1678,15 +1660,38 @@
#endif
}
+void os::get_summary_os_info(char* buf, size_t buflen) {
+ // These buffers are small because we want this to be brief
+ // and not use a lot of stack while generating the hs_err file.
+ char os[100];
+ size_t size = sizeof(os);
+ int mib_kern[] = { CTL_KERN, KERN_OSTYPE };
+ if (sysctl(mib_kern, 2, os, &size, NULL, 0) < 0) {
+#ifdef __APPLE__
+ strncpy(os, "Darwin", sizeof(os));
+#elif __OpenBSD__
+ strncpy(os, "OpenBSD", sizeof(os));
+#else
+ strncpy(os, "BSD", sizeof(os));
+#endif
+ }
+
+ char release[100];
+ size = sizeof(release);
+ int mib_release[] = { CTL_KERN, KERN_OSRELEASE };
+ if (sysctl(mib_release, 2, release, &size, NULL, 0) < 0) {
+ // if error, leave blank
+ strncpy(release, "", sizeof(release));
+ }
+ snprintf(buf, buflen, "%s %s", os, release);
+}
+
void os::print_os_info_brief(outputStream* st) {
- st->print("Bsd");
-
os::Posix::print_uname_info(st);
}
void os::print_os_info(outputStream* st) {
st->print("OS:");
- st->print("Bsd");
os::Posix::print_uname_info(st);
@@ -1699,6 +1704,33 @@
// Nothing to do for now.
}
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+ unsigned int mhz;
+ size_t size = sizeof(mhz);
+ int mib[] = { CTL_HW, HW_CPU_FREQ };
+ if (sysctl(mib, 2, &mhz, &size, NULL, 0) < 0) {
+ mhz = 1; // looks like an error but can be divided by
+ } else {
+ mhz /= 1000000; // reported in millions
+ }
+
+ char model[100];
+ size = sizeof(model);
+ int mib_model[] = { CTL_HW, HW_MODEL };
+ if (sysctl(mib_model, 2, model, &size, NULL, 0) < 0) {
+ strncpy(model, cpu_arch, sizeof(model));
+ }
+
+ char machine[100];
+ size = sizeof(machine);
+ int mib_machine[] = { CTL_HW, HW_MACHINE };
+ if (sysctl(mib_machine, 2, machine, &size, NULL, 0) < 0) {
+ strncpy(machine, "", sizeof(machine));
+ }
+
+ snprintf(buf, buflen, "%s %s %d MHz", model, machine, mhz);
+}
+
void os::print_memory_info(outputStream* st) {
st->print("Memory:");
@@ -1709,11 +1741,6 @@
st->print("(" UINT64_FORMAT "k free)",
os::available_memory() >> 10);
st->cr();
-
- // meminfo
- st->print("\n/proc/meminfo:\n");
- _print_ascii_file("/proc/meminfo", st);
- st->cr();
}
void os::print_siginfo(outputStream* st, void* siginfo) {
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -2043,31 +2043,96 @@
// Searching for the debian_version file is the last resort. It contains
// an informative string like "6.0.6" or "wheezy/sid". Because of this
// "Debian " is printed before the contents of the debian_version file.
+
+const char* distro_files[] = {
+ "/etc/oracle-release",
+ "/etc/mandriva-release",
+ "/etc/mandrake-release",
+ "/etc/sun-release",
+ "/etc/redhat-release",
+ "/etc/lsb-release",
+ "/etc/SuSE-release",
+ "/etc/turbolinux-release",
+ "/etc/gentoo-release",
+ "/etc/ltib-release",
+ "/etc/angstrom-version",
+ "/etc/system-release",
+ "/etc/os-release",
+ NULL };
+
void os::Linux::print_distro_info(outputStream* st) {
- if (!_print_ascii_file("/etc/oracle-release", st) &&
- !_print_ascii_file("/etc/mandriva-release", st) &&
- !_print_ascii_file("/etc/mandrake-release", st) &&
- !_print_ascii_file("/etc/sun-release", st) &&
- !_print_ascii_file("/etc/redhat-release", st) &&
- !_print_ascii_file("/etc/lsb-release", st) &&
- !_print_ascii_file("/etc/SuSE-release", st) &&
- !_print_ascii_file("/etc/turbolinux-release", st) &&
- !_print_ascii_file("/etc/gentoo-release", st) &&
- !_print_ascii_file("/etc/ltib-release", st) &&
- !_print_ascii_file("/etc/angstrom-version", st) &&
- !_print_ascii_file("/etc/system-release", st) &&
- !_print_ascii_file("/etc/os-release", st)) {
-
- if (file_exists("/etc/debian_version")) {
- st->print("Debian ");
- _print_ascii_file("/etc/debian_version", st);
- } else {
- st->print("Linux");
+ for (int i = 0;; i++) {
+ const char* file = distro_files[i];
+ if (file == NULL) {
+ break; // done
}
+ // If file prints, we found it.
+ if (_print_ascii_file(file, st)) {
+ return;
+ }
+ }
+
+ if (file_exists("/etc/debian_version")) {
+ st->print("Debian ");
+ _print_ascii_file("/etc/debian_version", st);
+ } else {
+ st->print("Linux");
}
st->cr();
}
+static void parse_os_info(char* distro, size_t length, const char* file) {
+ FILE* fp = fopen(file, "r");
+ if (fp != NULL) {
+ char buf[256];
+ // get last line of the file.
+ while (fgets(buf, sizeof(buf), fp)) { }
+ // Edit out extra stuff in expected ubuntu format
+ if (strstr(buf, "DISTRIB_DESCRIPTION=") != NULL) {
+ char* ptr = strstr(buf, "\""); // the name is in quotes
+ if (ptr != NULL) {
+ ptr++; // go beyond first quote
+ char* nl = strchr(ptr, '\"');
+ if (nl != NULL) *nl = '\0';
+ strncpy(distro, ptr, length);
+ } else {
+ ptr = strstr(buf, "=");
+ ptr++; // go beyond equals then
+ char* nl = strchr(ptr, '\n');
+ if (nl != NULL) *nl = '\0';
+ strncpy(distro, ptr, length);
+ }
+ } else {
+ // if not in expected Ubuntu format, print out whole line minus \n
+ char* nl = strchr(buf, '\n');
+ if (nl != NULL) *nl = '\0';
+ strncpy(distro, buf, length);
+ }
+ // close distro file
+ fclose(fp);
+ }
+}
+
+void os::get_summary_os_info(char* buf, size_t buflen) {
+ for (int i = 0;; i++) {
+ const char* file = distro_files[i];
+ if (file == NULL) {
+ break; // ran out of distro_files
+ }
+ if (file_exists(file)) {
+ parse_os_info(buf, buflen, file);
+ return;
+ }
+ }
+ // special case for debian
+ if (file_exists("/etc/debian_version")) {
+ strncpy(buf, "Debian ", buflen);
+ parse_os_info(&buf[7], buflen-7, "/etc/debian_version");
+ } else {
+ strncpy(buf, "Linux", buflen);
+ }
+}
+
void os::Linux::print_libversion_info(outputStream* st) {
// libc, pthread
st->print("libc:");
@@ -2150,6 +2215,48 @@
}
}
+const char* search_string = IA32_ONLY("model name") AMD64_ONLY("model name")
+ IA64_ONLY("") SPARC_ONLY("cpu")
+ ARM32_ONLY("Processor") PPC_ONLY("Processor") AARCH64_ONLY("Processor");
+
+// Parses the cpuinfo file for string representing the model name.
+void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
+ FILE* fp = fopen("/proc/cpuinfo", "r");
+ if (fp != NULL) {
+ while (!feof(fp)) {
+ char buf[256];
+ if (fgets(buf, sizeof(buf), fp)) {
+ char* start = strstr(buf, search_string);
+ if (start != NULL) {
+ char *ptr = start + strlen(search_string);
+ char *end = buf + strlen(buf);
+ while (ptr != end) {
+ // skip whitespace and colon for the rest of the name.
+ if (*ptr != ' ' && *ptr != '\t' && *ptr != ':') {
+ break;
+ }
+ ptr++;
+ }
+ if (ptr != end) {
+ // reasonable string, get rid of newline and keep the rest
+ char* nl = strchr(buf, '\n');
+ if (nl != NULL) *nl = '\0';
+ strncpy(cpuinfo, ptr, length);
+ fclose(fp);
+ return;
+ }
+ }
+ }
+ }
+ fclose(fp);
+ }
+ // cpuinfo not found or parsing failed, just print generic string. The entire
+ // /proc/cpuinfo file will be printed later in the file (or enough of it for x86)
+ strncpy(cpuinfo, IA32_ONLY("x86_32") AMD64_ONLY("x86_32")
+ IA64_ONLY("IA64") SPARC_ONLY("sparcv9")
+ ARM32_ONLY("ARM") PPC_ONLY("PPC64") AARCH64_ONLY("AArch64"), length);
+}
+
void os::print_siginfo(outputStream* st, void* siginfo) {
const siginfo_t* si = (const siginfo_t*)siginfo;
--- a/hotspot/src/os/posix/vm/os_posix.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -236,6 +236,15 @@
st->cr();
}
+#ifndef PRODUCT
+bool os::get_host_name(char* buf, size_t buflen) {
+ struct utsname name;
+ uname(&name);
+ jio_snprintf(buf, buflen, "%s", name.nodename);
+ return true;
+}
+#endif // PRODUCT
+
bool os::has_allocatable_memory_limit(julong* limit) {
struct rlimit rlim;
int getrlimit_res = getrlimit(RLIMIT_AS, &rlim);
@@ -1070,7 +1079,7 @@
return ret == 0;
}
-bool PosixSemaphore::timedwait(const struct timespec ts) {
+bool PosixSemaphore::timedwait(struct timespec ts) {
while (true) {
int result = sem_timedwait(&_semaphore, &ts);
if (result == 0) {
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -1971,6 +1971,26 @@
st->cr();
}
+void os::get_summary_os_info(char* buf, size_t buflen) {
+ strncpy(buf, "Solaris", buflen); // default to plain solaris
+ FILE* fp = fopen("/etc/release", "r");
+ if (fp != NULL) {
+ char tmp[256];
+ // Only get the first line and chop out everything but the os name.
+ if (fgets(tmp, sizeof(tmp), fp)) {
+ char* ptr = tmp;
+ // skip past whitespace characters
+ while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')) ptr++;
+ if (*ptr != '\0') {
+ char* nl = strchr(ptr, '\n');
+ if (nl != NULL) *nl = '\0';
+ strncpy(buf, ptr, buflen);
+ }
+ }
+ fclose(fp);
+ }
+}
+
void os::Solaris::print_libversion_info(outputStream* st) {
st->print(" (T2 libthread)");
st->cr();
@@ -1998,6 +2018,22 @@
return status;
}
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+ // Get MHz with system call. We don't seem to already have this.
+ processor_info_t stats;
+ processorid_t id = getcpuid();
+ int clock = 0;
+ if (processor_info(id, &stats) != -1) {
+ clock = stats.pi_clock; // pi_processor_type isn't more informative than below
+ }
+#ifdef AMD64
+ snprintf(buf, buflen, "x86 64 bit %d MHz", clock);
+#else
+ // must be sparc
+ snprintf(buf, buflen, "Sparcv9 64 bit %d MHz", clock);
+#endif
+}
+
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
// Nothing to do for now.
}
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -1593,6 +1593,21 @@
return result;
}
+#ifndef PRODUCT
+bool os::get_host_name(char* buf, size_t buflen) {
+ DWORD size = (DWORD)buflen;
+ return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE);
+}
+#endif // PRODUCT
+
+void os::get_summary_os_info(char* buf, size_t buflen) {
+ stringStream sst(buf, buflen);
+ os::win32::print_windows_version(&sst);
+ // chop off newline character
+ char* nl = strchr(buf, '\n');
+ if (nl != NULL) *nl = '\0';
+}
+
void os::print_os_info_brief(outputStream* st) {
os::print_os_info(st);
}
@@ -1600,15 +1615,14 @@
void os::print_os_info(outputStream* st) {
#ifdef ASSERT
char buffer[1024];
- DWORD size = sizeof(buffer);
- st->print(" HostName: ");
- if (GetComputerNameEx(ComputerNameDnsHostname, buffer, &size)) {
- st->print("%s", buffer);
+ st->print("HostName: ");
+ if (get_host_name(buffer, sizeof(buffer))) {
+ st->print("%s ", buffer);
} else {
- st->print("N/A");
+ st->print("N/A ");
}
#endif
- st->print(" OS:");
+ st->print("OS:");
os::win32::print_windows_version(st);
}
@@ -1738,6 +1752,23 @@
// Nothing to do for now.
}
+void os::get_summary_cpu_info(char* buf, size_t buflen) {
+ HKEY key;
+ DWORD status = RegOpenKey(HKEY_LOCAL_MACHINE,
+ "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
+ if (status == ERROR_SUCCESS) {
+ DWORD size = (DWORD)buflen;
+ status = RegQueryValueEx(key, "ProcessorNameString", NULL, NULL, (byte*)buf, &size);
+ if (status != ERROR_SUCCESS) {
+ strncpy(buf, "## __CPU__", buflen);
+ }
+ RegCloseKey(key);
+ } else {
+ // Put generic cpu info to return
+ strncpy(buf, "## __CPU__", buflen);
+ }
+}
+
void os::print_memory_info(outputStream* st) {
st->print("Memory:");
st->print(" %dk page", os::vm_page_size()>>10);
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -99,6 +99,164 @@
return buffer_blob;
}
+bool Compiler::is_intrinsic_supported(methodHandle method) {
+ vmIntrinsics::ID id = method->intrinsic_id();
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ if (method->is_synchronized()) {
+ // C1 does not support intrinsification of synchronized methods.
+ return false;
+ }
+
+ switch (id) {
+ case vmIntrinsics::_compareAndSwapLong:
+ if (!VM_Version::supports_cx8()) return false;
+ break;
+ case vmIntrinsics::_getAndAddInt:
+ if (!VM_Version::supports_atomic_getadd4()) return false;
+ break;
+ case vmIntrinsics::_getAndAddLong:
+ if (!VM_Version::supports_atomic_getadd8()) return false;
+ break;
+ case vmIntrinsics::_getAndSetInt:
+ if (!VM_Version::supports_atomic_getset4()) return false;
+ break;
+ case vmIntrinsics::_getAndSetLong:
+ if (!VM_Version::supports_atomic_getset8()) return false;
+ break;
+ case vmIntrinsics::_getAndSetObject:
+#ifdef _LP64
+ if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) return false;
+ if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) return false;
+#else
+ if (!VM_Version::supports_atomic_getset4()) return false;
+#endif
+ break;
+ case vmIntrinsics::_arraycopy:
+ case vmIntrinsics::_currentTimeMillis:
+ case vmIntrinsics::_nanoTime:
+ case vmIntrinsics::_Reference_get:
+ // Use the intrinsic version of Reference.get() so that the value in
+ // the referent field can be registered by the G1 pre-barrier code.
+ // Also to prevent commoning reads from this field across safepoint
+ // since GC can change its value.
+ case vmIntrinsics::_loadFence:
+ case vmIntrinsics::_storeFence:
+ case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_floatToRawIntBits:
+ case vmIntrinsics::_intBitsToFloat:
+ case vmIntrinsics::_doubleToRawLongBits:
+ case vmIntrinsics::_longBitsToDouble:
+ case vmIntrinsics::_getClass:
+ case vmIntrinsics::_isInstance:
+ case vmIntrinsics::_currentThread:
+ case vmIntrinsics::_dabs:
+ case vmIntrinsics::_dsqrt:
+ case vmIntrinsics::_dsin:
+ case vmIntrinsics::_dcos:
+ case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dlog:
+ case vmIntrinsics::_dlog10:
+ case vmIntrinsics::_dexp:
+ case vmIntrinsics::_dpow:
+ case vmIntrinsics::_getObject:
+ case vmIntrinsics::_getBoolean:
+ case vmIntrinsics::_getByte:
+ case vmIntrinsics::_getShort:
+ case vmIntrinsics::_getChar:
+ case vmIntrinsics::_getInt:
+ case vmIntrinsics::_getLong:
+ case vmIntrinsics::_getFloat:
+ case vmIntrinsics::_getDouble:
+ case vmIntrinsics::_putObject:
+ case vmIntrinsics::_putBoolean:
+ case vmIntrinsics::_putByte:
+ case vmIntrinsics::_putShort:
+ case vmIntrinsics::_putChar:
+ case vmIntrinsics::_putInt:
+ case vmIntrinsics::_putLong:
+ case vmIntrinsics::_putFloat:
+ case vmIntrinsics::_putDouble:
+ case vmIntrinsics::_getObjectVolatile:
+ case vmIntrinsics::_getBooleanVolatile:
+ case vmIntrinsics::_getByteVolatile:
+ case vmIntrinsics::_getShortVolatile:
+ case vmIntrinsics::_getCharVolatile:
+ case vmIntrinsics::_getIntVolatile:
+ case vmIntrinsics::_getLongVolatile:
+ case vmIntrinsics::_getFloatVolatile:
+ case vmIntrinsics::_getDoubleVolatile:
+ case vmIntrinsics::_putObjectVolatile:
+ case vmIntrinsics::_putBooleanVolatile:
+ case vmIntrinsics::_putByteVolatile:
+ case vmIntrinsics::_putShortVolatile:
+ case vmIntrinsics::_putCharVolatile:
+ case vmIntrinsics::_putIntVolatile:
+ case vmIntrinsics::_putLongVolatile:
+ case vmIntrinsics::_putFloatVolatile:
+ case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getByte_raw:
+ case vmIntrinsics::_getShort_raw:
+ case vmIntrinsics::_getChar_raw:
+ case vmIntrinsics::_getInt_raw:
+ case vmIntrinsics::_getLong_raw:
+ case vmIntrinsics::_getFloat_raw:
+ case vmIntrinsics::_getDouble_raw:
+ case vmIntrinsics::_putByte_raw:
+ case vmIntrinsics::_putShort_raw:
+ case vmIntrinsics::_putChar_raw:
+ case vmIntrinsics::_putInt_raw:
+ case vmIntrinsics::_putLong_raw:
+ case vmIntrinsics::_putFloat_raw:
+ case vmIntrinsics::_putDouble_raw:
+ case vmIntrinsics::_putOrderedObject:
+ case vmIntrinsics::_putOrderedInt:
+ case vmIntrinsics::_putOrderedLong:
+ case vmIntrinsics::_getShortUnaligned:
+ case vmIntrinsics::_getCharUnaligned:
+ case vmIntrinsics::_getIntUnaligned:
+ case vmIntrinsics::_getLongUnaligned:
+ case vmIntrinsics::_putShortUnaligned:
+ case vmIntrinsics::_putCharUnaligned:
+ case vmIntrinsics::_putIntUnaligned:
+ case vmIntrinsics::_putLongUnaligned:
+ case vmIntrinsics::_checkIndex:
+ case vmIntrinsics::_updateCRC32:
+ case vmIntrinsics::_updateBytesCRC32:
+ case vmIntrinsics::_updateByteBufferCRC32:
+ case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_compareAndSwapObject:
+#ifdef TRACE_HAVE_INTRINSICS
+ case vmIntrinsics::_classID:
+ case vmIntrinsics::_threadID:
+ case vmIntrinsics::_counterTime:
+#endif
+ break;
+ default:
+ return false; // Intrinsics not on the previous list are not available.
+ }
+
+ return true;
+}
+
+bool Compiler::is_intrinsic_disabled_by_flag(methodHandle method) {
+ vmIntrinsics::ID id = method->intrinsic_id();
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ if (vmIntrinsics::is_disabled_by_flags(id)) {
+ return true;
+ }
+
+ if (!InlineNatives && id != vmIntrinsics::_Reference_get) {
+ return true;
+ }
+
+ if (!InlineClassNatives && id == vmIntrinsics::_getClass) {
+ return true;
+ }
+
+ return false;
+}
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
@@ -117,3 +275,7 @@
void Compiler::print_timers() {
Compilation::print_timers();
}
+
+bool Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+ return is_intrinsic_supported(method) && !is_intrinsic_disabled_by_flag(method);
+}
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -55,6 +55,18 @@
// Print compilation timers and statistics
virtual void print_timers();
+ // Check the availability of an intrinsic for 'method' given a compilation context.
+ // The compilation context is needed to support per-method usage of the
+ // DisableIntrinsic flag. However, as C1 ignores the DisableIntrinsic flag, it
+ // ignores the compilation context.
+ virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
+
+ // Check if the C1 compiler supports an intrinsic for 'method'.
+ virtual bool is_intrinsic_supported(methodHandle method);
+
+ // Processing of command-line flags specific to the C1 compiler.
+ virtual bool is_intrinsic_disabled_by_flag(methodHandle method);
+
// Size of the code buffer
static int code_buffer_size();
};
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -3372,231 +3372,85 @@
return NULL;
}
-
-bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
- if (callee->is_synchronized()) {
- // We don't currently support any synchronized intrinsics
- return false;
- }
-
- // callee seems like a good candidate
- // determine id
+void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) {
vmIntrinsics::ID id = callee->intrinsic_id();
- if (!InlineNatives && id != vmIntrinsics::_Reference_get) {
- // InlineNatives does not control Reference.get
- INLINE_BAILOUT("intrinsic method inlining disabled");
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ // Some intrinsics need special IR nodes.
+ switch(id) {
+ case vmIntrinsics::_getObject : append_unsafe_get_obj(callee, T_OBJECT, false); return;
+ case vmIntrinsics::_getBoolean : append_unsafe_get_obj(callee, T_BOOLEAN, false); return;
+ case vmIntrinsics::_getByte : append_unsafe_get_obj(callee, T_BYTE, false); return;
+ case vmIntrinsics::_getShort : append_unsafe_get_obj(callee, T_SHORT, false); return;
+ case vmIntrinsics::_getChar : append_unsafe_get_obj(callee, T_CHAR, false); return;
+ case vmIntrinsics::_getInt : append_unsafe_get_obj(callee, T_INT, false); return;
+ case vmIntrinsics::_getLong : append_unsafe_get_obj(callee, T_LONG, false); return;
+ case vmIntrinsics::_getFloat : append_unsafe_get_obj(callee, T_FLOAT, false); return;
+ case vmIntrinsics::_getDouble : append_unsafe_get_obj(callee, T_DOUBLE, false); return;
+ case vmIntrinsics::_putObject : append_unsafe_put_obj(callee, T_OBJECT, false); return;
+ case vmIntrinsics::_putBoolean : append_unsafe_put_obj(callee, T_BOOLEAN, false); return;
+ case vmIntrinsics::_putByte : append_unsafe_put_obj(callee, T_BYTE, false); return;
+ case vmIntrinsics::_putShort : append_unsafe_put_obj(callee, T_SHORT, false); return;
+ case vmIntrinsics::_putChar : append_unsafe_put_obj(callee, T_CHAR, false); return;
+ case vmIntrinsics::_putInt : append_unsafe_put_obj(callee, T_INT, false); return;
+ case vmIntrinsics::_putLong : append_unsafe_put_obj(callee, T_LONG, false); return;
+ case vmIntrinsics::_putFloat : append_unsafe_put_obj(callee, T_FLOAT, false); return;
+ case vmIntrinsics::_putDouble : append_unsafe_put_obj(callee, T_DOUBLE, false); return;
+ case vmIntrinsics::_getShortUnaligned : append_unsafe_get_obj(callee, T_SHORT, false); return;
+ case vmIntrinsics::_getCharUnaligned : append_unsafe_get_obj(callee, T_CHAR, false); return;
+ case vmIntrinsics::_getIntUnaligned : append_unsafe_get_obj(callee, T_INT, false); return;
+ case vmIntrinsics::_getLongUnaligned : append_unsafe_get_obj(callee, T_LONG, false); return;
+ case vmIntrinsics::_putShortUnaligned : append_unsafe_put_obj(callee, T_SHORT, false); return;
+ case vmIntrinsics::_putCharUnaligned : append_unsafe_put_obj(callee, T_CHAR, false); return;
+ case vmIntrinsics::_putIntUnaligned : append_unsafe_put_obj(callee, T_INT, false); return;
+ case vmIntrinsics::_putLongUnaligned : append_unsafe_put_obj(callee, T_LONG, false); return;
+ case vmIntrinsics::_getObjectVolatile : append_unsafe_get_obj(callee, T_OBJECT, true); return;
+ case vmIntrinsics::_getBooleanVolatile : append_unsafe_get_obj(callee, T_BOOLEAN, true); return;
+ case vmIntrinsics::_getByteVolatile : append_unsafe_get_obj(callee, T_BYTE, true); return;
+ case vmIntrinsics::_getShortVolatile : append_unsafe_get_obj(callee, T_SHORT, true); return;
+ case vmIntrinsics::_getCharVolatile : append_unsafe_get_obj(callee, T_CHAR, true); return;
+ case vmIntrinsics::_getIntVolatile : append_unsafe_get_obj(callee, T_INT, true); return;
+ case vmIntrinsics::_getLongVolatile : append_unsafe_get_obj(callee, T_LONG, true); return;
+ case vmIntrinsics::_getFloatVolatile : append_unsafe_get_obj(callee, T_FLOAT, true); return;
+ case vmIntrinsics::_getDoubleVolatile : append_unsafe_get_obj(callee, T_DOUBLE, true); return;
+ case vmIntrinsics::_putObjectVolatile : append_unsafe_put_obj(callee, T_OBJECT, true); return;
+ case vmIntrinsics::_putBooleanVolatile : append_unsafe_put_obj(callee, T_BOOLEAN, true); return;
+ case vmIntrinsics::_putByteVolatile : append_unsafe_put_obj(callee, T_BYTE, true); return;
+ case vmIntrinsics::_putShortVolatile : append_unsafe_put_obj(callee, T_SHORT, true); return;
+ case vmIntrinsics::_putCharVolatile : append_unsafe_put_obj(callee, T_CHAR, true); return;
+ case vmIntrinsics::_putIntVolatile : append_unsafe_put_obj(callee, T_INT, true); return;
+ case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return;
+ case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return;
+ case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return;
+ case vmIntrinsics::_getByte_raw : append_unsafe_get_raw(callee, T_BYTE ); return;
+ case vmIntrinsics::_getShort_raw : append_unsafe_get_raw(callee, T_SHORT ); return;
+ case vmIntrinsics::_getChar_raw : append_unsafe_get_raw(callee, T_CHAR ); return;
+ case vmIntrinsics::_getInt_raw : append_unsafe_get_raw(callee, T_INT ); return;
+ case vmIntrinsics::_getLong_raw : append_unsafe_get_raw(callee, T_LONG ); return;
+ case vmIntrinsics::_getFloat_raw : append_unsafe_get_raw(callee, T_FLOAT ); return;
+ case vmIntrinsics::_getDouble_raw : append_unsafe_get_raw(callee, T_DOUBLE); return;
+ case vmIntrinsics::_putByte_raw : append_unsafe_put_raw(callee, T_BYTE ); return;
+ case vmIntrinsics::_putShort_raw : append_unsafe_put_raw(callee, T_SHORT ); return;
+ case vmIntrinsics::_putChar_raw : append_unsafe_put_raw(callee, T_CHAR ); return;
+ case vmIntrinsics::_putInt_raw : append_unsafe_put_raw(callee, T_INT ); return;
+ case vmIntrinsics::_putLong_raw : append_unsafe_put_raw(callee, T_LONG ); return;
+ case vmIntrinsics::_putFloat_raw : append_unsafe_put_raw(callee, T_FLOAT ); return;
+ case vmIntrinsics::_putDouble_raw : append_unsafe_put_raw(callee, T_DOUBLE); return;
+ case vmIntrinsics::_putOrderedObject : append_unsafe_put_obj(callee, T_OBJECT, true); return;
+ case vmIntrinsics::_putOrderedInt : append_unsafe_put_obj(callee, T_INT, true); return;
+ case vmIntrinsics::_putOrderedLong : append_unsafe_put_obj(callee, T_LONG, true); return;
+ case vmIntrinsics::_compareAndSwapLong:
+ case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return;
+ case vmIntrinsics::_getAndAddInt:
+ case vmIntrinsics::_getAndAddLong : append_unsafe_get_and_set_obj(callee, true); return;
+ case vmIntrinsics::_getAndSetInt :
+ case vmIntrinsics::_getAndSetLong :
+ case vmIntrinsics::_getAndSetObject : append_unsafe_get_and_set_obj(callee, false); return;
+ default:
+ break;
}
- bool preserves_state = false;
- bool cantrap = true;
- switch (id) {
- case vmIntrinsics::_arraycopy:
- if (!InlineArrayCopy) return false;
- break;
-
-#ifdef TRACE_HAVE_INTRINSICS
- case vmIntrinsics::_classID:
- case vmIntrinsics::_threadID:
- preserves_state = true;
- cantrap = true;
- break;
-
- case vmIntrinsics::_counterTime:
- preserves_state = true;
- cantrap = false;
- break;
-#endif
-
- case vmIntrinsics::_currentTimeMillis:
- case vmIntrinsics::_nanoTime:
- preserves_state = true;
- cantrap = false;
- break;
-
- case vmIntrinsics::_floatToRawIntBits :
- case vmIntrinsics::_intBitsToFloat :
- case vmIntrinsics::_doubleToRawLongBits :
- case vmIntrinsics::_longBitsToDouble :
- if (!InlineMathNatives) return false;
- preserves_state = true;
- cantrap = false;
- break;
-
- case vmIntrinsics::_getClass :
- case vmIntrinsics::_isInstance :
- if (!InlineClassNatives) return false;
- preserves_state = true;
- break;
-
- case vmIntrinsics::_currentThread :
- if (!InlineThreadNatives) return false;
- preserves_state = true;
- cantrap = false;
- break;
-
- case vmIntrinsics::_dabs : // fall through
- case vmIntrinsics::_dsqrt : // fall through
- case vmIntrinsics::_dsin : // fall through
- case vmIntrinsics::_dcos : // fall through
- case vmIntrinsics::_dtan : // fall through
- case vmIntrinsics::_dlog : // fall through
- case vmIntrinsics::_dlog10 : // fall through
- case vmIntrinsics::_dexp : // fall through
- case vmIntrinsics::_dpow : // fall through
- if (!InlineMathNatives) return false;
- cantrap = false;
- preserves_state = true;
- break;
-
- // Use special nodes for Unsafe instructions so we can more easily
- // perform an address-mode optimization on the raw variants
- case vmIntrinsics::_getObject : return append_unsafe_get_obj(callee, T_OBJECT, false);
- case vmIntrinsics::_getBoolean: return append_unsafe_get_obj(callee, T_BOOLEAN, false);
- case vmIntrinsics::_getByte : return append_unsafe_get_obj(callee, T_BYTE, false);
- case vmIntrinsics::_getShort : return append_unsafe_get_obj(callee, T_SHORT, false);
- case vmIntrinsics::_getChar : return append_unsafe_get_obj(callee, T_CHAR, false);
- case vmIntrinsics::_getInt : return append_unsafe_get_obj(callee, T_INT, false);
- case vmIntrinsics::_getLong : return append_unsafe_get_obj(callee, T_LONG, false);
- case vmIntrinsics::_getFloat : return append_unsafe_get_obj(callee, T_FLOAT, false);
- case vmIntrinsics::_getDouble : return append_unsafe_get_obj(callee, T_DOUBLE, false);
-
- case vmIntrinsics::_putObject : return append_unsafe_put_obj(callee, T_OBJECT, false);
- case vmIntrinsics::_putBoolean: return append_unsafe_put_obj(callee, T_BOOLEAN, false);
- case vmIntrinsics::_putByte : return append_unsafe_put_obj(callee, T_BYTE, false);
- case vmIntrinsics::_putShort : return append_unsafe_put_obj(callee, T_SHORT, false);
- case vmIntrinsics::_putChar : return append_unsafe_put_obj(callee, T_CHAR, false);
- case vmIntrinsics::_putInt : return append_unsafe_put_obj(callee, T_INT, false);
- case vmIntrinsics::_putLong : return append_unsafe_put_obj(callee, T_LONG, false);
- case vmIntrinsics::_putFloat : return append_unsafe_put_obj(callee, T_FLOAT, false);
- case vmIntrinsics::_putDouble : return append_unsafe_put_obj(callee, T_DOUBLE, false);
-
- case vmIntrinsics::_getShortUnaligned :
- return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_SHORT, false) : false;
- case vmIntrinsics::_getCharUnaligned :
- return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_CHAR, false) : false;
- case vmIntrinsics::_getIntUnaligned :
- return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_INT, false) : false;
- case vmIntrinsics::_getLongUnaligned :
- return UseUnalignedAccesses ? append_unsafe_get_obj(callee, T_LONG, false) : false;
-
- case vmIntrinsics::_putShortUnaligned :
- return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_SHORT, false) : false;
- case vmIntrinsics::_putCharUnaligned :
- return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_CHAR, false) : false;
- case vmIntrinsics::_putIntUnaligned :
- return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_INT, false) : false;
- case vmIntrinsics::_putLongUnaligned :
- return UseUnalignedAccesses ? append_unsafe_put_obj(callee, T_LONG, false) : false;
-
- case vmIntrinsics::_getObjectVolatile : return append_unsafe_get_obj(callee, T_OBJECT, true);
- case vmIntrinsics::_getBooleanVolatile: return append_unsafe_get_obj(callee, T_BOOLEAN, true);
- case vmIntrinsics::_getByteVolatile : return append_unsafe_get_obj(callee, T_BYTE, true);
- case vmIntrinsics::_getShortVolatile : return append_unsafe_get_obj(callee, T_SHORT, true);
- case vmIntrinsics::_getCharVolatile : return append_unsafe_get_obj(callee, T_CHAR, true);
- case vmIntrinsics::_getIntVolatile : return append_unsafe_get_obj(callee, T_INT, true);
- case vmIntrinsics::_getLongVolatile : return append_unsafe_get_obj(callee, T_LONG, true);
- case vmIntrinsics::_getFloatVolatile : return append_unsafe_get_obj(callee, T_FLOAT, true);
- case vmIntrinsics::_getDoubleVolatile : return append_unsafe_get_obj(callee, T_DOUBLE, true);
-
- case vmIntrinsics::_putObjectVolatile : return append_unsafe_put_obj(callee, T_OBJECT, true);
- case vmIntrinsics::_putBooleanVolatile: return append_unsafe_put_obj(callee, T_BOOLEAN, true);
- case vmIntrinsics::_putByteVolatile : return append_unsafe_put_obj(callee, T_BYTE, true);
- case vmIntrinsics::_putShortVolatile : return append_unsafe_put_obj(callee, T_SHORT, true);
- case vmIntrinsics::_putCharVolatile : return append_unsafe_put_obj(callee, T_CHAR, true);
- case vmIntrinsics::_putIntVolatile : return append_unsafe_put_obj(callee, T_INT, true);
- case vmIntrinsics::_putLongVolatile : return append_unsafe_put_obj(callee, T_LONG, true);
- case vmIntrinsics::_putFloatVolatile : return append_unsafe_put_obj(callee, T_FLOAT, true);
- case vmIntrinsics::_putDoubleVolatile : return append_unsafe_put_obj(callee, T_DOUBLE, true);
-
- case vmIntrinsics::_getByte_raw : return append_unsafe_get_raw(callee, T_BYTE);
- case vmIntrinsics::_getShort_raw : return append_unsafe_get_raw(callee, T_SHORT);
- case vmIntrinsics::_getChar_raw : return append_unsafe_get_raw(callee, T_CHAR);
- case vmIntrinsics::_getInt_raw : return append_unsafe_get_raw(callee, T_INT);
- case vmIntrinsics::_getLong_raw : return append_unsafe_get_raw(callee, T_LONG);
- case vmIntrinsics::_getFloat_raw : return append_unsafe_get_raw(callee, T_FLOAT);
- case vmIntrinsics::_getDouble_raw : return append_unsafe_get_raw(callee, T_DOUBLE);
-
- case vmIntrinsics::_putByte_raw : return append_unsafe_put_raw(callee, T_BYTE);
- case vmIntrinsics::_putShort_raw : return append_unsafe_put_raw(callee, T_SHORT);
- case vmIntrinsics::_putChar_raw : return append_unsafe_put_raw(callee, T_CHAR);
- case vmIntrinsics::_putInt_raw : return append_unsafe_put_raw(callee, T_INT);
- case vmIntrinsics::_putLong_raw : return append_unsafe_put_raw(callee, T_LONG);
- case vmIntrinsics::_putFloat_raw : return append_unsafe_put_raw(callee, T_FLOAT);
- case vmIntrinsics::_putDouble_raw : return append_unsafe_put_raw(callee, T_DOUBLE);
-
- case vmIntrinsics::_checkIndex :
- if (!InlineNIOCheckIndex) return false;
- preserves_state = true;
- break;
- case vmIntrinsics::_putOrderedObject : return append_unsafe_put_obj(callee, T_OBJECT, true);
- case vmIntrinsics::_putOrderedInt : return append_unsafe_put_obj(callee, T_INT, true);
- case vmIntrinsics::_putOrderedLong : return append_unsafe_put_obj(callee, T_LONG, true);
-
- case vmIntrinsics::_compareAndSwapLong:
- if (!VM_Version::supports_cx8()) return false;
- // fall through
- case vmIntrinsics::_compareAndSwapInt:
- case vmIntrinsics::_compareAndSwapObject:
- append_unsafe_CAS(callee);
- return true;
-
- case vmIntrinsics::_getAndAddInt:
- if (!VM_Version::supports_atomic_getadd4()) {
- return false;
- }
- return append_unsafe_get_and_set_obj(callee, true);
- case vmIntrinsics::_getAndAddLong:
- if (!VM_Version::supports_atomic_getadd8()) {
- return false;
- }
- return append_unsafe_get_and_set_obj(callee, true);
- case vmIntrinsics::_getAndSetInt:
- if (!VM_Version::supports_atomic_getset4()) {
- return false;
- }
- return append_unsafe_get_and_set_obj(callee, false);
- case vmIntrinsics::_getAndSetLong:
- if (!VM_Version::supports_atomic_getset8()) {
- return false;
- }
- return append_unsafe_get_and_set_obj(callee, false);
- case vmIntrinsics::_getAndSetObject:
-#ifdef _LP64
- if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) {
- return false;
- }
- if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) {
- return false;
- }
-#else
- if (!VM_Version::supports_atomic_getset4()) {
- return false;
- }
-#endif
- return append_unsafe_get_and_set_obj(callee, false);
-
- case vmIntrinsics::_Reference_get:
- // Use the intrinsic version of Reference.get() so that the value in
- // the referent field can be registered by the G1 pre-barrier code.
- // Also to prevent commoning reads from this field across safepoint
- // since GC can change its value.
- preserves_state = true;
- break;
-
- case vmIntrinsics::_updateCRC32:
- case vmIntrinsics::_updateBytesCRC32:
- case vmIntrinsics::_updateByteBufferCRC32:
- if (!UseCRC32Intrinsics) return false;
- cantrap = false;
- preserves_state = true;
- break;
-
- case vmIntrinsics::_loadFence :
- case vmIntrinsics::_storeFence:
- case vmIntrinsics::_fullFence :
- break;
-
- default : return false; // do not inline
- }
+
// create intrinsic node
const bool has_receiver = !callee->is_static();
ValueType* result_type = as_ValueType(callee->return_type());
@@ -3621,8 +3475,10 @@
}
}
- Intrinsic* result = new Intrinsic(result_type, id, args, has_receiver, state_before,
- preserves_state, cantrap);
+ Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(),
+ args, has_receiver, state_before,
+ vmIntrinsics::preserves_state(id),
+ vmIntrinsics::can_trap(id));
// append instruction & push result
Value value = append_split(result);
if (result_type != voidType) push(result_type, value);
@@ -3630,8 +3486,22 @@
if (callee != method() && profile_return() && result_type->is_object_kind()) {
profile_return_type(result, callee);
}
-
- // done
+}
+
+bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
+ // For calling is_intrinsic_available we need to transition to
+ // the '_thread_in_vm' state because is_intrinsic_available()
+ // does not accesses critical VM-internal data.
+ if (!_compilation->compiler()->is_intrinsic_available(callee->get_Method(), NULL)) {
+ if (!InlineNatives) {
+ // Return false and also set message that the inlining of
+ // intrinsics has been disabled in general.
+ INLINE_BAILOUT("intrinsic method inlining disabled");
+ } else {
+ return false;
+ }
+ }
+ build_graph_for_intrinsic(callee);
return true;
}
@@ -4224,58 +4094,46 @@
_scope_data = scope_data()->parent();
}
-bool GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) {
- if (InlineUnsafeOps) {
- Values* args = state()->pop_arguments(callee->arg_size());
- null_check(args->at(0));
- Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) {
+ Values* args = state()->pop_arguments(callee->arg_size());
+ null_check(args->at(0));
+ Instruction* offset = args->at(2);
#ifndef _LP64
- offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+ offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
- Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile));
- push(op->type(), op);
- compilation()->set_has_unsafe_access(true);
- }
- return InlineUnsafeOps;
+ Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile));
+ push(op->type(), op);
+ compilation()->set_has_unsafe_access(true);
}
-bool GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) {
- if (InlineUnsafeOps) {
- Values* args = state()->pop_arguments(callee->arg_size());
- null_check(args->at(0));
- Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) {
+ Values* args = state()->pop_arguments(callee->arg_size());
+ null_check(args->at(0));
+ Instruction* offset = args->at(2);
#ifndef _LP64
- offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+ offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
- Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile));
- compilation()->set_has_unsafe_access(true);
- kill_all();
- }
- return InlineUnsafeOps;
+ Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile));
+ compilation()->set_has_unsafe_access(true);
+ kill_all();
}
-bool GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) {
- if (InlineUnsafeOps) {
- Values* args = state()->pop_arguments(callee->arg_size());
- null_check(args->at(0));
- Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false));
- push(op->type(), op);
- compilation()->set_has_unsafe_access(true);
- }
- return InlineUnsafeOps;
+void GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) {
+ Values* args = state()->pop_arguments(callee->arg_size());
+ null_check(args->at(0));
+ Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false));
+ push(op->type(), op);
+ compilation()->set_has_unsafe_access(true);
}
-bool GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) {
- if (InlineUnsafeOps) {
- Values* args = state()->pop_arguments(callee->arg_size());
- null_check(args->at(0));
- Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2)));
- compilation()->set_has_unsafe_access(true);
- }
- return InlineUnsafeOps;
+void GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) {
+ Values* args = state()->pop_arguments(callee->arg_size());
+ null_check(args->at(0));
+ Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2)));
+ compilation()->set_has_unsafe_access(true);
}
@@ -4352,21 +4210,18 @@
}
}
-bool GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) {
- if (InlineUnsafeOps) {
- Values* args = state()->pop_arguments(callee->arg_size());
- BasicType t = callee->return_type()->basic_type();
- null_check(args->at(0));
- Instruction* offset = args->at(2);
+void GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) {
+ Values* args = state()->pop_arguments(callee->arg_size());
+ BasicType t = callee->return_type()->basic_type();
+ null_check(args->at(0));
+ Instruction* offset = args->at(2);
#ifndef _LP64
- offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
+ offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
- Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add));
- compilation()->set_has_unsafe_access(true);
- kill_all();
- push(op->type(), op);
- }
- return InlineUnsafeOps;
+ Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add));
+ compilation()->set_has_unsafe_access(true);
+ kill_all();
+ push(op->type(), op);
}
#ifndef PRODUCT
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -339,6 +339,8 @@
void inline_sync_entry(Value lock, BlockBegin* sync_handler);
void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false);
+ void build_graph_for_intrinsic(ciMethod* callee);
+
// inliners
bool try_inline( ciMethod* callee, bool holder_known, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL);
bool try_inline_intrinsics(ciMethod* callee);
@@ -364,12 +366,12 @@
void pop_scope();
void pop_scope_for_jsr();
- bool append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile);
- bool append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile);
- bool append_unsafe_get_raw(ciMethod* callee, BasicType t);
- bool append_unsafe_put_raw(ciMethod* callee, BasicType t);
+ void append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile);
+ void append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile);
+ void append_unsafe_get_raw(ciMethod* callee, BasicType t);
+ void append_unsafe_put_raw(ciMethod* callee, BasicType t);
void append_unsafe_CAS(ciMethod* callee);
- bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
+ void append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true);
--- a/hotspot/src/share/vm/c1/c1_ValueType.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_ValueType.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -153,7 +153,19 @@
case T_FLOAT : return new FloatConstant (value.as_float ());
case T_DOUBLE : return new DoubleConstant(value.as_double());
case T_ARRAY : // fall through (ciConstant doesn't have an array accessor)
- case T_OBJECT : return new ObjectConstant(value.as_object());
+ case T_OBJECT : {
+ // TODO: Common the code with GraphBuilder::load_constant?
+ ciObject* obj = value.as_object();
+ if (obj->is_null_object())
+ return objectNull;
+ if (obj->is_loaded()) {
+ if (obj->is_array())
+ return new ArrayConstant(obj->as_array());
+ else if (obj->is_instance())
+ return new InstanceConstant(obj->as_instance());
+ }
+ return new ObjectConstant(obj);
+ }
}
ShouldNotReachHere();
return illegalType;
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -809,6 +809,22 @@
return name;
}
+// Returns the Java name for this Java mirror (Resource allocated)
+// See Klass::external_name().
+// For primitive type Java mirrors, its type name is returned.
+const char* java_lang_Class::as_external_name(oop java_class) {
+ assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+ const char* name = NULL;
+ if (is_primitive(java_class)) {
+ name = type2name(primitive_type(java_class));
+ } else {
+ name = as_Klass(java_class)->external_name();
+ }
+ if (name == NULL) {
+ name = "<null>";
+ }
+ return name;
+}
Klass* java_lang_Class::array_klass(oop java_class) {
Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
@@ -1468,6 +1484,19 @@
};
+Symbol* get_source_file_name(InstanceKlass* holder, int version) {
+ // Find the specific ik version that contains this source_file_name_index
+ // via the previous versions list, but use the current version's
+ // constant pool to look it up. The previous version's index has been
+ // merged for the current constant pool.
+ InstanceKlass* ik = holder->get_klass_version(version);
+ // This version has been cleaned up.
+ if (ik == NULL) return NULL;
+ int source_file_name_index = ik->source_file_name_index();
+ return (source_file_name_index == 0) ?
+ (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index);
+}
+
// Print stack trace element to resource allocated buffer
char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
int method_id, int version, int bci, int cpref) {
@@ -1484,17 +1513,11 @@
char* method_name = sym->as_C_string();
buf_len += (int)strlen(method_name);
- // Use specific ik version as a holder since the mirror might
- // refer to version that is now obsolete and no longer accessible
- // via the previous versions list.
- holder = holder->get_klass_version(version);
char* source_file_name = NULL;
- if (holder != NULL) {
- Symbol* source = holder->source_file_name();
- if (source != NULL) {
- source_file_name = source->as_C_string();
- buf_len += (int)strlen(source_file_name);
- }
+ Symbol* source = get_source_file_name(holder, version);
+ if (source != NULL) {
+ source_file_name = source->as_C_string();
+ buf_len += (int)strlen(source_file_name);
}
// Allocate temporary buffer with extra space for formatting and line number
@@ -1909,12 +1932,7 @@
java_lang_StackTraceElement::set_lineNumber(element(), -1);
} else {
// Fill in source file name and line number.
- // Use specific ik version as a holder since the mirror might
- // refer to version that is now obsolete and no longer accessible
- // via the previous versions list.
- holder = holder->get_klass_version(version);
- assert(holder != NULL, "sanity check");
- Symbol* source = holder->source_file_name();
+ Symbol* source = get_source_file_name(holder, version);
if (ShowHiddenFrames && source == NULL)
source = vmSymbols::unknown_class_name();
oop filename = StringTable::intern(source, CHECK_0);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -276,6 +276,7 @@
}
static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS);
static void print_signature(oop java_class, outputStream *st);
+ static const char* as_external_name(oop java_class);
// Testing
static bool is_instance(oop obj);
--- a/hotspot/src/share/vm/classfile/verificationType.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -86,7 +86,7 @@
VerificationType comp_this = get_component(context, CHECK_false);
VerificationType comp_from = from.get_component(context, CHECK_false);
if (!comp_this.is_bogus() && !comp_from.is_bogus()) {
- return comp_this.is_assignable_from(comp_from, context,
+ return comp_this.is_component_assignable_from(comp_from, context,
from_field_is_protected, CHECK_false);
}
}
--- a/hotspot/src/share/vm/classfile/verificationType.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -297,6 +297,26 @@
}
}
+ // Check to see if one array component type is assignable to another.
+ // Same as is_assignable_from() except int primitives must be identical.
+ bool is_component_assignable_from(
+ const VerificationType& from, ClassVerifier* context,
+ bool from_field_is_protected, TRAPS) const {
+ if (equals(from) || is_bogus()) {
+ return true;
+ } else {
+ switch(_u._data) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ return false;
+ default:
+ return is_assignable_from(from, context, from_field_is_protected, CHECK_false);
+ }
+ }
+ }
+
VerificationType get_component(ClassVerifier* context, TRAPS) const;
int dimensions() const {
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -324,6 +324,319 @@
return vmIntrinsics::_none;
}
+bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+ switch(id) {
+#ifdef TRACE_HAVE_INTRINSICS
+ case vmIntrinsics::_classID:
+ case vmIntrinsics::_threadID:
+ case vmIntrinsics::_counterTime:
+#endif
+ case vmIntrinsics::_currentTimeMillis:
+ case vmIntrinsics::_nanoTime:
+ case vmIntrinsics::_floatToRawIntBits:
+ case vmIntrinsics::_intBitsToFloat:
+ case vmIntrinsics::_doubleToRawLongBits:
+ case vmIntrinsics::_longBitsToDouble:
+ case vmIntrinsics::_getClass:
+ case vmIntrinsics::_isInstance:
+ case vmIntrinsics::_currentThread:
+ case vmIntrinsics::_dabs:
+ case vmIntrinsics::_dsqrt:
+ case vmIntrinsics::_dsin:
+ case vmIntrinsics::_dcos:
+ case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dlog:
+ case vmIntrinsics::_dlog10:
+ case vmIntrinsics::_dexp:
+ case vmIntrinsics::_dpow:
+ case vmIntrinsics::_checkIndex:
+ case vmIntrinsics::_Reference_get:
+ case vmIntrinsics::_updateCRC32:
+ case vmIntrinsics::_updateBytesCRC32:
+ case vmIntrinsics::_updateByteBufferCRC32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool vmIntrinsics::can_trap(vmIntrinsics::ID id) {
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+ switch(id) {
+#ifdef TRACE_HAVE_INTRINSICS
+ case vmIntrinsics::_counterTime:
+#endif
+ case vmIntrinsics::_currentTimeMillis:
+ case vmIntrinsics::_nanoTime:
+ case vmIntrinsics::_floatToRawIntBits:
+ case vmIntrinsics::_intBitsToFloat:
+ case vmIntrinsics::_doubleToRawLongBits:
+ case vmIntrinsics::_longBitsToDouble:
+ case vmIntrinsics::_currentThread:
+ case vmIntrinsics::_dabs:
+ case vmIntrinsics::_dsqrt:
+ case vmIntrinsics::_dsin:
+ case vmIntrinsics::_dcos:
+ case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dlog:
+ case vmIntrinsics::_dlog10:
+ case vmIntrinsics::_dexp:
+ case vmIntrinsics::_dpow:
+ case vmIntrinsics::_updateCRC32:
+ case vmIntrinsics::_updateBytesCRC32:
+ case vmIntrinsics::_updateByteBufferCRC32:
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool vmIntrinsics::does_virtual_dispatch(vmIntrinsics::ID id) {
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+ switch(id) {
+ case vmIntrinsics::_hashCode:
+ case vmIntrinsics::_clone:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+ switch (id) {
+ case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+ case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+ return 1;
+ case vmIntrinsics::_digestBase_implCompressMB:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+ switch (id) {
+ case vmIntrinsics::_isInstance:
+ case vmIntrinsics::_isAssignableFrom:
+ case vmIntrinsics::_getModifiers:
+ case vmIntrinsics::_isInterface:
+ case vmIntrinsics::_isArray:
+ case vmIntrinsics::_isPrimitive:
+ case vmIntrinsics::_getSuperclass:
+ case vmIntrinsics::_Class_cast:
+ case vmIntrinsics::_getLength:
+ case vmIntrinsics::_newArray:
+ if (!InlineClassNatives) return true;
+ break;
+ case vmIntrinsics::_currentThread:
+ case vmIntrinsics::_isInterrupted:
+ if (!InlineThreadNatives) return true;
+ break;
+ case vmIntrinsics::_floatToRawIntBits:
+ case vmIntrinsics::_intBitsToFloat:
+ case vmIntrinsics::_doubleToRawLongBits:
+ case vmIntrinsics::_longBitsToDouble:
+ case vmIntrinsics::_dabs:
+ case vmIntrinsics::_dsqrt:
+ case vmIntrinsics::_dsin:
+ case vmIntrinsics::_dcos:
+ case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dlog:
+ case vmIntrinsics::_dexp:
+ case vmIntrinsics::_dpow:
+ case vmIntrinsics::_dlog10:
+ case vmIntrinsics::_datan2:
+ case vmIntrinsics::_min:
+ case vmIntrinsics::_max:
+ case vmIntrinsics::_floatToIntBits:
+ case vmIntrinsics::_doubleToLongBits:
+ if (!InlineMathNatives) return true;
+ break;
+ case vmIntrinsics::_arraycopy:
+ if (!InlineArrayCopy) return true;
+ break;
+ case vmIntrinsics::_updateCRC32:
+ case vmIntrinsics::_updateBytesCRC32:
+ case vmIntrinsics::_updateByteBufferCRC32:
+ if (!UseCRC32Intrinsics) return true;
+ break;
+ case vmIntrinsics::_getObject:
+ case vmIntrinsics::_getBoolean:
+ case vmIntrinsics::_getByte:
+ case vmIntrinsics::_getShort:
+ case vmIntrinsics::_getChar:
+ case vmIntrinsics::_getInt:
+ case vmIntrinsics::_getLong:
+ case vmIntrinsics::_getFloat:
+ case vmIntrinsics::_getDouble:
+ case vmIntrinsics::_putObject:
+ case vmIntrinsics::_putBoolean:
+ case vmIntrinsics::_putByte:
+ case vmIntrinsics::_putShort:
+ case vmIntrinsics::_putChar:
+ case vmIntrinsics::_putInt:
+ case vmIntrinsics::_putLong:
+ case vmIntrinsics::_putFloat:
+ case vmIntrinsics::_putDouble:
+ case vmIntrinsics::_getObjectVolatile:
+ case vmIntrinsics::_getBooleanVolatile:
+ case vmIntrinsics::_getByteVolatile:
+ case vmIntrinsics::_getShortVolatile:
+ case vmIntrinsics::_getCharVolatile:
+ case vmIntrinsics::_getIntVolatile:
+ case vmIntrinsics::_getLongVolatile:
+ case vmIntrinsics::_getFloatVolatile:
+ case vmIntrinsics::_getDoubleVolatile:
+ case vmIntrinsics::_putObjectVolatile:
+ case vmIntrinsics::_putBooleanVolatile:
+ case vmIntrinsics::_putByteVolatile:
+ case vmIntrinsics::_putShortVolatile:
+ case vmIntrinsics::_putCharVolatile:
+ case vmIntrinsics::_putIntVolatile:
+ case vmIntrinsics::_putLongVolatile:
+ case vmIntrinsics::_putFloatVolatile:
+ case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getByte_raw:
+ case vmIntrinsics::_getShort_raw:
+ case vmIntrinsics::_getChar_raw:
+ case vmIntrinsics::_getInt_raw:
+ case vmIntrinsics::_getLong_raw:
+ case vmIntrinsics::_getFloat_raw:
+ case vmIntrinsics::_getDouble_raw:
+ case vmIntrinsics::_putByte_raw:
+ case vmIntrinsics::_putShort_raw:
+ case vmIntrinsics::_putChar_raw:
+ case vmIntrinsics::_putInt_raw:
+ case vmIntrinsics::_putLong_raw:
+ case vmIntrinsics::_putFloat_raw:
+ case vmIntrinsics::_putDouble_raw:
+ case vmIntrinsics::_putOrderedObject:
+ case vmIntrinsics::_putOrderedLong:
+ case vmIntrinsics::_putOrderedInt:
+ case vmIntrinsics::_getAndAddInt:
+ case vmIntrinsics::_getAndAddLong:
+ case vmIntrinsics::_getAndSetInt:
+ case vmIntrinsics::_getAndSetLong:
+ case vmIntrinsics::_getAndSetObject:
+ if (!InlineUnsafeOps) return true;
+ break;
+ case vmIntrinsics::_getShortUnaligned:
+ case vmIntrinsics::_getCharUnaligned:
+ case vmIntrinsics::_getIntUnaligned:
+ case vmIntrinsics::_getLongUnaligned:
+ case vmIntrinsics::_putShortUnaligned:
+ case vmIntrinsics::_putCharUnaligned:
+ case vmIntrinsics::_putIntUnaligned:
+ case vmIntrinsics::_putLongUnaligned:
+ case vmIntrinsics::_allocateInstance:
+ case vmIntrinsics::_getAddress_raw:
+ case vmIntrinsics::_putAddress_raw:
+ if (!InlineUnsafeOps || !UseUnalignedAccesses) return true;
+ break;
+ case vmIntrinsics::_hashCode:
+ if (!InlineObjectHash) return true;
+ break;
+ case vmIntrinsics::_aescrypt_encryptBlock:
+ case vmIntrinsics::_aescrypt_decryptBlock:
+ if (!UseAESIntrinsics) return true;
+ break;
+ case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+ case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+ if (!UseAESIntrinsics) return true;
+ break;
+ case vmIntrinsics::_sha_implCompress:
+ if (!UseSHA1Intrinsics) return true;
+ break;
+ case vmIntrinsics::_sha2_implCompress:
+ if (!UseSHA256Intrinsics) return true;
+ break;
+ case vmIntrinsics::_sha5_implCompress:
+ if (!UseSHA512Intrinsics) return true;
+ break;
+ case vmIntrinsics::_digestBase_implCompressMB:
+ if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return true;
+ break;
+ case vmIntrinsics::_ghash_processBlocks:
+ if (!UseGHASHIntrinsics) return true;
+ break;
+ case vmIntrinsics::_updateBytesCRC32C:
+ case vmIntrinsics::_updateDirectByteBufferCRC32C:
+ if (!UseCRC32CIntrinsics) return true;
+ break;
+ case vmIntrinsics::_copyMemory:
+ if (!InlineArrayCopy || !InlineUnsafeOps) return true;
+ break;
+#ifdef COMPILER1
+ case vmIntrinsics::_checkIndex:
+ if (!InlineNIOCheckIndex) return true;
+ break;
+#endif // COMPILER1
+#ifdef COMPILER2
+ case vmIntrinsics::_clone:
+ case vmIntrinsics::_copyOf:
+ case vmIntrinsics::_copyOfRange:
+ // These intrinsics use both the objectcopy and the arraycopy
+ // intrinsic mechanism.
+ if (!InlineObjectCopy || !InlineArrayCopy) return true;
+ break;
+ case vmIntrinsics::_compareTo:
+ if (!SpecialStringCompareTo) return true;
+ break;
+ case vmIntrinsics::_indexOf:
+ if (!SpecialStringIndexOf) return true;
+ break;
+ case vmIntrinsics::_equals:
+ if (!SpecialStringEquals) return true;
+ break;
+ case vmIntrinsics::_equalsC:
+ if (!SpecialArraysEquals) return true;
+ break;
+ case vmIntrinsics::_encodeISOArray:
+ if (!SpecialEncodeISOArray) return true;
+ break;
+ case vmIntrinsics::_getCallerClass:
+ if (!InlineReflectionGetCallerClass) return true;
+ break;
+ case vmIntrinsics::_multiplyToLen:
+ if (!UseMultiplyToLenIntrinsic) return true;
+ break;
+ case vmIntrinsics::_squareToLen:
+ if (!UseSquareToLenIntrinsic) return true;
+ break;
+ case vmIntrinsics::_mulAdd:
+ if (!UseMulAddIntrinsic) return true;
+ break;
+ case vmIntrinsics::_montgomeryMultiply:
+ if (!UseMontgomeryMultiplyIntrinsic) return true;
+ break;
+ case vmIntrinsics::_montgomerySquare:
+ if (!UseMontgomerySquareIntrinsic) return true;
+ break;
+ case vmIntrinsics::_addExactI:
+ case vmIntrinsics::_addExactL:
+ case vmIntrinsics::_decrementExactI:
+ case vmIntrinsics::_decrementExactL:
+ case vmIntrinsics::_incrementExactI:
+ case vmIntrinsics::_incrementExactL:
+ case vmIntrinsics::_multiplyExactI:
+ case vmIntrinsics::_multiplyExactL:
+ case vmIntrinsics::_negateExactI:
+ case vmIntrinsics::_negateExactL:
+ case vmIntrinsics::_subtractExactI:
+ case vmIntrinsics::_subtractExactL:
+ if (!UseMathExactIntrinsics || !InlineMathNatives) return true;
+ break;
+#endif // COMPILER2
+ default:
+ return false;
+ }
+
+ return false;
+}
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
static const char* vm_intrinsic_name_bodies =
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -1368,6 +1368,26 @@
// Raw conversion:
static ID for_raw_conversion(BasicType src, BasicType dest);
+
+ // The methods below provide information related to compiling intrinsics.
+
+ // (1) Information needed by the C1 compiler.
+
+ static bool preserves_state(vmIntrinsics::ID id);
+ static bool can_trap(vmIntrinsics::ID id);
+
+ // (2) Information needed by the C2 compiler.
+
+ // Returns true if the intrinsic for method 'method' will perform a virtual dispatch.
+ static bool does_virtual_dispatch(vmIntrinsics::ID id);
+ // A return value larger than 0 indicates that the intrinsic for method
+ // 'method' requires predicated logic.
+ static int predicates_needed(vmIntrinsics::ID id);
+
+ // Returns true if an intrinsic is disabled by command-line flags and
+ // false otherwise. Implements functionality common to the C1
+ // and the C2 compiler.
+ static bool is_disabled_by_flags(vmIntrinsics::ID id);
};
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -66,6 +66,58 @@
virtual bool supports_osr () { return true; }
virtual bool can_compile_method(methodHandle method) { return true; }
+ // Determine if the current compiler provides an intrinsic
+ // for method 'method'. An intrinsic is available if:
+ // - the intrinsic is enabled (by using the appropriate command-line flag) and
+ // - the platform on which the VM is running supports the intrinsic
+ // (i.e., the platform provides the instructions necessary for the compiler
+ // to generate the intrinsic code).
+ //
+ // The second parameter, 'compilation_context', is needed to implement functionality
+ // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
+ // be used to prohibit the C2 compiler (but not the C1 compiler) to use an intrinsic.
+ // There are three ways to disable an intrinsic using the DisableIntrinsic flag:
+ //
+ // (1) -XX:DisableIntrinsic=_hashCode,_getClass
+ // Disables intrinsification of _hashCode and _getClass globally
+ // (i.e., the intrinsified version the methods will not be used at all).
+ // (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
+ // Disables intrinsification of _hashCode if it is called from
+ // aClass::aMethod (but not for any other call site of _hashCode)
+ // (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
+ // Some methods are not compiled by C2. Instead, the C2 compiler
+ // returns directly the intrinsified version of these methods.
+ // The command above forces C2 to compile _Reference_get, but
+ // allows using the intrinsified version of _Reference_get at all
+ // other call sites.
+ //
+ // From the modes above, (1) disable intrinsics globally, (2) and (3)
+ // disable intrinsics on a per-method basis. In cases (2) and (3) the
+ // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
+ // respectively.
+ virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+ return false;
+ }
+
+ // Determines if an intrinsic is supported by the compiler, that is,
+ // the compiler provides the instructions necessary to generate
+ // the intrinsic code for method 'method'.
+ //
+ // The 'is_intrinsic_supported' method is a white list, that is,
+ // by default no intrinsics are supported by a compiler except
+ // the ones listed in the method. Overriding methods should conform
+ // to this behavior.
+ virtual bool is_intrinsic_supported(methodHandle method) {
+ return false;
+ }
+
+ // Implements compiler-specific processing of command-line flags.
+ // Processing of command-line flags common to all compilers is implemented
+ // in vmIntrinsicss::is_disabled_by_flag.
+ virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
+ return false;
+ }
+
// Compiler type queries.
bool is_c1() { return _type == c1; }
bool is_c2() { return _type == c2; }
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, 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
@@ -345,6 +345,14 @@
}
}
+// RedefineClasses support
+void CompileTask::metadata_do(void f(Metadata*)) {
+ f(method());
+ if (hot_method() != NULL && hot_method() != method()) {
+ f(hot_method());
+ }
+}
+
// ------------------------------------------------------------------
// CompileTask::print_line_on_error
//
@@ -660,6 +668,11 @@
* Get the next CompileTask from a CompileQueue
*/
CompileTask* CompileQueue::get() {
+ // save methods from RedefineClasses across safepoint
+ // across MethodCompileQueue_lock below.
+ methodHandle save_method;
+ methodHandle save_hot_method;
+
MutexLocker locker(MethodCompileQueue_lock);
// If _first is NULL we have no more compile jobs. There are two reasons for
// having no compile jobs: First, we compiled everything we wanted. Second,
@@ -693,6 +706,12 @@
No_Safepoint_Verifier nsv;
task = CompilationPolicy::policy()->select_task(this);
}
+
+ // Save method pointers across unlock safepoint. The task is removed from
+ // the compilation queue, which is walked during RedefineClasses.
+ save_method = methodHandle(task->method());
+ save_hot_method = methodHandle(task->hot_method());
+
remove(task);
purge_stale_tasks(); // may temporarily release MCQ lock
return task;
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, 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
@@ -80,6 +80,7 @@
int compile_id() const { return _compile_id; }
Method* method() const { return _method; }
+ Method* hot_method() const { return _hot_method; }
int osr_bci() const { return _osr_bci; }
bool is_complete() const { return _is_complete; }
bool is_blocking() const { return _is_blocking; }
@@ -108,6 +109,9 @@
bool is_free() const { return _is_free; }
void set_is_free(bool val) { _is_free = val; }
+ // RedefineClasses support
+ void metadata_do(void f(Metadata*));
+
private:
static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -36,10 +36,11 @@
#include "runtime/orderAccess.inline.hpp"
#include "runtime/vmThread.hpp"
-void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
- OopsInGenClosure* cl,
- CardTableRS* ct,
- uint n_threads) {
+void CardTableModRefBSForCTRS::
+non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+ OopsInGenClosure* cl,
+ CardTableRS* ct,
+ uint n_threads) {
assert(n_threads > 0, "expected n_threads > 0");
assert(n_threads <= ParallelGCThreads,
err_msg("n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads));
@@ -81,7 +82,7 @@
}
void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
process_stride(Space* sp,
MemRegion used,
jint stride, int n_strides,
@@ -170,7 +171,7 @@
#endif
void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
process_chunk_boundaries(Space* sp,
DirtyCardToOopClosure* dcto_cl,
MemRegion chunk_mr,
@@ -426,7 +427,7 @@
#undef NOISY
void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
get_LNC_array_for_space(Space* sp,
jbyte**& lowest_non_clean,
uintptr_t& lowest_non_clean_base_chunk_index,
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -403,14 +403,6 @@
_saved_index = -1;
}
-void CMMarkStack::oops_do(OopClosure* f) {
- assert(_saved_index == _index,
- err_msg("saved index: %d index: %d", _saved_index, _index));
- for (int i = 0; i < _index; i += 1) {
- f->do_oop(&_base[i]);
- }
-}
-
CMRootRegions::CMRootRegions() :
_young_list(NULL), _cm(NULL), _scan_in_progress(false),
_should_abort(false), _next_survivor(NULL) { }
@@ -2717,53 +2709,26 @@
}
#ifndef PRODUCT
-enum VerifyNoCSetOopsPhase {
- VerifyNoCSetOopsStack,
- VerifyNoCSetOopsQueues
-};
-
-class VerifyNoCSetOopsClosure : public OopClosure, public ObjectClosure {
+class VerifyNoCSetOops VALUE_OBJ_CLASS_SPEC {
private:
G1CollectedHeap* _g1h;
- VerifyNoCSetOopsPhase _phase;
+ const char* _phase;
int _info;
- const char* phase_str() {
- switch (_phase) {
- case VerifyNoCSetOopsStack: return "Stack";
- case VerifyNoCSetOopsQueues: return "Queue";
- default: ShouldNotReachHere();
- }
- return NULL;
- }
-
- void do_object_work(oop obj) {
+public:
+ VerifyNoCSetOops(const char* phase, int info = -1) :
+ _g1h(G1CollectedHeap::heap()),
+ _phase(phase),
+ _info(info)
+ { }
+
+ void operator()(oop obj) const {
+ guarantee(obj->is_oop(),
+ err_msg("Non-oop " PTR_FORMAT ", phase: %s, info: %d",
+ p2i(obj), _phase, _info));
guarantee(!_g1h->obj_in_cs(obj),
err_msg("obj: " PTR_FORMAT " in CSet, phase: %s, info: %d",
- p2i((void*) obj), phase_str(), _info));
- }
-
-public:
- VerifyNoCSetOopsClosure() : _g1h(G1CollectedHeap::heap()) { }
-
- void set_phase(VerifyNoCSetOopsPhase phase, int info = -1) {
- _phase = phase;
- _info = info;
- }
-
- virtual void do_oop(oop* p) {
- oop obj = oopDesc::load_decode_heap_oop(p);
- do_object_work(obj);
- }
-
- virtual void do_oop(narrowOop* p) {
- // We should not come across narrow oops while scanning marking
- // stacks
- ShouldNotReachHere();
- }
-
- virtual void do_object(oop obj) {
- do_object_work(obj);
+ p2i(obj), _phase, _info));
}
};
@@ -2773,17 +2738,13 @@
return;
}
- VerifyNoCSetOopsClosure cl;
-
// Verify entries on the global mark stack
- cl.set_phase(VerifyNoCSetOopsStack);
- _markStack.oops_do(&cl);
+ _markStack.iterate(VerifyNoCSetOops("Stack"));
// Verify entries on the task queues
- for (uint i = 0; i < _max_worker_id; i += 1) {
- cl.set_phase(VerifyNoCSetOopsQueues, i);
+ for (uint i = 0; i < _max_worker_id; ++i) {
CMTaskQueue* queue = _task_queues->queue(i);
- queue->oops_do(&cl);
+ queue->iterate(VerifyNoCSetOops("Queue", i));
}
// Verify the global finger
@@ -2806,7 +2767,7 @@
// Verify the task fingers
assert(parallel_marking_threads() <= _max_worker_id, "sanity");
- for (int i = 0; i < (int) parallel_marking_threads(); i += 1) {
+ for (uint i = 0; i < parallel_marking_threads(); ++i) {
CMTask* task = _tasks[i];
HeapWord* task_finger = task->finger();
if (task_finger != NULL && task_finger < _heap_end) {
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -246,9 +246,10 @@
// Make sure that we have not added any entries to the stack during GC.
void note_end_of_gc();
- // iterate over the oops in the mark stack, up to the bound recorded via
- // the call above.
- void oops_do(OopClosure* f);
+ // Apply fn to each oop in the mark stack, up to the bound recorded
+ // via one of the above "note" functions. The mark stack must not
+ // be modified while iterating.
+ template<typename Fn> void iterate(Fn fn);
};
class ForceOverflowSettings VALUE_OBJ_CLASS_SPEC {
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -223,6 +223,15 @@
#undef check_mark
+template<typename Fn>
+inline void CMMarkStack::iterate(Fn fn) {
+ assert(_saved_index == _index,
+ err_msg("saved index: %d index: %d", _saved_index, _index));
+ for (int i = 0; i < _index; ++i) {
+ fn(_base[i]);
+ }
+}
+
inline void CMTask::push(oop obj) {
HeapWord* objAddr = (HeapWord*) obj;
assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -39,13 +39,8 @@
protected:
G1CollectedHeap* _g1h;
- // Outside of GC pauses, the number of bytes used in all regions other
- // than the current allocation region.
- size_t _summary_bytes_used;
-
public:
- G1Allocator(G1CollectedHeap* heap) :
- _g1h(heap), _summary_bytes_used(0) { }
+ G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { }
static G1Allocator* create_allocator(G1CollectedHeap* g1h);
@@ -59,32 +54,13 @@
virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0;
virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0;
- virtual size_t used() = 0;
+ virtual size_t used_in_alloc_regions() = 0;
virtual bool is_retained_old_region(HeapRegion* hr) = 0;
void reuse_retained_old_region(EvacuationInfo& evacuation_info,
OldGCAllocRegion* old,
HeapRegion** retained);
- size_t used_unlocked() const {
- return _summary_bytes_used;
- }
-
- void increase_used(size_t bytes) {
- _summary_bytes_used += bytes;
- }
-
- void decrease_used(size_t bytes) {
- assert(_summary_bytes_used >= bytes,
- err_msg("invariant: _summary_bytes_used: " SIZE_FORMAT " should be >= bytes: " SIZE_FORMAT,
- _summary_bytes_used, bytes));
- _summary_bytes_used -= bytes;
- }
-
- void set_used(size_t bytes) {
- _summary_bytes_used = bytes;
- }
-
virtual HeapRegion* new_heap_region(uint hrs_index,
G1BlockOffsetSharedArray* sharedOffsetArray,
MemRegion mr) {
@@ -133,10 +109,10 @@
return &_old_gc_alloc_region;
}
- virtual size_t used() {
+ virtual size_t used_in_alloc_regions() {
assert(Heap_lock->owner() != NULL,
"Should be owned on this thread's behalf.");
- size_t result = _summary_bytes_used;
+ size_t result = 0;
// Read only once in case it is set to NULL concurrently
HeapRegion* hr = mutator_alloc_region(AllocationContext::current())->get();
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -632,7 +632,7 @@
check_bitmaps("Humongous Region Allocation", first_hr);
assert(first_hr->used() == word_size * HeapWordSize, "invariant");
- _allocator->increase_used(first_hr->used());
+ increase_used(first_hr->used());
_humongous_set.add(first_hr);
return new_obj;
@@ -998,7 +998,7 @@
if ((prev_last_region != NULL) && (start_region == prev_last_region)) {
start_address = start_region->end();
if (start_address > last_address) {
- _allocator->increase_used(word_size * HeapWordSize);
+ increase_used(word_size * HeapWordSize);
start_region->set_top(last_address + 1);
continue;
}
@@ -1012,7 +1012,7 @@
if (!_hrm.allocate_containing_regions(curr_range, &commits)) {
return false;
}
- _allocator->increase_used(word_size * HeapWordSize);
+ increase_used(word_size * HeapWordSize);
if (commits != 0) {
ergo_verbose1(ErgoHeapSizing,
"attempt heap expansion",
@@ -1104,7 +1104,7 @@
if (start_address != bottom_address) {
size_t fill_size = pointer_delta(start_address, bottom_address);
G1CollectedHeap::fill_with_objects(bottom_address, fill_size);
- _allocator->increase_used(fill_size * HeapWordSize);
+ increase_used(fill_size * HeapWordSize);
}
}
}
@@ -1917,7 +1917,6 @@
_ref_processor_cm(NULL),
_ref_processor_stw(NULL),
_bot_shared(NULL),
- _evac_failure_scan_stack(NULL),
_cg1r(NULL),
_g1mm(NULL),
_refine_cte_cl(NULL),
@@ -1930,6 +1929,7 @@
_free_regions_coming(false),
_young_list(new YoungList(this)),
_gc_time_stamp(0),
+ _summary_bytes_used(0),
_survivor_plab_stats(YoungPLABSize, PLABWeight),
_old_plab_stats(OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true),
@@ -2204,6 +2204,11 @@
G1StringDedup::initialize();
+ _preserved_objs = NEW_C_HEAP_ARRAY(OopAndMarkOopStack, ParallelGCThreads, mtGC);
+ for (uint i = 0; i < ParallelGCThreads; i++) {
+ new (&_preserved_objs[i]) OopAndMarkOopStack();
+ }
+
return JNI_OK;
}
@@ -2371,7 +2376,7 @@
// Computes the sum of the storage used by the various regions.
size_t G1CollectedHeap::used() const {
- size_t result = _allocator->used();
+ size_t result = _summary_bytes_used + _allocator->used_in_alloc_regions();
if (_archive_allocator != NULL) {
result += _archive_allocator->used();
}
@@ -2379,7 +2384,7 @@
}
size_t G1CollectedHeap::used_unlocked() const {
- return _allocator->used_unlocked();
+ return _summary_bytes_used;
}
class SumUsedClosure: public HeapRegionClosure {
@@ -3376,7 +3381,7 @@
// Print the per-region information.
st->cr();
- st->print_cr("Heap Regions: (Y=young(eden), SU=young(survivor), "
+ st->print_cr("Heap Regions: (E=young(eden), S=young(survivor), O=old, "
"HS=humongous(starts), HC=humongous(continues), "
"CS=collection set, F=free, A=archive, TS=gc time stamp, "
"PTAMS=previous top-at-mark-start, "
@@ -4102,7 +4107,7 @@
_young_list->reset_auxilary_lists();
if (evacuation_failed()) {
- _allocator->set_used(recalculate_used());
+ set_used(recalculate_used());
if (_archive_allocator != NULL) {
_archive_allocator->clear_used();
}
@@ -4114,7 +4119,7 @@
} else {
// The "used" of the the collection set have already been subtracted
// when they were freed. Add in the bytes evacuated.
- _allocator->increase_used(g1_policy()->bytes_copied_during_gc());
+ increase_used(g1_policy()->bytes_copied_during_gc());
}
if (collector_state()->during_initial_mark_pause()) {
@@ -4255,21 +4260,6 @@
return true;
}
-void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) {
- _drain_in_progress = false;
- set_evac_failure_closure(cl);
- _evac_failure_scan_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
-}
-
-void G1CollectedHeap::finalize_for_evac_failure() {
- assert(_evac_failure_scan_stack != NULL &&
- _evac_failure_scan_stack->length() == 0,
- "Postcondition");
- assert(!_drain_in_progress, "Postcondition");
- delete _evac_failure_scan_stack;
- _evac_failure_scan_stack = NULL;
-}
-
void G1CollectedHeap::remove_self_forwarding_pointers() {
double remove_self_forwards_start = os::elapsedTime();
@@ -4277,104 +4267,30 @@
workers()->run_task(&rsfp_task);
// Now restore saved marks, if any.
- assert(_objs_with_preserved_marks.size() ==
- _preserved_marks_of_objs.size(), "Both or none.");
- while (!_objs_with_preserved_marks.is_empty()) {
- oop obj = _objs_with_preserved_marks.pop();
- markOop m = _preserved_marks_of_objs.pop();
- obj->set_mark(m);
- }
- _objs_with_preserved_marks.clear(true);
- _preserved_marks_of_objs.clear(true);
+ for (uint i = 0; i < ParallelGCThreads; i++) {
+ OopAndMarkOopStack& cur = _preserved_objs[i];
+ while (!cur.is_empty()) {
+ OopAndMarkOop elem = cur.pop();
+ elem.set_mark();
+ }
+ cur.clear(true);
+ }
g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0);
}
-void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
- _evac_failure_scan_stack->push(obj);
-}
-
-void G1CollectedHeap::drain_evac_failure_scan_stack() {
- assert(_evac_failure_scan_stack != NULL, "precondition");
-
- while (_evac_failure_scan_stack->length() > 0) {
- oop obj = _evac_failure_scan_stack->pop();
- _evac_failure_closure->set_region(heap_region_containing(obj));
- obj->oop_iterate_backwards(_evac_failure_closure);
- }
-}
-
-oop
-G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state,
- oop old) {
- assert(obj_in_cs(old),
- err_msg("obj: " PTR_FORMAT " should still be in the CSet",
- p2i(old)));
- markOop m = old->mark();
- oop forward_ptr = old->forward_to_atomic(old);
- if (forward_ptr == NULL) {
- // Forward-to-self succeeded.
- assert(_par_scan_state != NULL, "par scan state");
- OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure();
- uint queue_num = _par_scan_state->queue_num();
-
+void G1CollectedHeap::preserve_mark_during_evac_failure(uint queue_num, oop obj, markOop m) {
+ if (!_evacuation_failed) {
_evacuation_failed = true;
- _evacuation_failed_info_array[queue_num].register_copy_failure(old->size());
- if (_evac_failure_closure != cl) {
- MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag);
- assert(!_drain_in_progress,
- "Should only be true while someone holds the lock.");
- // Set the global evac-failure closure to the current thread's.
- assert(_evac_failure_closure == NULL, "Or locking has failed.");
- set_evac_failure_closure(cl);
- // Now do the common part.
- handle_evacuation_failure_common(old, m);
- // Reset to NULL.
- set_evac_failure_closure(NULL);
- } else {
- // The lock is already held, and this is recursive.
- assert(_drain_in_progress, "This should only be the recursive case.");
- handle_evacuation_failure_common(old, m);
- }
- return old;
- } else {
- // Forward-to-self failed. Either someone else managed to allocate
- // space for this object (old != forward_ptr) or they beat us in
- // self-forwarding it (old == forward_ptr).
- assert(old == forward_ptr || !obj_in_cs(forward_ptr),
- err_msg("obj: " PTR_FORMAT " forwarded to: " PTR_FORMAT " "
- "should not be in the CSet",
- p2i(old), p2i(forward_ptr)));
- return forward_ptr;
- }
-}
-
-void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) {
- preserve_mark_if_necessary(old, m);
-
- HeapRegion* r = heap_region_containing(old);
- if (!r->evacuation_failed()) {
- r->set_evacuation_failed(true);
- _hr_printer.evac_failure(r);
- }
-
- push_on_evac_failure_scan_stack(old);
-
- if (!_drain_in_progress) {
- // prevent recursion in copy_to_survivor_space()
- _drain_in_progress = true;
- drain_evac_failure_scan_stack();
- _drain_in_progress = false;
- }
-}
-
-void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) {
- assert(evacuation_failed(), "Oversaving!");
+ }
+
+ _evacuation_failed_info_array[queue_num].register_copy_failure(obj->size());
+
// We want to call the "for_promotion_failure" version only in the
// case of a promotion failure.
if (m->must_be_preserved_for_promotion_failure(obj)) {
- _objs_with_preserved_marks.push(obj);
- _preserved_marks_of_objs.push(m);
+ OopAndMarkOop elem(obj, m);
+ _preserved_objs[queue_num].push(elem);
}
}
@@ -4450,14 +4366,7 @@
mark_object(obj);
}
}
-
- if (barrier == G1BarrierEvac) {
- _par_scan_state->update_rs(_from, p, _worker_id);
- }
-}
-
-template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(oop* p);
-template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(narrowOop* p);
+}
class G1ParEvacuateFollowersClosure : public VoidClosure {
protected:
@@ -4597,9 +4506,6 @@
ReferenceProcessor* rp = _g1h->ref_processor_stw();
G1ParScanThreadState pss(_g1h, worker_id, rp);
- G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
-
- pss.set_evac_failure_closure(&evac_failure_cl);
bool only_young = _g1h->collector_state()->gcs_are_young();
@@ -5269,9 +5175,6 @@
G1STWIsAliveClosure is_alive(_g1h);
G1ParScanThreadState pss(_g1h, worker_id, NULL);
- G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-
- pss.set_evac_failure_closure(&evac_failure_cl);
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL);
@@ -5368,10 +5271,6 @@
HandleMark hm;
G1ParScanThreadState pss(_g1h, worker_id, NULL);
- G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL);
-
- pss.set_evac_failure_closure(&evac_failure_cl);
-
assert(pss.queue_is_empty(), "both queue and overflow should be empty");
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL);
@@ -5476,15 +5375,11 @@
// Use only a single queue for this PSS.
G1ParScanThreadState pss(this, 0, NULL);
+ assert(pss.queue_is_empty(), "pre-condition");
// We do not embed a reference processor in the copying/scanning
// closures while we're actually processing the discovered
// reference objects.
- G1ParScanHeapEvacFailureClosure evac_failure_cl(this, &pss, NULL);
-
- pss.set_evac_failure_closure(&evac_failure_cl);
-
- assert(pss.queue_is_empty(), "pre-condition");
G1ParScanExtRootClosure only_copy_non_heap_cl(this, &pss, NULL);
@@ -5590,8 +5485,6 @@
const uint n_workers = workers()->active_workers();
- init_for_evac_failure(NULL);
-
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
double start_par_time_sec = os::elapsedTime();
double end_par_time_sec;
@@ -5655,8 +5548,6 @@
purge_code_root_memory();
- finalize_for_evac_failure();
-
if (evacuation_failed()) {
remove_self_forwarding_pointers();
@@ -5745,7 +5636,7 @@
}
void G1CollectedHeap::decrement_summary_bytes(size_t bytes) {
- _allocator->decrease_used(bytes);
+ decrease_used(bytes);
}
class G1ParCleanupCTTask : public AbstractGangTask {
@@ -6395,6 +6286,21 @@
_hrm.remove_all_free_regions();
}
+void G1CollectedHeap::increase_used(size_t bytes) {
+ _summary_bytes_used += bytes;
+}
+
+void G1CollectedHeap::decrease_used(size_t bytes) {
+ assert(_summary_bytes_used >= bytes,
+ err_msg("invariant: _summary_bytes_used: " SIZE_FORMAT " should be >= bytes: " SIZE_FORMAT,
+ _summary_bytes_used, bytes));
+ _summary_bytes_used -= bytes;
+}
+
+void G1CollectedHeap::set_used(size_t bytes) {
+ _summary_bytes_used = bytes;
+}
+
class RebuildRegionSetsClosure : public HeapRegionClosure {
private:
bool _free_list_only;
@@ -6463,15 +6369,15 @@
heap_region_iterate(&cl);
if (!free_list_only) {
- _allocator->set_used(cl.total_used());
+ set_used(cl.total_used());
if (_archive_allocator != NULL) {
_archive_allocator->clear_used();
}
}
- assert(_allocator->used_unlocked() == recalculate_used(),
- err_msg("inconsistent _allocator->used_unlocked(), "
+ assert(used_unlocked() == recalculate_used(),
+ err_msg("inconsistent used_unlocked(), "
"value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT,
- _allocator->used_unlocked(), recalculate_used()));
+ used_unlocked(), recalculate_used()));
}
void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) {
@@ -6511,7 +6417,7 @@
assert(alloc_region->is_eden(), "all mutator alloc regions should be eden");
g1_policy()->add_region_to_incremental_cset_lhs(alloc_region);
- _allocator->increase_used(allocated_bytes);
+ increase_used(allocated_bytes);
_hr_printer.retire(alloc_region);
// We update the eden sizes here, when the region is retired,
// instead of when it's allocated, since this is the point that its
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -251,6 +251,15 @@
// Class that handles the different kinds of allocations.
G1Allocator* _allocator;
+ // Outside of GC pauses, the number of bytes used in all regions other
+ // than the current allocation region(s).
+ size_t _summary_bytes_used;
+
+ void increase_used(size_t bytes);
+ void decrease_used(size_t bytes);
+
+ void set_used(size_t bytes);
+
// Class that handles archive allocation ranges.
G1ArchiveAllocator* _archive_allocator;
@@ -858,44 +867,27 @@
// forwarding pointers to themselves. Reset them.
void remove_self_forwarding_pointers();
- // Together, these store an object with a preserved mark, and its mark value.
- Stack<oop, mtGC> _objs_with_preserved_marks;
- Stack<markOop, mtGC> _preserved_marks_of_objs;
+ struct OopAndMarkOop {
+ private:
+ oop _o;
+ markOop _m;
+ public:
+ OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) {
+ }
+
+ void set_mark() {
+ _o->set_mark(_m);
+ }
+ };
+
+ typedef Stack<OopAndMarkOop,mtGC> OopAndMarkOopStack;
+ // Stores marks with the corresponding oop that we need to preserve during evacuation
+ // failure.
+ OopAndMarkOopStack* _preserved_objs;
// Preserve the mark of "obj", if necessary, in preparation for its mark
// word being overwritten with a self-forwarding-pointer.
- void preserve_mark_if_necessary(oop obj, markOop m);
-
- // The stack of evac-failure objects left to be scanned.
- GrowableArray<oop>* _evac_failure_scan_stack;
- // The closure to apply to evac-failure objects.
-
- OopsInHeapRegionClosure* _evac_failure_closure;
- // Set the field above.
- void
- set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_closure) {
- _evac_failure_closure = evac_failure_closure;
- }
-
- // Push "obj" on the scan stack.
- void push_on_evac_failure_scan_stack(oop obj);
- // Process scan stack entries until the stack is empty.
- void drain_evac_failure_scan_stack();
- // True iff an invocation of "drain_scan_stack" is in progress; to
- // prevent unnecessary recursion.
- bool _drain_in_progress;
-
- // Do any necessary initialization for evacuation-failure handling.
- // "cl" is the closure that will be used to process evac-failure
- // objects.
- void init_for_evac_failure(OopsInHeapRegionClosure* cl);
- // Do any necessary cleanup for evacuation-failure handling data
- // structures.
- void finalize_for_evac_failure();
-
- // An attempt to evacuate "obj" has failed; take necessary steps.
- oop handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop obj);
- void handle_evacuation_failure_common(oop obj, markOop m);
+ void preserve_mark_during_evac_failure(uint queue, oop obj, markOop m);
#ifndef PRODUCT
// Support for forcing evacuation failures. Analogous to
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -111,7 +111,6 @@
enum G1Barrier {
G1BarrierNone,
- G1BarrierEvac,
G1BarrierKlass
};
@@ -148,8 +147,6 @@
// We use a separate closure to handle references during evacuation
// failure processing.
-typedef G1ParCopyClosure<G1BarrierEvac, G1MarkNone> G1ParScanHeapEvacFailureClosure;
-
class FilterIntoCSClosure: public ExtendedOopClosure {
G1CollectedHeap* _g1;
OopClosure* _oc;
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -144,8 +144,6 @@
#endif // ASSERT
void G1ParScanThreadState::trim_queue() {
- assert(_evac_failure_cl != NULL, "not set");
-
StarTask ref;
do {
// Drain the overflow stack first, so other threads can steal.
@@ -222,7 +220,7 @@
if (obj_ptr == NULL) {
// This will either forward-to-self, or detect that someone else has
// installed a forwarding pointer.
- return _g1h->handle_evacuation_failure_par(this, old);
+ return handle_evacuation_failure_par(old, old_mark);
}
}
}
@@ -236,7 +234,7 @@
// Doing this after all the allocation attempts also tests the
// undo_allocation() method too.
_g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
- return _g1h->handle_evacuation_failure_par(this, old);
+ return handle_evacuation_failure_par(old, old_mark);
}
#endif // !PRODUCT
@@ -301,3 +299,36 @@
return forward_ptr;
}
}
+
+oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
+ assert(_g1h->obj_in_cs(old),
+ err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));
+
+ oop forward_ptr = old->forward_to_atomic(old);
+ if (forward_ptr == NULL) {
+ // Forward-to-self succeeded. We are the "owner" of the object.
+ HeapRegion* r = _g1h->heap_region_containing(old);
+
+ if (!r->evacuation_failed()) {
+ r->set_evacuation_failed(true);
+ _g1h->hr_printer()->evac_failure(r);
+ }
+
+ _g1h->preserve_mark_during_evac_failure(_queue_num, old, m);
+
+ _scanner.set_region(r);
+ old->oop_iterate_backwards(&_scanner);
+
+ return old;
+ } else {
+ // Forward-to-self failed. Either someone else managed to allocate
+ // space for this object (old != forward_ptr) or they beat us in
+ // self-forwarding it (old == forward_ptr).
+ assert(old == forward_ptr || !_g1h->obj_in_cs(forward_ptr),
+ err_msg("Object " PTR_FORMAT " forwarded to: " PTR_FORMAT " "
+ "should not be in the CSet",
+ p2i(old), p2i(forward_ptr)));
+ return forward_ptr;
+ }
+}
+
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -54,8 +54,6 @@
uint _tenuring_threshold;
G1ParScanClosure _scanner;
- OopsInHeapRegionClosure* _evac_failure_cl;
-
int _hash_seed;
uint _queue_num;
@@ -114,12 +112,6 @@
}
}
- void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
- _evac_failure_cl = evac_failure_cl;
- }
-
- OopsInHeapRegionClosure* evac_failure_closure() { return _evac_failure_cl; }
-
int* hash_seed() { return &_hash_seed; }
uint queue_num() { return _queue_num; }
@@ -211,6 +203,9 @@
void trim_queue();
inline void steal_and_trim_queue(RefToScanQueueSet *task_queues);
+
+ // An attempt to evacuate "obj" has failed; take necessary steps.
+ oop handle_evacuation_failure_par(oop obj, markOop m);
};
#endif // SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_HPP
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -252,12 +252,12 @@
"Percentage (0-100) of the heap size to use as default " \
" maximum young gen size.") \
range(0, 100) \
- constraint(G1MaxNewSizePercentConstraintFunc) \
+ constraint(G1MaxNewSizePercentConstraintFunc,AfterErgo) \
\
experimental(uintx, G1NewSizePercent, 5, \
"Percentage (0-100) of the heap size to use as default " \
"minimum young gen size.") \
- constraint(G1NewSizePercentConstraintFunc) \
+ constraint(G1NewSizePercentConstraintFunc,AfterErgo) \
\
experimental(uintx, G1MixedGCLiveThresholdPercent, 85, \
"Threshold for regions to be considered for inclusion in the " \
--- a/hotspot/src/share/vm/gc/g1/vmStructs_g1.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/vmStructs_g1.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -45,13 +45,11 @@
nonstatic_field(HeapRegionManager, _regions, G1HeapRegionTable) \
nonstatic_field(HeapRegionManager, _num_committed, uint) \
\
- nonstatic_field(G1Allocator, _summary_bytes_used, size_t) \
- \
+ nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \
nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager) \
nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \
nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \
nonstatic_field(G1CollectedHeap, _humongous_set, HeapRegionSetBase) \
- nonstatic_field(G1CollectedHeap, _allocator, G1Allocator*) \
\
nonstatic_field(G1MonitoringSupport, _eden_committed, size_t) \
nonstatic_field(G1MonitoringSupport, _eden_used, size_t) \
@@ -78,12 +76,10 @@
declare_toplevel_type(HeapRegionSetBase) \
declare_toplevel_type(HeapRegionSetCount) \
declare_toplevel_type(G1MonitoringSupport) \
- declare_toplevel_type(G1Allocator) \
\
declare_toplevel_type(G1CollectedHeap*) \
declare_toplevel_type(HeapRegion*) \
declare_toplevel_type(G1MonitoringSupport*) \
- declare_toplevel_type(G1Allocator*) \
#endif // SHARE_VM_GC_G1_VMSTRUCTS_G1_HPP
--- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -40,7 +40,6 @@
PSYoungGen* _young_gen;
CardTableExtension* _card_table;
HeapWord* _unmarked_addr;
- jbyte* _unmarked_card;
protected:
template <class T> void do_oop_work(T* p) {
@@ -50,7 +49,6 @@
// Don't overwrite the first missing card mark
if (_unmarked_addr == NULL) {
_unmarked_addr = (HeapWord*)p;
- _unmarked_card = _card_table->byte_for(p);
}
}
}
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -623,7 +623,7 @@
{
// DefNew needs to run with n_threads == 0, to make sure the serial
// version of the card table scanning code is used.
- // See: CardTableModRefBS::non_clean_card_iterate_possibly_parallel.
+ // See: CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel.
StrongRootsScope srs(0);
gch->gen_process_roots(&srs,
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -24,22 +24,12 @@
#include "precompiled.hpp"
#include "gc/shared/cardTableModRefBS.inline.hpp"
-#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/space.hpp"
#include "gc/shared/space.inline.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/universe.hpp"
#include "memory/virtualspace.hpp"
-#include "runtime/java.hpp"
-#include "runtime/mutexLocker.hpp"
#include "services/memTracker.hpp"
#include "utilities/macros.hpp"
-#ifdef COMPILER1
-#include "c1/c1_LIR.hpp"
-#include "c1/c1_LIRGenerator.hpp"
-#endif
// This kind of "BarrierSet" allows a "CollectedHeap" to detect and
// enumerate ref fields that have been modified (since the last
@@ -68,12 +58,7 @@
_committed(NULL),
_cur_covered_regions(0),
_byte_map(NULL),
- byte_map_base(NULL),
- // LNC functionality
- _lowest_non_clean(NULL),
- _lowest_non_clean_chunk_size(NULL),
- _lowest_non_clean_base_chunk_index(NULL),
- _last_LNC_resizing_collection(NULL)
+ byte_map_base(NULL)
{
assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary");
assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary");
@@ -130,25 +115,6 @@
!ExecMem, "card table last card");
*guard_card = last_card;
- _lowest_non_clean =
- NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
- _lowest_non_clean_chunk_size =
- NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
- _lowest_non_clean_base_chunk_index =
- NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
- _last_LNC_resizing_collection =
- NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
- if (_lowest_non_clean == NULL
- || _lowest_non_clean_chunk_size == NULL
- || _lowest_non_clean_base_chunk_index == NULL
- || _last_LNC_resizing_collection == NULL)
- vm_exit_during_initialization("couldn't allocate an LNC array.");
- for (int i = 0; i < _max_covered_regions; i++) {
- _lowest_non_clean[i] = NULL;
- _lowest_non_clean_chunk_size[i] = 0;
- _last_LNC_resizing_collection[i] = -1;
- }
-
if (TraceCardTableModRefBS) {
gclog_or_tty->print_cr("CardTableModRefBS::CardTableModRefBS: ");
gclog_or_tty->print_cr(" "
@@ -171,22 +137,6 @@
delete[] _committed;
_committed = NULL;
}
- if (_lowest_non_clean) {
- FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
- _lowest_non_clean = NULL;
- }
- if (_lowest_non_clean_chunk_size) {
- FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
- _lowest_non_clean_chunk_size = NULL;
- }
- if (_lowest_non_clean_base_chunk_index) {
- FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
- _lowest_non_clean_base_chunk_index = NULL;
- }
- if (_last_LNC_resizing_collection) {
- FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
- _last_LNC_resizing_collection = NULL;
- }
}
int CardTableModRefBS::find_covering_region_by_base(HeapWord* base) {
@@ -437,32 +387,6 @@
}
-void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
- MemRegion mr,
- OopsInGenClosure* cl,
- CardTableRS* ct,
- uint n_threads) {
- if (!mr.is_empty()) {
- if (n_threads > 0) {
-#if INCLUDE_ALL_GCS
- non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
-#else // INCLUDE_ALL_GCS
- fatal("Parallel gc not supported here.");
-#endif // INCLUDE_ALL_GCS
- } else {
- // clear_cl finds contiguous dirty ranges of cards to process and clear.
-
- // This is the single-threaded version used by DefNew.
- const bool parallel = false;
-
- DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
- ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
-
- clear_cl.do_MemRegion(mr);
- }
- }
-}
-
void CardTableModRefBS::dirty_MemRegion(MemRegion mr) {
assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" );
@@ -623,15 +547,3 @@
p2i(_byte_map), p2i(_byte_map + _byte_map_size), p2i(byte_map_base));
}
-bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
- return
- CardTableModRefBS::card_will_be_scanned(cv) ||
- _rs->is_prev_nonclean_card_val(cv);
-};
-
-bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
- return
- cv != clean_card &&
- (CardTableModRefBS::card_may_have_been_dirty(cv) ||
- CardTableRS::youngergen_may_have_been_dirty(cv));
-};
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -40,23 +40,9 @@
// Closures used to scan dirty cards should take these
// considerations into account.
-class Generation;
-class OopsInGenClosure;
-class DirtyCardToOopClosure;
-class ClearNoncleanCardWrapper;
-class CardTableRS;
-
class CardTableModRefBS: public ModRefBarrierSet {
// Some classes get to look at some private stuff.
- friend class BytecodeInterpreter;
friend class VMStructs;
- friend class CardTableRS;
- friend class CheckForUnmarkedOops; // Needs access to raw card bytes.
- friend class SharkBuilder;
-#ifndef PRODUCT
- // For debugging.
- friend class GuaranteeNotModClosure;
-#endif
protected:
enum CardValues {
@@ -75,24 +61,6 @@
// a word's worth (row) of clean card values
static const intptr_t clean_card_row = (intptr_t)(-1);
- // dirty and precleaned are equivalent wrt younger_refs_iter.
- static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
- return cv == dirty_card || cv == precleaned_card;
- }
-
- // Returns "true" iff the value "cv" will cause the card containing it
- // to be scanned in the current traversal. May be overridden by
- // subtypes.
- virtual bool card_will_be_scanned(jbyte cv) {
- return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
- }
-
- // Returns "true" iff the value "cv" may have represented a dirty card at
- // some point.
- virtual bool card_may_have_been_dirty(jbyte cv) {
- return card_is_dirty_wrt_gen_iter(cv);
- }
-
// The declaration order of these const fields is important; see the
// constructor before changing.
const MemRegion _whole_heap; // the region covered by the card table
@@ -174,20 +142,6 @@
return byte_for(p) + 1;
}
- // Iterate over the portion of the card-table which covers the given
- // region mr in the given space and apply cl to any dirty sub-regions
- // of mr. Clears the dirty cards as they are processed.
- void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
- OopsInGenClosure* cl, CardTableRS* ct,
- uint n_threads);
-
- private:
- // Work method used to implement non_clean_card_iterate_possibly_parallel()
- // above in the parallel case.
- void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
- OopsInGenClosure* cl, CardTableRS* ct,
- uint n_threads);
-
protected:
// Dirty the bytes corresponding to "mr" (not all of which must be
// covered.)
@@ -197,65 +151,6 @@
// all of which must be covered.)
void clear_MemRegion(MemRegion mr);
- // *** Support for parallel card scanning.
-
- // This is an array, one element per covered region of the card table.
- // Each entry is itself an array, with one element per chunk in the
- // covered region. Each entry of these arrays is the lowest non-clean
- // card of the corresponding chunk containing part of an object from the
- // previous chunk, or else NULL.
- typedef jbyte* CardPtr;
- typedef CardPtr* CardArr;
- CardArr* _lowest_non_clean;
- size_t* _lowest_non_clean_chunk_size;
- uintptr_t* _lowest_non_clean_base_chunk_index;
- int* _last_LNC_resizing_collection;
-
- // Initializes "lowest_non_clean" to point to the array for the region
- // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
- // index of the corresponding to the first element of that array.
- // Ensures that these arrays are of sufficient size, allocating if necessary.
- // May be called by several threads concurrently.
- void get_LNC_array_for_space(Space* sp,
- jbyte**& lowest_non_clean,
- uintptr_t& lowest_non_clean_base_chunk_index,
- size_t& lowest_non_clean_chunk_size);
-
- // Returns the number of chunks necessary to cover "mr".
- size_t chunks_to_cover(MemRegion mr) {
- return (size_t)(addr_to_chunk_index(mr.last()) -
- addr_to_chunk_index(mr.start()) + 1);
- }
-
- // Returns the index of the chunk in a stride which
- // covers the given address.
- uintptr_t addr_to_chunk_index(const void* addr) {
- uintptr_t card = (uintptr_t) byte_for(addr);
- return card / ParGCCardsPerStrideChunk;
- }
-
- // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
- // to the cards in the stride (of n_strides) within the given space.
- void process_stride(Space* sp,
- MemRegion used,
- jint stride, int n_strides,
- OopsInGenClosure* cl,
- CardTableRS* ct,
- jbyte** lowest_non_clean,
- uintptr_t lowest_non_clean_base_chunk_index,
- size_t lowest_non_clean_chunk_size);
-
- // Makes sure that chunk boundaries are handled appropriately, by
- // adjusting the min_done of dcto_cl, and by using a special card-table
- // value to indicate how min_done should be set.
- void process_chunk_boundaries(Space* sp,
- DirtyCardToOopClosure* dcto_cl,
- MemRegion chunk_mr,
- MemRegion used,
- jbyte** lowest_non_clean,
- uintptr_t lowest_non_clean_base_chunk_index,
- size_t lowest_non_clean_chunk_size);
-
public:
// Constants
enum SomePublicConstants {
@@ -436,34 +331,5 @@
static const BarrierSet::Name value = BarrierSet::CardTableModRef;
};
-class CardTableRS;
-
-// A specialization for the CardTableRS gen rem set.
-class CardTableModRefBSForCTRS: public CardTableModRefBS {
- CardTableRS* _rs;
-protected:
- bool card_will_be_scanned(jbyte cv);
- bool card_may_have_been_dirty(jbyte cv);
-public:
- CardTableModRefBSForCTRS(MemRegion whole_heap) :
- CardTableModRefBS(
- whole_heap,
- // Concrete tag should be BarrierSet::CardTableForRS.
- // That will presently break things in a bunch of places though.
- // The concrete tag is used as a dispatch key in many places, and
- // CardTableForRS does not correctly dispatch in some of those
- // uses. This will be addressed as part of a reorganization of the
- // BarrierSet hierarchy.
- BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS))
- {}
-
- void set_CTRS(CardTableRS* rs) { _rs = rs; }
-};
-
-template<>
-struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
- static const BarrierSet::Name value = BarrierSet::CardTableForRS;
-};
-
#endif // SHARE_VM_GC_SHARED_CARDTABLEMODREFBS_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/cardTableModRefBS.inline.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "memory/allocation.inline.hpp"
+#include "gc/shared/space.inline.hpp"
+
+CardTableModRefBSForCTRS::CardTableModRefBSForCTRS(MemRegion whole_heap) :
+ CardTableModRefBS(
+ whole_heap,
+ // Concrete tag should be BarrierSet::CardTableForRS.
+ // That will presently break things in a bunch of places though.
+ // The concrete tag is used as a dispatch key in many places, and
+ // CardTableForRS does not correctly dispatch in some of those
+ // uses. This will be addressed as part of a reorganization of the
+ // BarrierSet hierarchy.
+ BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS)),
+ // LNC functionality
+ _lowest_non_clean(NULL),
+ _lowest_non_clean_chunk_size(NULL),
+ _lowest_non_clean_base_chunk_index(NULL),
+ _last_LNC_resizing_collection(NULL)
+{ }
+
+void CardTableModRefBSForCTRS::initialize() {
+ CardTableModRefBS::initialize();
+ _lowest_non_clean =
+ NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
+ _lowest_non_clean_chunk_size =
+ NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
+ _lowest_non_clean_base_chunk_index =
+ NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
+ _last_LNC_resizing_collection =
+ NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
+ if (_lowest_non_clean == NULL
+ || _lowest_non_clean_chunk_size == NULL
+ || _lowest_non_clean_base_chunk_index == NULL
+ || _last_LNC_resizing_collection == NULL)
+ vm_exit_during_initialization("couldn't allocate an LNC array.");
+ for (int i = 0; i < _max_covered_regions; i++) {
+ _lowest_non_clean[i] = NULL;
+ _lowest_non_clean_chunk_size[i] = 0;
+ _last_LNC_resizing_collection[i] = -1;
+ }
+}
+
+CardTableModRefBSForCTRS::~CardTableModRefBSForCTRS() {
+ if (_lowest_non_clean) {
+ FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
+ _lowest_non_clean = NULL;
+ }
+ if (_lowest_non_clean_chunk_size) {
+ FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
+ _lowest_non_clean_chunk_size = NULL;
+ }
+ if (_lowest_non_clean_base_chunk_index) {
+ FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
+ _lowest_non_clean_base_chunk_index = NULL;
+ }
+ if (_last_LNC_resizing_collection) {
+ FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
+ _last_LNC_resizing_collection = NULL;
+ }
+}
+
+bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
+ return
+ card_is_dirty_wrt_gen_iter(cv) ||
+ _rs->is_prev_nonclean_card_val(cv);
+}
+
+bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
+ return
+ cv != clean_card &&
+ (card_is_dirty_wrt_gen_iter(cv) ||
+ CardTableRS::youngergen_may_have_been_dirty(cv));
+}
+
+void CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel(
+ Space* sp,
+ MemRegion mr,
+ OopsInGenClosure* cl,
+ CardTableRS* ct,
+ uint n_threads)
+{
+ if (!mr.is_empty()) {
+ if (n_threads > 0) {
+#if INCLUDE_ALL_GCS
+ non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
+#else // INCLUDE_ALL_GCS
+ fatal("Parallel gc not supported here.");
+#endif // INCLUDE_ALL_GCS
+ } else {
+ // clear_cl finds contiguous dirty ranges of cards to process and clear.
+
+ // This is the single-threaded version used by DefNew.
+ const bool parallel = false;
+
+ DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
+ ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
+
+ clear_cl.do_MemRegion(mr);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+#define SHARE_VM_GC_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+
+#include "gc/shared/cardTableModRefBS.hpp"
+
+class CardTableRS;
+class DirtyCardToOopClosure;
+class OopsInGenClosure;
+
+// A specialization for the CardTableRS gen rem set.
+class CardTableModRefBSForCTRS: public CardTableModRefBS {
+ friend class CardTableRS;
+
+public:
+ CardTableModRefBSForCTRS(MemRegion whole_heap);
+ ~CardTableModRefBSForCTRS();
+
+ virtual void initialize();
+
+ void set_CTRS(CardTableRS* rs) { _rs = rs; }
+
+private:
+ CardTableRS* _rs;
+
+ // *** Support for parallel card scanning.
+
+ // dirty and precleaned are equivalent wrt younger_refs_iter.
+ static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
+ return cv == dirty_card || cv == precleaned_card;
+ }
+
+ // Returns "true" iff the value "cv" will cause the card containing it
+ // to be scanned in the current traversal. May be overridden by
+ // subtypes.
+ bool card_will_be_scanned(jbyte cv);
+
+ // Returns "true" iff the value "cv" may have represented a dirty card at
+ // some point.
+ bool card_may_have_been_dirty(jbyte cv);
+
+ // Iterate over the portion of the card-table which covers the given
+ // region mr in the given space and apply cl to any dirty sub-regions
+ // of mr. Clears the dirty cards as they are processed.
+ void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
+ OopsInGenClosure* cl, CardTableRS* ct,
+ uint n_threads);
+
+ // Work method used to implement non_clean_card_iterate_possibly_parallel()
+ // above in the parallel case.
+ void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+ OopsInGenClosure* cl, CardTableRS* ct,
+ uint n_threads);
+
+ // This is an array, one element per covered region of the card table.
+ // Each entry is itself an array, with one element per chunk in the
+ // covered region. Each entry of these arrays is the lowest non-clean
+ // card of the corresponding chunk containing part of an object from the
+ // previous chunk, or else NULL.
+ typedef jbyte* CardPtr;
+ typedef CardPtr* CardArr;
+ CardArr* _lowest_non_clean;
+ size_t* _lowest_non_clean_chunk_size;
+ uintptr_t* _lowest_non_clean_base_chunk_index;
+ int* _last_LNC_resizing_collection;
+
+ // Initializes "lowest_non_clean" to point to the array for the region
+ // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
+ // index of the corresponding to the first element of that array.
+ // Ensures that these arrays are of sufficient size, allocating if necessary.
+ // May be called by several threads concurrently.
+ void get_LNC_array_for_space(Space* sp,
+ jbyte**& lowest_non_clean,
+ uintptr_t& lowest_non_clean_base_chunk_index,
+ size_t& lowest_non_clean_chunk_size);
+
+ // Returns the number of chunks necessary to cover "mr".
+ size_t chunks_to_cover(MemRegion mr) {
+ return (size_t)(addr_to_chunk_index(mr.last()) -
+ addr_to_chunk_index(mr.start()) + 1);
+ }
+
+ // Returns the index of the chunk in a stride which
+ // covers the given address.
+ uintptr_t addr_to_chunk_index(const void* addr) {
+ uintptr_t card = (uintptr_t) byte_for(addr);
+ return card / ParGCCardsPerStrideChunk;
+ }
+
+ // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
+ // to the cards in the stride (of n_strides) within the given space.
+ void process_stride(Space* sp,
+ MemRegion used,
+ jint stride, int n_strides,
+ OopsInGenClosure* cl,
+ CardTableRS* ct,
+ jbyte** lowest_non_clean,
+ uintptr_t lowest_non_clean_base_chunk_index,
+ size_t lowest_non_clean_chunk_size);
+
+ // Makes sure that chunk boundaries are handled appropriately, by
+ // adjusting the min_done of dcto_cl, and by using a special card-table
+ // value to indicate how min_done should be set.
+ void process_chunk_boundaries(Space* sp,
+ DirtyCardToOopClosure* dcto_cl,
+ MemRegion chunk_mr,
+ MemRegion used,
+ jbyte** lowest_non_clean,
+ uintptr_t lowest_non_clean_base_chunk_index,
+ size_t lowest_non_clean_chunk_size);
+
+};
+
+template<>
+struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
+ static const BarrierSet::Name value = BarrierSet::CardTableForRS;
+};
+
+#endif // include guard
+
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -240,7 +240,7 @@
// cur-younger-gen ==> cur_younger_gen
// cur_youngergen_and_prev_nonclean_card ==> no change.
void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
- jbyte* entry = ct_bs()->byte_for(field);
+ jbyte* entry = _ct_bs->byte_for(field);
do {
jbyte entry_val = *entry;
// We put this first because it's probably the most common case.
@@ -398,10 +398,10 @@
jbyte* cur_entry = byte_for(used.start());
jbyte* limit = byte_after(used.last());
while (cur_entry < limit) {
- if (*cur_entry == CardTableModRefBS::clean_card) {
+ if (*cur_entry == clean_card_val()) {
jbyte* first_dirty = cur_entry+1;
while (first_dirty < limit &&
- *first_dirty == CardTableModRefBS::clean_card) {
+ *first_dirty == clean_card_val()) {
first_dirty++;
}
// If the first object is a regular object, and it has a
@@ -418,7 +418,7 @@
!boundary_obj->is_typeArray()) {
guarantee(cur_entry > byte_for(used.start()),
"else boundary would be boundary_block");
- if (*byte_for(boundary_block) != CardTableModRefBS::clean_card) {
+ if (*byte_for(boundary_block) != clean_card_val()) {
begin = boundary_block + s->block_size(boundary_block);
start_block = begin;
}
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -25,7 +25,7 @@
#ifndef SHARE_VM_GC_SHARED_CARDTABLERS_HPP
#define SHARE_VM_GC_SHARED_CARDTABLERS_HPP
-#include "gc/shared/cardTableModRefBS.hpp"
+#include "gc/shared/cardTableModRefBSForCTRS.hpp"
#include "gc/shared/genRemSet.hpp"
#include "memory/memRegion.hpp"
@@ -42,16 +42,16 @@
friend class ClearNoncleanCardWrapper;
static jbyte clean_card_val() {
- return CardTableModRefBS::clean_card;
+ return CardTableModRefBSForCTRS::clean_card;
}
static intptr_t clean_card_row() {
- return CardTableModRefBS::clean_card_row;
+ return CardTableModRefBSForCTRS::clean_card_row;
}
static bool
card_is_dirty_wrt_gen_iter(jbyte cv) {
- return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
+ return CardTableModRefBSForCTRS::card_is_dirty_wrt_gen_iter(cv);
}
CardTableModRefBSForCTRS* _ct_bs;
@@ -61,17 +61,17 @@
void verify_space(Space* s, HeapWord* gen_start);
enum ExtendedCardValue {
- youngergen_card = CardTableModRefBS::CT_MR_BS_last_reserved + 1,
+ youngergen_card = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 1,
// These are for parallel collection.
// There are three P (parallel) youngergen card values. In general, this
// needs to be more than the number of generations (including the perm
// gen) that might have younger_refs_do invoked on them separately. So
// if we add more gens, we have to add more values.
- youngergenP1_card = CardTableModRefBS::CT_MR_BS_last_reserved + 2,
- youngergenP2_card = CardTableModRefBS::CT_MR_BS_last_reserved + 3,
- youngergenP3_card = CardTableModRefBS::CT_MR_BS_last_reserved + 4,
+ youngergenP1_card = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 2,
+ youngergenP2_card = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 3,
+ youngergenP3_card = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 4,
cur_youngergen_and_prev_nonclean_card =
- CardTableModRefBS::CT_MR_BS_last_reserved + 5
+ CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 5
};
// An array that contains, for each generation, the card table value last
@@ -107,7 +107,7 @@
// *** GenRemSet functions.
CardTableRS* as_CardTableRS() { return this; }
- CardTableModRefBS* ct_bs() { return _ct_bs; }
+ CardTableModRefBSForCTRS* ct_bs() { return _ct_bs; }
// Override.
void prepare_for_younger_refs_iterate(bool parallel);
@@ -147,7 +147,7 @@
void invalidate_or_clear(Generation* old_gen);
static uintx ct_max_alignment_constraint() {
- return CardTableModRefBS::ct_max_alignment_constraint();
+ return CardTableModRefBSForCTRS::ct_max_alignment_constraint();
}
jbyte* byte_for(void* p) { return _ct_bs->byte_for(p); }
--- a/hotspot/src/share/vm/gc/shared/taskqueue.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -295,8 +295,9 @@
// Delete any resource associated with the queue.
~GenericTaskQueue();
- // apply the closure to all elements in the task queue
- void oops_do(OopClosure* f);
+ // Apply fn to each element in the task queue. The queue must not
+ // be modified while iterating.
+ template<typename Fn> void iterate(Fn fn);
private:
// Element array.
--- a/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -259,20 +259,14 @@
}
template<class E, MEMFLAGS F, unsigned int N>
-inline void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
- // tty->print_cr("START OopTaskQueue::oops_do");
+template<class Fn>
+inline void GenericTaskQueue<E, F, N>::iterate(Fn fn) {
uint iters = size();
uint index = _bottom;
for (uint i = 0; i < iters; ++i) {
index = decrement_index(index);
- // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T,
- // index, &_elems[index], _elems[index]);
- E* t = (E*)&_elems[index]; // cast away volatility
- oop* p = (oop*)t;
- assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
- f->do_oop(p);
+ fn(const_cast<E&>(_elems[index])); // cast away volatility
}
- // tty->print_cr("END OopTaskQueue::oops_do");
}
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -56,6 +56,7 @@
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.inline.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
@@ -656,6 +657,11 @@
Metaspace::global_initialize();
+ // Checks 'AfterMemoryInit' constraints.
+ if (!CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::AfterMemoryInit)) {
+ return JNI_EINVAL;
+ }
+
// Create memory for metadata. Must be after initializing heap for
// DumpSharedSpaces.
ClassLoaderData::init_null_class_loader_data();
--- a/hotspot/src/share/vm/oops/oop.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/oops/oop.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -200,7 +200,6 @@
// Access to fields in a instanceOop through these methods.
oop obj_field(int offset) const;
- volatile oop obj_field_volatile(int offset) const;
void obj_field_put(int offset, oop value);
void obj_field_put_raw(int offset, oop value);
void obj_field_put_volatile(int offset, oop value);
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -284,11 +284,7 @@
load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) :
load_decode_heap_oop(obj_field_addr<oop>(offset));
}
-inline volatile oop oopDesc::obj_field_volatile(int offset) const {
- volatile oop value = obj_field(offset);
- OrderAccess::acquire();
- return value;
-}
+
inline void oopDesc::obj_field_put(int offset, oop value) {
UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) :
oop_store(obj_field_addr<oop>(offset), value);
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -659,7 +659,7 @@
"0 for no aliasing, 1 for oop/field/static/array split, " \
"2 for class split, 3 for unique instances") \
range(0, 3) \
- constraint(AliasLevelConstraintFunc) \
+ constraint(AliasLevelConstraintFunc,AfterErgo) \
\
develop(bool, VerifyAliases, false, \
"perform extra checks on the results of alias analysis") \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -79,7 +79,6 @@
return OptoRuntime::generate(thread->env());
}
-
void C2Compiler::initialize() {
// The first compiler thread that gets here will initialize the
// small amount of global state (and runtime stubs) that C2 needs.
@@ -154,11 +153,361 @@
}
}
-
void C2Compiler::print_timers() {
Compile::print_timers();
}
+bool C2Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+ // Assume a non-virtual dispatch. A virtual dispatch is
+ // possible for only a limited set of available intrinsics whereas
+ // a non-virtual dispatch is possible for all available intrinsics.
+ return is_intrinsic_supported(method, false) &&
+ !is_intrinsic_disabled_by_flag(method, compilation_context);
+}
+
+bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
+ vmIntrinsics::ID id = method->intrinsic_id();
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ if (id < vmIntrinsics::FIRST_ID || id >= vmIntrinsics::LAST_COMPILER_INLINE) {
+ return false;
+ }
+
+ // Only Object.hashCode and Object.clone intrinsics implement also a virtual
+ // dispatch because calling both methods is expensive but both methods are
+ // frequently overridden. All other intrinsics implement only a non-virtual
+ // dispatch.
+ if (is_virtual) {
+ switch (id) {
+ case vmIntrinsics::_hashCode:
+ case vmIntrinsics::_clone:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ switch (id) {
+ case vmIntrinsics::_compareTo:
+ if (!Matcher::match_rule_supported(Op_StrComp)) return false;
+ break;
+ case vmIntrinsics::_equals:
+ if (!Matcher::match_rule_supported(Op_StrEquals)) return false;
+ break;
+ case vmIntrinsics::_equalsC:
+ if (!Matcher::match_rule_supported(Op_AryEq)) return false;
+ break;
+ case vmIntrinsics::_copyMemory:
+ if (StubRoutines::unsafe_arraycopy() == NULL) return false;
+ break;
+ case vmIntrinsics::_encodeISOArray:
+ if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false;
+ break;
+ case vmIntrinsics::_bitCount_i:
+ if (!Matcher::match_rule_supported(Op_PopCountI)) return false;
+ break;
+ case vmIntrinsics::_bitCount_l:
+ if (!Matcher::match_rule_supported(Op_PopCountL)) return false;
+ break;
+ case vmIntrinsics::_numberOfLeadingZeros_i:
+ if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false;
+ break;
+ case vmIntrinsics::_numberOfLeadingZeros_l:
+ if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false;
+ break;
+ case vmIntrinsics::_numberOfTrailingZeros_i:
+ if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false;
+ break;
+ case vmIntrinsics::_numberOfTrailingZeros_l:
+ if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false;
+ break;
+ case vmIntrinsics::_reverseBytes_c:
+ if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return false;
+ break;
+ case vmIntrinsics::_reverseBytes_s:
+ if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return false;
+ break;
+ case vmIntrinsics::_reverseBytes_i:
+ if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return false;
+ break;
+ case vmIntrinsics::_reverseBytes_l:
+ if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false;
+ break;
+ case vmIntrinsics::_compareAndSwapObject:
+#ifdef _LP64
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
+#endif
+ break;
+ case vmIntrinsics::_compareAndSwapLong:
+ if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false;
+ break;
+ case vmIntrinsics::_getAndAddInt:
+ if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false;
+ break;
+ case vmIntrinsics::_getAndAddLong:
+ if (!Matcher::match_rule_supported(Op_GetAndAddL)) return false;
+ break;
+ case vmIntrinsics::_getAndSetInt:
+ if (!Matcher::match_rule_supported(Op_GetAndSetI)) return false;
+ break;
+ case vmIntrinsics::_getAndSetLong:
+ if (!Matcher::match_rule_supported(Op_GetAndSetL)) return false;
+ break;
+ case vmIntrinsics::_getAndSetObject:
+#ifdef _LP64
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return false;
+ if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return false;
+ break;
+#else
+ if (!Matcher::match_rule_supported(Op_GetAndSetP)) return false;
+ break;
+#endif
+ case vmIntrinsics::_incrementExactI:
+ case vmIntrinsics::_addExactI:
+ if (!Matcher::match_rule_supported(Op_OverflowAddI)) return false;
+ break;
+ case vmIntrinsics::_incrementExactL:
+ case vmIntrinsics::_addExactL:
+ if (!Matcher::match_rule_supported(Op_OverflowAddL)) return false;
+ break;
+ case vmIntrinsics::_decrementExactI:
+ case vmIntrinsics::_subtractExactI:
+ if (!Matcher::match_rule_supported(Op_OverflowSubI)) return false;
+ break;
+ case vmIntrinsics::_decrementExactL:
+ case vmIntrinsics::_subtractExactL:
+ if (!Matcher::match_rule_supported(Op_OverflowSubL)) return false;
+ break;
+ case vmIntrinsics::_negateExactI:
+ if (!Matcher::match_rule_supported(Op_OverflowSubI)) return false;
+ break;
+ case vmIntrinsics::_negateExactL:
+ if (!Matcher::match_rule_supported(Op_OverflowSubL)) return false;
+ break;
+ case vmIntrinsics::_multiplyExactI:
+ if (!Matcher::match_rule_supported(Op_OverflowMulI)) return false;
+ break;
+ case vmIntrinsics::_multiplyExactL:
+ if (!Matcher::match_rule_supported(Op_OverflowMulL)) return false;
+ break;
+ case vmIntrinsics::_getCallerClass:
+ if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return false;
+ break;
+ case vmIntrinsics::_hashCode:
+ case vmIntrinsics::_identityHashCode:
+ case vmIntrinsics::_getClass:
+ case vmIntrinsics::_dsin:
+ case vmIntrinsics::_dcos:
+ case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dabs:
+ case vmIntrinsics::_datan2:
+ case vmIntrinsics::_dsqrt:
+ case vmIntrinsics::_dexp:
+ case vmIntrinsics::_dlog:
+ case vmIntrinsics::_dlog10:
+ case vmIntrinsics::_dpow:
+ case vmIntrinsics::_min:
+ case vmIntrinsics::_max:
+ case vmIntrinsics::_arraycopy:
+ case vmIntrinsics::_indexOf:
+ case vmIntrinsics::_getObject:
+ case vmIntrinsics::_getBoolean:
+ case vmIntrinsics::_getByte:
+ case vmIntrinsics::_getShort:
+ case vmIntrinsics::_getChar:
+ case vmIntrinsics::_getInt:
+ case vmIntrinsics::_getLong:
+ case vmIntrinsics::_getFloat:
+ case vmIntrinsics::_getDouble:
+ case vmIntrinsics::_putObject:
+ case vmIntrinsics::_putBoolean:
+ case vmIntrinsics::_putByte:
+ case vmIntrinsics::_putShort:
+ case vmIntrinsics::_putChar:
+ case vmIntrinsics::_putInt:
+ case vmIntrinsics::_putLong:
+ case vmIntrinsics::_putFloat:
+ case vmIntrinsics::_putDouble:
+ case vmIntrinsics::_getByte_raw:
+ case vmIntrinsics::_getShort_raw:
+ case vmIntrinsics::_getChar_raw:
+ case vmIntrinsics::_getInt_raw:
+ case vmIntrinsics::_getLong_raw:
+ case vmIntrinsics::_getFloat_raw:
+ case vmIntrinsics::_getDouble_raw:
+ case vmIntrinsics::_getAddress_raw:
+ case vmIntrinsics::_putByte_raw:
+ case vmIntrinsics::_putShort_raw:
+ case vmIntrinsics::_putChar_raw:
+ case vmIntrinsics::_putInt_raw:
+ case vmIntrinsics::_putLong_raw:
+ case vmIntrinsics::_putFloat_raw:
+ case vmIntrinsics::_putDouble_raw:
+ case vmIntrinsics::_putAddress_raw:
+ case vmIntrinsics::_getObjectVolatile:
+ case vmIntrinsics::_getBooleanVolatile:
+ case vmIntrinsics::_getByteVolatile:
+ case vmIntrinsics::_getShortVolatile:
+ case vmIntrinsics::_getCharVolatile:
+ case vmIntrinsics::_getIntVolatile:
+ case vmIntrinsics::_getLongVolatile:
+ case vmIntrinsics::_getFloatVolatile:
+ case vmIntrinsics::_getDoubleVolatile:
+ case vmIntrinsics::_putObjectVolatile:
+ case vmIntrinsics::_putBooleanVolatile:
+ case vmIntrinsics::_putByteVolatile:
+ case vmIntrinsics::_putShortVolatile:
+ case vmIntrinsics::_putCharVolatile:
+ case vmIntrinsics::_putIntVolatile:
+ case vmIntrinsics::_putLongVolatile:
+ case vmIntrinsics::_putFloatVolatile:
+ case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getShortUnaligned:
+ case vmIntrinsics::_getCharUnaligned:
+ case vmIntrinsics::_getIntUnaligned:
+ case vmIntrinsics::_getLongUnaligned:
+ case vmIntrinsics::_putShortUnaligned:
+ case vmIntrinsics::_putCharUnaligned:
+ case vmIntrinsics::_putIntUnaligned:
+ case vmIntrinsics::_putLongUnaligned:
+ case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_putOrderedObject:
+ case vmIntrinsics::_putOrderedInt:
+ case vmIntrinsics::_putOrderedLong:
+ case vmIntrinsics::_loadFence:
+ case vmIntrinsics::_storeFence:
+ case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_currentThread:
+ case vmIntrinsics::_isInterrupted:
+#ifdef TRACE_HAVE_INTRINSICS
+ case vmIntrinsics::_classID:
+ case vmIntrinsics::_threadID:
+ case vmIntrinsics::_counterTime:
+#endif
+ case vmIntrinsics::_currentTimeMillis:
+ case vmIntrinsics::_nanoTime:
+ case vmIntrinsics::_allocateInstance:
+ case vmIntrinsics::_newArray:
+ case vmIntrinsics::_getLength:
+ case vmIntrinsics::_copyOf:
+ case vmIntrinsics::_copyOfRange:
+ case vmIntrinsics::_clone:
+ case vmIntrinsics::_isAssignableFrom:
+ case vmIntrinsics::_isInstance:
+ case vmIntrinsics::_getModifiers:
+ case vmIntrinsics::_isInterface:
+ case vmIntrinsics::_isArray:
+ case vmIntrinsics::_isPrimitive:
+ case vmIntrinsics::_getSuperclass:
+ case vmIntrinsics::_getClassAccessFlags:
+ case vmIntrinsics::_floatToRawIntBits:
+ case vmIntrinsics::_floatToIntBits:
+ case vmIntrinsics::_intBitsToFloat:
+ case vmIntrinsics::_doubleToRawLongBits:
+ case vmIntrinsics::_doubleToLongBits:
+ case vmIntrinsics::_longBitsToDouble:
+ case vmIntrinsics::_Reference_get:
+ case vmIntrinsics::_Class_cast:
+ case vmIntrinsics::_aescrypt_encryptBlock:
+ case vmIntrinsics::_aescrypt_decryptBlock:
+ case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
+ case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
+ case vmIntrinsics::_sha_implCompress:
+ case vmIntrinsics::_sha2_implCompress:
+ case vmIntrinsics::_sha5_implCompress:
+ case vmIntrinsics::_digestBase_implCompressMB:
+ case vmIntrinsics::_multiplyToLen:
+ case vmIntrinsics::_squareToLen:
+ case vmIntrinsics::_mulAdd:
+ case vmIntrinsics::_montgomeryMultiply:
+ case vmIntrinsics::_montgomerySquare:
+ case vmIntrinsics::_ghash_processBlocks:
+ case vmIntrinsics::_updateCRC32:
+ case vmIntrinsics::_updateBytesCRC32:
+ case vmIntrinsics::_updateByteBufferCRC32:
+ case vmIntrinsics::_updateBytesCRC32C:
+ case vmIntrinsics::_updateDirectByteBufferCRC32C:
+ case vmIntrinsics::_profileBoolean:
+ case vmIntrinsics::_isCompileConstant:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool C2Compiler::is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context) {
+ vmIntrinsics::ID id = method->intrinsic_id();
+ assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+ if (vmIntrinsics::is_disabled_by_flags(method->intrinsic_id())) {
+ return true;
+ }
+
+ // Check if the intrinsic corresponding to 'method' has been disabled on
+ // the command line by using the DisableIntrinsic flag (either globally
+ // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
+ // for details).
+ // Usually, the compilation context is the caller of the method 'method'.
+ // The only case when for a non-recursive method 'method' the compilation context
+ // is not the caller of the 'method' (but it is the method itself) is
+ // java.lang.ref.Referene::get.
+ // For java.lang.ref.Reference::get, the intrinsic version is used
+ // instead of the C2-compiled version so that the value in the referent
+ // field can be registered by the G1 pre-barrier code. The intrinsified
+ // version of Reference::get also adds a memory barrier to prevent
+ // commoning reads from the referent field across safepoint since GC
+ // can change the referent field's value. See Compile::Compile()
+ // in src/share/vm/opto/compile.cpp for more details.
+ ccstr disable_intr = NULL;
+ if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
+ (!compilation_context.is_null() &&
+ CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
+ strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
+ ) {
+ return true;
+ }
+
+ // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
+ // the following switch statement.
+ if (!InlineNatives) {
+ switch (id) {
+ case vmIntrinsics::_indexOf:
+ case vmIntrinsics::_compareTo:
+ case vmIntrinsics::_equals:
+ case vmIntrinsics::_equalsC:
+ case vmIntrinsics::_getAndAddInt:
+ case vmIntrinsics::_getAndAddLong:
+ case vmIntrinsics::_getAndSetInt:
+ case vmIntrinsics::_getAndSetLong:
+ case vmIntrinsics::_getAndSetObject:
+ case vmIntrinsics::_loadFence:
+ case vmIntrinsics::_storeFence:
+ case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_Reference_get:
+ break;
+ default:
+ return true;
+ }
+ }
+
+ if (!InlineUnsafeOps) {
+ switch (id) {
+ case vmIntrinsics::_loadFence:
+ case vmIntrinsics::_storeFence:
+ case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_compareAndSwapObject:
+ case vmIntrinsics::_compareAndSwapLong:
+ case vmIntrinsics::_compareAndSwapInt:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
int C2Compiler::initial_code_buffer_size() {
assert(SegmentedCodeCache, "Should be only used with a segmented code cache");
return Compile::MAX_inst_size + Compile::MAX_locs_size + initial_const_capacity;
--- a/hotspot/src/share/vm/opto/c2compiler.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -36,7 +36,6 @@
// Name
const char *name() { return "C2"; }
-
void initialize();
// Compilation entry point for methods
@@ -52,6 +51,26 @@
// Print compilation timers and statistics
void print_timers();
+ // Check the availability of an intrinsic for 'method' given a compilation context.
+ virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
+
+ // Return true if the intrinsification of a method supported by the compiler
+ // assuming a non-virtual dispatch. Return false otherwise.
+ virtual bool is_intrinsic_supported(methodHandle method) {
+ return is_intrinsic_supported(method, false);
+ }
+
+ // Check if the compiler supports an intrinsic for 'method' given the
+ // the dispatch mode specified by the 'is_virtual' parameter.
+ virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual);
+
+ // Processing of command-line flags specific to the C2 compiler.
+ virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
+ return is_intrinsic_disabled_by_flag(method, NULL);
+ }
+
+ virtual bool is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context);
+
// Initial size of the code buffer (may be increased at runtime)
static int initial_code_buffer_size();
};
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -31,6 +31,7 @@
#include "oops/objArrayKlass.hpp"
#include "opto/addnode.hpp"
#include "opto/arraycopynode.hpp"
+#include "opto/c2compiler.hpp"
#include "opto/callGenerator.hpp"
#include "opto/castnode.hpp"
#include "opto/cfgnode.hpp"
@@ -305,330 +306,40 @@
bool inline_isCompileConstant();
};
-
//---------------------------make_vm_intrinsic----------------------------
CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
vmIntrinsics::ID id = m->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
- ccstr disable_intr = NULL;
-
- if ((DisableIntrinsic[0] != '\0'
- && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
- (method_has_option_value("DisableIntrinsic", disable_intr)
- && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) {
- // disabled by a user request on the command line:
- // example: -XX:DisableIntrinsic=_hashCode,_getClass
- return NULL;
- }
-
if (!m->is_loaded()) {
- // do not attempt to inline unloaded methods
- return NULL;
- }
-
- // Only a few intrinsics implement a virtual dispatch.
- // They are expensive calls which are also frequently overridden.
- if (is_virtual) {
- switch (id) {
- case vmIntrinsics::_hashCode:
- case vmIntrinsics::_clone:
- // OK, Object.hashCode and Object.clone intrinsics come in both flavors
- break;
- default:
- return NULL;
- }
- }
-
- // -XX:-InlineNatives disables nearly all intrinsics:
- if (!InlineNatives) {
- switch (id) {
- case vmIntrinsics::_indexOf:
- case vmIntrinsics::_compareTo:
- case vmIntrinsics::_equals:
- case vmIntrinsics::_equalsC:
- case vmIntrinsics::_getAndAddInt:
- case vmIntrinsics::_getAndAddLong:
- case vmIntrinsics::_getAndSetInt:
- case vmIntrinsics::_getAndSetLong:
- case vmIntrinsics::_getAndSetObject:
- case vmIntrinsics::_loadFence:
- case vmIntrinsics::_storeFence:
- case vmIntrinsics::_fullFence:
- break; // InlineNatives does not control String.compareTo
- case vmIntrinsics::_Reference_get:
- break; // InlineNatives does not control Reference.get
- default:
- return NULL;
- }
- }
-
- int predicates = 0;
- bool does_virtual_dispatch = false;
-
- switch (id) {
- case vmIntrinsics::_compareTo:
- if (!SpecialStringCompareTo) return NULL;
- if (!Matcher::match_rule_supported(Op_StrComp)) return NULL;
- break;
- case vmIntrinsics::_indexOf:
- if (!SpecialStringIndexOf) return NULL;
- break;
- case vmIntrinsics::_equals:
- if (!SpecialStringEquals) return NULL;
- if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL;
- break;
- case vmIntrinsics::_equalsC:
- if (!SpecialArraysEquals) return NULL;
- if (!Matcher::match_rule_supported(Op_AryEq)) return NULL;
- break;
- case vmIntrinsics::_arraycopy:
- if (!InlineArrayCopy) return NULL;
- break;
- case vmIntrinsics::_copyMemory:
- if (StubRoutines::unsafe_arraycopy() == NULL) return NULL;
- if (!InlineArrayCopy) return NULL;
- break;
- case vmIntrinsics::_hashCode:
- if (!InlineObjectHash) return NULL;
- does_virtual_dispatch = true;
- break;
- case vmIntrinsics::_clone:
- does_virtual_dispatch = true;
- case vmIntrinsics::_copyOf:
- case vmIntrinsics::_copyOfRange:
- if (!InlineObjectCopy) return NULL;
- // These also use the arraycopy intrinsic mechanism:
- if (!InlineArrayCopy) return NULL;
- break;
- case vmIntrinsics::_encodeISOArray:
- if (!SpecialEncodeISOArray) return NULL;
- if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL;
- break;
- case vmIntrinsics::_checkIndex:
- // We do not intrinsify this. The optimizer does fine with it.
+ // Do not attempt to inline unloaded methods.
return NULL;
-
- case vmIntrinsics::_getCallerClass:
- if (!InlineReflectionGetCallerClass) return NULL;
- if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL;
- break;
-
- case vmIntrinsics::_bitCount_i:
- if (!Matcher::match_rule_supported(Op_PopCountI)) return NULL;
- break;
-
- case vmIntrinsics::_bitCount_l:
- if (!Matcher::match_rule_supported(Op_PopCountL)) return NULL;
- break;
-
- case vmIntrinsics::_numberOfLeadingZeros_i:
- if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return NULL;
- break;
-
- case vmIntrinsics::_numberOfLeadingZeros_l:
- if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return NULL;
- break;
-
- case vmIntrinsics::_numberOfTrailingZeros_i:
- if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return NULL;
- break;
-
- case vmIntrinsics::_numberOfTrailingZeros_l:
- if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL;
- break;
-
- case vmIntrinsics::_reverseBytes_c:
- if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return NULL;
- break;
- case vmIntrinsics::_reverseBytes_s:
- if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return NULL;
- break;
- case vmIntrinsics::_reverseBytes_i:
- if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return NULL;
- break;
- case vmIntrinsics::_reverseBytes_l:
- if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return NULL;
- break;
-
- case vmIntrinsics::_Reference_get:
- // Use the intrinsic version of Reference.get() so that the value in
- // the referent field can be registered by the G1 pre-barrier code.
- // Also add memory barrier to prevent commoning reads from this field
- // across safepoint since GC can change it value.
- break;
-
- case vmIntrinsics::_compareAndSwapObject:
-#ifdef _LP64
- if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return NULL;
-#endif
- break;
-
- case vmIntrinsics::_compareAndSwapLong:
- if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return NULL;
- break;
-
- case vmIntrinsics::_getAndAddInt:
- if (!Matcher::match_rule_supported(Op_GetAndAddI)) return NULL;
- break;
-
- case vmIntrinsics::_getAndAddLong:
- if (!Matcher::match_rule_supported(Op_GetAndAddL)) return NULL;
- break;
-
- case vmIntrinsics::_getAndSetInt:
- if (!Matcher::match_rule_supported(Op_GetAndSetI)) return NULL;
- break;
-
- case vmIntrinsics::_getAndSetLong:
- if (!Matcher::match_rule_supported(Op_GetAndSetL)) return NULL;
- break;
-
- case vmIntrinsics::_getAndSetObject:
-#ifdef _LP64
- if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return NULL;
- if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return NULL;
- break;
-#else
- if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL;
- break;
-#endif
-
- case vmIntrinsics::_aescrypt_encryptBlock:
- case vmIntrinsics::_aescrypt_decryptBlock:
- if (!UseAESIntrinsics) return NULL;
- break;
-
- case vmIntrinsics::_multiplyToLen:
- if (!UseMultiplyToLenIntrinsic) return NULL;
- break;
-
- case vmIntrinsics::_squareToLen:
- if (!UseSquareToLenIntrinsic) return NULL;
- break;
-
- case vmIntrinsics::_mulAdd:
- if (!UseMulAddIntrinsic) return NULL;
- break;
-
- case vmIntrinsics::_montgomeryMultiply:
- if (!UseMontgomeryMultiplyIntrinsic) return NULL;
- break;
- case vmIntrinsics::_montgomerySquare:
- if (!UseMontgomerySquareIntrinsic) return NULL;
- break;
-
- case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
- case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
- if (!UseAESIntrinsics) return NULL;
- // these two require the predicated logic
- predicates = 1;
- break;
-
- case vmIntrinsics::_sha_implCompress:
- if (!UseSHA1Intrinsics) return NULL;
- break;
-
- case vmIntrinsics::_sha2_implCompress:
- if (!UseSHA256Intrinsics) return NULL;
- break;
-
- case vmIntrinsics::_sha5_implCompress:
- if (!UseSHA512Intrinsics) return NULL;
- break;
-
- case vmIntrinsics::_digestBase_implCompressMB:
- if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL;
- predicates = 3;
- break;
-
- case vmIntrinsics::_ghash_processBlocks:
- if (!UseGHASHIntrinsics) return NULL;
- break;
-
- case vmIntrinsics::_updateCRC32:
- case vmIntrinsics::_updateBytesCRC32:
- case vmIntrinsics::_updateByteBufferCRC32:
- if (!UseCRC32Intrinsics) return NULL;
- break;
-
- case vmIntrinsics::_updateBytesCRC32C:
- case vmIntrinsics::_updateDirectByteBufferCRC32C:
- if (!UseCRC32CIntrinsics) return NULL;
- break;
-
- case vmIntrinsics::_incrementExactI:
- case vmIntrinsics::_addExactI:
- if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_incrementExactL:
- case vmIntrinsics::_addExactL:
- if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_decrementExactI:
- case vmIntrinsics::_subtractExactI:
- if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_decrementExactL:
- case vmIntrinsics::_subtractExactL:
- if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_negateExactI:
- if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_negateExactL:
- if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_multiplyExactI:
- if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL;
- break;
- case vmIntrinsics::_multiplyExactL:
- if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL;
- break;
-
- case vmIntrinsics::_getShortUnaligned:
- case vmIntrinsics::_getCharUnaligned:
- case vmIntrinsics::_getIntUnaligned:
- case vmIntrinsics::_getLongUnaligned:
- case vmIntrinsics::_putShortUnaligned:
- case vmIntrinsics::_putCharUnaligned:
- case vmIntrinsics::_putIntUnaligned:
- case vmIntrinsics::_putLongUnaligned:
- if (!UseUnalignedAccesses) return NULL;
- break;
-
- default:
+ }
+
+ C2Compiler* compiler = (C2Compiler*)CompileBroker::compiler(CompLevel_full_optimization);
+ bool is_available = false;
+
+ {
+ // For calling is_intrinsic_supported and is_intrinsic_disabled_by_flag
+ // the compiler must transition to '_thread_in_vm' state because both
+ // methods access VM-internal data.
+ VM_ENTRY_MARK;
+ methodHandle mh(THREAD, m->get_Method());
+ methodHandle ct(THREAD, method()->get_Method());
+ is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
+ !compiler->is_intrinsic_disabled_by_flag(mh, ct);
+ }
+
+ if (is_available) {
assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
- break;
- }
-
- // -XX:-InlineClassNatives disables natives from the Class class.
- // The flag applies to all reflective calls, notably Array.newArray
- // (visible to Java programmers as Array.newInstance).
- if (m->holder()->name() == ciSymbol::java_lang_Class() ||
- m->holder()->name() == ciSymbol::java_lang_reflect_Array()) {
- if (!InlineClassNatives) return NULL;
- }
-
- // -XX:-InlineThreadNatives disables natives from the Thread class.
- if (m->holder()->name() == ciSymbol::java_lang_Thread()) {
- if (!InlineThreadNatives) return NULL;
- }
-
- // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes.
- if (m->holder()->name() == ciSymbol::java_lang_Math() ||
- m->holder()->name() == ciSymbol::java_lang_Float() ||
- m->holder()->name() == ciSymbol::java_lang_Double()) {
- if (!InlineMathNatives) return NULL;
- }
-
- // -XX:-InlineUnsafeOps disables natives from the Unsafe class.
- if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) {
- if (!InlineUnsafeOps) return NULL;
- }
-
- return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id);
+ return new LibraryIntrinsic(m, is_virtual,
+ vmIntrinsics::predicates_needed(id),
+ vmIntrinsics::does_virtual_dispatch(id),
+ (vmIntrinsics::ID) id);
+ } else {
+ return NULL;
+ }
}
//----------------------register_library_intrinsics-----------------------
@@ -812,7 +523,6 @@
case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile);
case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile);
case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile);
-
case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile);
case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile);
case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile);
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -2824,7 +2824,7 @@
if (klass->oop_is_instance()) {
InstanceKlass* ik = InstanceKlass::cast(klass);
- // ignore the class if it's has been initialized yet
+ // Ignore the class if it hasn't been initialized yet
if (!ik->is_linked()) {
return true;
}
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -528,6 +528,24 @@
return mh->queued_for_compilation();
WB_END
+WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
+ if (compLevel < CompLevel_none || compLevel > CompLevel_highest_tier) {
+ return false; // Intrinsic is not available on a non-existent compilation level.
+ }
+ jmethodID method_id, compilation_context_id;
+ method_id = reflected_method_to_jmid(thread, env, method);
+ CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+ methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
+ if (compilation_context != NULL) {
+ compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
+ CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+ methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
+ return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch);
+ } else {
+ return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL);
+ }
+WB_END
+
WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, CompLevel_none);
@@ -1477,14 +1495,17 @@
#endif // INCLUDE_NMT
{CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames },
{CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
- {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I",
- (void*)&WB_DeoptimizeMethod },
+ {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I",
+ (void*)&WB_DeoptimizeMethod },
{CC"isMethodCompiled0", CC"(Ljava/lang/reflect/Executable;Z)Z",
(void*)&WB_IsMethodCompiled },
{CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
(void*)&WB_IsMethodCompilable},
{CC"isMethodQueuedForCompilation0",
CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
+ {CC"isIntrinsicAvailable0",
+ CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
+ (void*)&WB_IsIntrinsicAvailable},
{CC"makeMethodNotCompilable0",
CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable},
{CC"testSetDontInlineMethod0",
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -788,9 +788,11 @@
st->print_cr("VM Arguments:");
if (num_jvm_flags() > 0) {
st->print("jvm_flags: "); print_jvm_flags_on(st);
+ st->cr();
}
if (num_jvm_args() > 0) {
st->print("jvm_args: "); print_jvm_args_on(st);
+ st->cr();
}
st->print_cr("java_command: %s", java_command() ? java_command() : "<unknown>");
if (_java_class_path != NULL) {
@@ -800,12 +802,32 @@
st->print_cr("Launcher Type: %s", _sun_java_launcher);
}
+void Arguments::print_summary_on(outputStream* st) {
+ // Print the command line. Environment variables that are helpful for
+ // reproducing the problem are written later in the hs_err file.
+ // flags are from setting file
+ if (num_jvm_flags() > 0) {
+ st->print_raw("Settings File: ");
+ print_jvm_flags_on(st);
+ st->cr();
+ }
+ // args are the command line and environment variable arguments.
+ st->print_raw("Command Line: ");
+ if (num_jvm_args() > 0) {
+ print_jvm_args_on(st);
+ }
+ // this is the classfile and any arguments to the java program
+ if (java_command() != NULL) {
+ st->print("%s", java_command());
+ }
+ st->cr();
+}
+
void Arguments::print_jvm_flags_on(outputStream* st) {
if (_num_jvm_flags > 0) {
for (int i=0; i < _num_jvm_flags; i++) {
st->print("%s ", _jvm_flags_array[i]);
}
- st->cr();
}
}
@@ -814,7 +836,6 @@
for (int i=0; i < _num_jvm_args; i++) {
st->print("%s ", _jvm_args_array[i]);
}
- st->cr();
}
}
@@ -1205,32 +1226,6 @@
}
}
-/**
- * Returns the minimum number of compiler threads needed to run the JVM. The following
- * configurations are possible.
- *
- * 1) The JVM is build using an interpreter only. As a result, the minimum number of
- * compiler threads is 0.
- * 2) The JVM is build using the compiler(s) and tiered compilation is disabled. As
- * a result, either C1 or C2 is used, so the minimum number of compiler threads is 1.
- * 3) The JVM is build using the compiler(s) and tiered compilation is enabled. However,
- * the option "TieredStopAtLevel < CompLevel_full_optimization". As a result, only
- * C1 can be used, so the minimum number of compiler threads is 1.
- * 4) The JVM is build using the compilers and tiered compilation is enabled. The option
- * 'TieredStopAtLevel = CompLevel_full_optimization' (the default value). As a result,
- * the minimum number of compiler threads is 2.
- */
-int Arguments::get_min_number_of_compiler_threads() {
-#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
- return 0; // case 1
-#else
- if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
- return 1; // case 2 or case 3
- }
- return 2; // case 4 (tiered)
-#endif
-}
-
#if INCLUDE_ALL_GCS
static void disable_adaptive_size_policy(const char* collector_name) {
if (UseAdaptiveSizePolicy) {
@@ -2178,10 +2173,6 @@
status = false;
}
- int min_number_of_compiler_threads = get_min_number_of_compiler_threads();
- // The default CICompilerCount's value is CI_COMPILER_COUNT.
- assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number");
-
if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) {
warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
}
@@ -3989,10 +3980,10 @@
return JNI_OK;
}
-// Any custom code post the final range and constraint check
+// Any custom code post the 'CommandLineFlagConstraint::AfterErgo' constraint check
// can be done here. We pass a flag that specifies whether
// the check passed successfully
-void Arguments::post_final_range_and_constraint_check(bool check_passed) {
+void Arguments::post_after_ergo_constraint_check(bool check_passed) {
// This does not set the flag itself, but stores the value in a safe place for later usage.
_min_heap_free_ratio = MinHeapFreeRatio;
_max_heap_free_ratio = MaxHeapFreeRatio;
--- a/hotspot/src/share/vm/runtime/arguments.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -445,9 +445,6 @@
static char* SharedArchivePath;
public:
- // Tiered
- static int get_min_number_of_compiler_threads();
-
// Scale compile thresholds
// Returns threshold scaled with CompileThresholdScaling
static intx scaled_compile_threshold(intx threshold, double scale);
@@ -466,8 +463,8 @@
static jint apply_ergo();
// Adjusts the arguments after the OS have adjusted the arguments
static jint adjust_after_os();
- // Set any arguments that need to be set after the final range and constraint check
- static void post_final_range_and_constraint_check(bool check_passed);
+ // Set any arguments that need to be set after the 'CommandLineFlagConstraint::AfterErgo' constraint check
+ static void post_after_ergo_constraint_check(bool check_passed);
static void set_gc_specific_flags();
static inline bool gc_selected(); // whether a gc has been selected
@@ -495,6 +492,7 @@
// print jvm_flags, jvm_args and java_command
static void print_on(outputStream* st);
+ static void print_summary_on(outputStream* st);
// convenient methods to obtain / print jvm_flags and jvm_args
static const char* jvm_flags() { return build_resource_string(_jvm_flags_array, _num_jvm_flags); }
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -39,7 +39,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_bool(const char* name,
+ CommandLineFlagConstraintFunc_bool func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -53,7 +55,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_int(const char* name, CommandLineFlagConstraintFunc_int func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_int(const char* name,
+ CommandLineFlagConstraintFunc_int func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -67,7 +71,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_intx(const char* name,
+ CommandLineFlagConstraintFunc_intx func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -81,7 +87,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_uint(const char* name,
+ CommandLineFlagConstraintFunc_uint func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -95,7 +103,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_uintx(const char* name,
+ CommandLineFlagConstraintFunc_uintx func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -109,7 +119,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_uint64_t(const char* name,
+ CommandLineFlagConstraintFunc_uint64_t func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -123,7 +135,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_size_t(const char* name,
+ CommandLineFlagConstraintFunc_size_t func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -137,7 +151,9 @@
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint_double(const char* name, CommandLineFlagConstraintFunc_double func) : CommandLineFlagConstraint(name) {
+ CommandLineFlagConstraint_double(const char* name,
+ CommandLineFlagConstraintFunc_double func,
+ ConstraintType type) : CommandLineFlagConstraint(name, type) {
_constraint=func;
}
@@ -162,29 +178,29 @@
void emit_constraint_double(const char* /*name*/) { /* NOP */ }
// CommandLineFlagConstraint emitting code functions if function argument is provided
-void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func));
+void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func, type));
}
-void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func));
+void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func, type));
}
-void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func));
+void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func, type));
}
-void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func));
+void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func, type));
}
-void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func));
+void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func, type));
}
-void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func));
+void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func, type));
}
-void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func));
+void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func, type));
}
-void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func) {
- CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func));
+void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func, CommandLineFlagConstraint::ConstraintType type) {
+ CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func, type));
}
// Generate code to call emit_constraint_xxx function
@@ -201,16 +217,17 @@
#define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name
// Generate func argument to pass into emit_constraint_xxx functions
-#define EMIT_CONSTRAINT_CHECK(func) , func
+#define EMIT_CONSTRAINT_CHECK(func, type) , func, CommandLineFlagConstraint::type
// the "name" argument must be a string literal
-#define INITIAL_CONTRAINTS_SIZE 16
+#define INITIAL_CONSTRAINTS_SIZE 16
GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
+CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;
// Check the ranges of all flags that have them or print them out and exit if requested
void CommandLineFlagConstraintList::init(void) {
- _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONTRAINTS_SIZE, true);
+ _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
@@ -273,14 +290,89 @@
#endif // INCLUDE_ALL_GCS
}
-CommandLineFlagConstraint* CommandLineFlagConstraintList::find(const char* name) {
+// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
+CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) {
CommandLineFlagConstraint* found = NULL;
for (int i=0; i<length(); i++) {
CommandLineFlagConstraint* constraint = at(i);
- if (strcmp(constraint->name(), name) == 0) {
+ if ((strcmp(constraint->name(), name) == 0) &&
+ (constraint->type() <= _validating_type)) {
found = constraint;
break;
}
}
return found;
}
+
+// Check constraints for specific constraint type.
+bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) {
+//#define PRINT_CONSTRAINTS_SIZES
+#ifdef PRINT_CONSTRAINTS_SIZES
+ {
+ size_t size_constraints = sizeof(CommandLineFlagConstraintList);
+ for (int i=0; i<length(); i++) {
+ size_constraints += sizeof(CommandLineFlagConstraint);
+ CommandLineFlagConstraint* constraint = at(i);
+ const char* name = constraint->name();
+ Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+ if (flag->is_bool()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_bool);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ } else if (flag->is_intx()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_intx);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ } else if (flag->is_uintx()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_uintx);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ } else if (flag->is_uint64_t()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_uint64_t);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ } else if (flag->is_size_t()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_size_t);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ } else if (flag->is_double()) {
+ size_constraints += sizeof(CommandLineFlagConstraintFunc_double);
+ size_constraints += sizeof(CommandLineFlagConstraint*);
+ }
+ }
+ fprintf(stderr, "Size of %d constraints: " SIZE_FORMAT " bytes\n",
+ length(), size_constraints);
+ }
+#endif // PRINT_CONSTRAINTS_SIZES
+
+ // Skip if we already checked.
+ if (type < _validating_type) {
+ return true;
+ }
+ _validating_type = type;
+
+ bool status = true;
+ for (int i=0; i<length(); i++) {
+ CommandLineFlagConstraint* constraint = at(i);
+ if (type != constraint->type()) continue;
+ const char*name = constraint->name();
+ Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+ if (flag != NULL) {
+ if (flag->is_bool()) {
+ bool value = flag->get_bool();
+ if (constraint->apply_bool(&value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_intx()) {
+ intx value = flag->get_intx();
+ if (constraint->apply_intx(&value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_uintx()) {
+ uintx value = flag->get_uintx();
+ if (constraint->apply_uintx(&value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_uint64_t()) {
+ uint64_t value = flag->get_uint64_t();
+ if (constraint->apply_uint64_t(&value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_size_t()) {
+ size_t value = flag->get_size_t();
+ if (constraint->apply_size_t(&value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_double()) {
+ double value = flag->get_double();
+ if (constraint->apply_double(&value, true) != Flag::SUCCESS) status = false;
+ }
+ }
+ }
+ return status;
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -49,13 +49,27 @@
typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(bool verbose, double* value);
class CommandLineFlagConstraint : public CHeapObj<mtInternal> {
+public:
+ // During VM initialization, constraint validation will be done order of ConstraintType.
+ enum ConstraintType {
+ // Will be validated during argument processing (Arguments::parse_argument).
+ AtParse = 0,
+ // Will be validated by CommandLineFlags::check_constraints_of_after_ergo().
+ AfterErgo = 1,
+ // Will be validated by CommandLineFlags::check_constraints_of_after_memory_init().
+ AfterMemoryInit = 2
+ };
+
private:
const char* _name;
+ ConstraintType _validate_type;
+
public:
// the "name" argument must be a string literal
- CommandLineFlagConstraint(const char* name) { _name=name; };
+ CommandLineFlagConstraint(const char* name, ConstraintType type) { _name=name; _validate_type=type; };
~CommandLineFlagConstraint() {};
- const char* name() { return _name; }
+ const char* name() const { return _name; }
+ ConstraintType type() const { return _validate_type; }
virtual Flag::Error apply_bool(bool* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
virtual Flag::Error apply_int(int* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
virtual Flag::Error apply_intx(intx* value, bool verbose = true) { ShouldNotReachHere(); return Flag::ERR_OTHER; };
@@ -69,12 +83,17 @@
class CommandLineFlagConstraintList : public AllStatic {
private:
static GrowableArray<CommandLineFlagConstraint*>* _constraints;
+ // Latest constraint validation type.
+ static CommandLineFlagConstraint::ConstraintType _validating_type;
public:
static void init();
static int length() { return (_constraints != NULL) ? _constraints->length() : 0; }
static CommandLineFlagConstraint* at(int i) { return (_constraints != NULL) ? _constraints->at(i) : NULL; }
- static CommandLineFlagConstraint* find(const char* name);
+ static CommandLineFlagConstraint* find_if_needs_check(const char* name);
static void add(CommandLineFlagConstraint* constraint) { _constraints->append(constraint); }
+ // True if 'AfterErgo' or later constraint functions are validated.
+ static bool validated_after_ergo() { return _validating_type >= CommandLineFlagConstraint::AfterErgo; };
+ static bool check_constraints(CommandLineFlagConstraint::ConstraintType type);
};
#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTLIST_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -29,16 +29,57 @@
#include "utilities/defaultStream.hpp"
Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value) {
- if (CommandLineFlags::finishedInitializing() == true) {
- if ((*value <= 1) && (Arguments::mode() == Arguments::_comp)) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(),
- "AliasLevel (" INTX_FORMAT ") is not compatible "
- "with -Xcomp \n",
- *value);
- }
- return Flag::VIOLATES_CONSTRAINT;
+ if ((*value <= 1) && (Arguments::mode() == Arguments::_comp)) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "AliasLevel (" INTX_FORMAT ") is not compatible "
+ "with -Xcomp \n",
+ *value);
}
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
}
- return Flag::SUCCESS;
}
+
+/**
+ * Validate the minimum number of compiler threads needed to run the
+ * JVM. The following configurations are possible.
+ *
+ * 1) The JVM is build using an interpreter only. As a result, the minimum number of
+ * compiler threads is 0.
+ * 2) The JVM is build using the compiler(s) and tiered compilation is disabled. As
+ * a result, either C1 or C2 is used, so the minimum number of compiler threads is 1.
+ * 3) The JVM is build using the compiler(s) and tiered compilation is enabled. However,
+ * the option "TieredStopAtLevel < CompLevel_full_optimization". As a result, only
+ * C1 can be used, so the minimum number of compiler threads is 1.
+ * 4) The JVM is build using the compilers and tiered compilation is enabled. The option
+ * 'TieredStopAtLevel = CompLevel_full_optimization' (the default value). As a result,
+ * the minimum number of compiler threads is 2.
+ */
+Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value) {
+ int min_number_of_compiler_threads = 0;
+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)
+ // case 1
+#else
+ if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) {
+ min_number_of_compiler_threads = 1; // case 2 or case 3
+ } else {
+ min_number_of_compiler_threads = 2; // case 4 (tiered)
+ }
+#endif
+
+ // The default CICompilerCount's value is CI_COMPILER_COUNT.
+ assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number");
+
+ if (*value < (intx)min_number_of_compiler_threads) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "CICompilerCount=" INTX_FORMAT " must be at least %d \n",
+ *value, min_number_of_compiler_threads);
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -36,4 +36,6 @@
Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value);
+Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value);
+
#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -30,6 +30,9 @@
#if INCLUDE_ALL_GCS
#include "gc/g1/g1_globals.hpp"
+#include "gc/g1/heapRegionBounds.inline.hpp"
+#include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/shared/plab.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
@@ -38,8 +41,49 @@
#include "opto/c2_globals.hpp"
#endif // COMPILER2
+static Flag::Error MinPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+#if INCLUDE_ALL_GCS
+ if ((UseConcMarkSweepGC || UseG1GC) && (*value < PLAB::min_size())) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "%s (" SIZE_FORMAT ") must be greater than "
+ "ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
+ name, *value, PLAB::min_size());
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif // INCLUDE_ALL_GCS
+ return Flag::SUCCESS;
+}
+
+static Flag::Error MaxPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+#if INCLUDE_ALL_GCS
+ if ((UseConcMarkSweepGC || UseG1GC) && (*value > PLAB::max_size())) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "%s (" SIZE_FORMAT ") must be less than "
+ "ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
+ name, *value, PLAB::max_size());
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif // INCLUDE_ALL_GCS
+ return Flag::SUCCESS;
+}
+
+static Flag::Error MinMaxPLABSizeBounds(const char* name, bool verbose, size_t* value) {
+ if (MinPLABSizeBounds(name, verbose, value) == Flag::SUCCESS) {
+ return MaxPLABSizeBounds(name, verbose, value);
+ }
+ return Flag::VIOLATES_CONSTRAINT;
+}
+
+Flag::Error YoungPLABSizeConstraintFunc(bool verbose, size_t* value) {
+ return MinMaxPLABSizeBounds("YoungPLABSize", verbose, value);
+}
+
Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value > MaxHeapFreeRatio)) {
+ if (*value > MaxHeapFreeRatio) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
@@ -53,7 +97,7 @@
}
Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value < MinHeapFreeRatio)) {
+ if (*value < MinHeapFreeRatio) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
@@ -67,7 +111,7 @@
}
Flag::Error MinMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value > MaxMetaspaceFreeRatio)) {
+ if (*value > MaxMetaspaceFreeRatio) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be less than or "
@@ -81,7 +125,7 @@
}
Flag::Error MaxMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value < MinMetaspaceFreeRatio)) {
+ if (*value < MinMetaspaceFreeRatio) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be greater than or "
@@ -106,7 +150,7 @@
Flag::Error InitialTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
UseConcMarkSweepGCWorkaroundIfNeeded(*value, MaxTenuringThreshold);
- if ((CommandLineFlags::finishedInitializing()) && (*value > MaxTenuringThreshold)) {
+ if (*value > MaxTenuringThreshold) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"InitialTenuringThreshold (" UINTX_FORMAT ") must be less than or "
@@ -122,7 +166,7 @@
Flag::Error MaxTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
UseConcMarkSweepGCWorkaroundIfNeeded(InitialTenuringThreshold, *value);
- if ((CommandLineFlags::finishedInitializing()) && (*value < InitialTenuringThreshold)) {
+ if (*value < InitialTenuringThreshold) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"MaxTenuringThreshold (" UINTX_FORMAT ") must be greater than or "
@@ -136,9 +180,8 @@
}
#if INCLUDE_ALL_GCS
-
Flag::Error G1NewSizePercentConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value > G1MaxNewSizePercent)) {
+ if (*value > G1MaxNewSizePercent) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"G1NewSizePercent (" UINTX_FORMAT ") must be less than or "
@@ -152,7 +195,7 @@
}
Flag::Error G1MaxNewSizePercentConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value < G1NewSizePercent)) {
+ if (*value < G1NewSizePercent) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"G1MaxNewSizePercent (" UINTX_FORMAT ") must be greater than or "
@@ -168,7 +211,7 @@
#endif // INCLUDE_ALL_GCS
Flag::Error CMSOldPLABMinConstraintFunc(bool verbose, size_t* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value > CMSOldPLABMax)) {
+ if (*value > CMSOldPLABMax) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"CMSOldPLABMin (" SIZE_FORMAT ") must be less than or "
@@ -182,7 +225,7 @@
}
Flag::Error CMSPrecleanDenominatorConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value <= CMSPrecleanNumerator)) {
+ if (*value <= CMSPrecleanNumerator) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"CMSPrecleanDenominator (" UINTX_FORMAT ") must be strickly greater than "
@@ -196,7 +239,7 @@
}
Flag::Error CMSPrecleanNumeratorConstraintFunc(bool verbose, uintx* value) {
- if ((CommandLineFlags::finishedInitializing()) && (*value > (CMSPrecleanDenominator - 1))) {
+ if (*value > (CMSPrecleanDenominator - 1)) {
if (verbose == true) {
jio_fprintf(defaultStream::error_stream(),
"CMSPrecleanNumerator (" UINTX_FORMAT ") must be less than or "
@@ -210,25 +253,23 @@
}
Flag::Error SurvivorAlignmentInBytesConstraintFunc(bool verbose, intx* value) {
- if (CommandLineFlags::finishedInitializing()) {
- if (*value != 0) {
- if (!is_power_of_2(*value)) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(),
- "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be power of 2\n",
- *value);
- }
- return Flag::VIOLATES_CONSTRAINT;
+ if (*value != 0) {
+ if (!is_power_of_2(*value)) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be power of 2\n",
+ *value);
}
- if (*value < ObjectAlignmentInBytes) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(),
- "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be greater than or "
- "equal to ObjectAlignmentInBytes (" INTX_FORMAT ") \n",
- *value, ObjectAlignmentInBytes);
- }
- return Flag::VIOLATES_CONSTRAINT;
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ if (*value < ObjectAlignmentInBytes) {
+ if (verbose == true) {
+ jio_fprintf(defaultStream::error_stream(),
+ "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be greater than or "
+ "equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n",
+ *value, ObjectAlignmentInBytes);
}
+ return Flag::VIOLATES_CONSTRAINT;
}
}
return Flag::SUCCESS;
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -34,6 +34,8 @@
* an appropriate error value.
*/
+Flag::Error YoungPLABSizeConstraintFunc(bool verbose, size_t* value);
+
Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
Flag::Error MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value);
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -365,3 +365,63 @@
st->print("[ ... ]");
}
}
+
+bool CommandLineFlagRangeList::check_ranges() {
+//#define PRINT_RANGES_SIZES
+#ifdef PRINT_RANGES_SIZES
+ {
+ size_t size_ranges = sizeof(CommandLineFlagRangeList);
+ for (int i=0; i<length(); i++) {
+ size_ranges += sizeof(CommandLineFlagRange);
+ CommandLineFlagRange* range = at(i);
+ const char* name = range->name();
+ Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+ if (flag->is_intx()) {
+ size_ranges += 2*sizeof(intx);
+ size_ranges += sizeof(CommandLineFlagRange*);
+ } else if (flag->is_uintx()) {
+ size_ranges += 2*sizeof(uintx);
+ size_ranges += sizeof(CommandLineFlagRange*);
+ } else if (flag->is_uint64_t()) {
+ size_ranges += 2*sizeof(uint64_t);
+ size_ranges += sizeof(CommandLineFlagRange*);
+ } else if (flag->is_size_t()) {
+ size_ranges += 2*sizeof(size_t);
+ size_ranges += sizeof(CommandLineFlagRange*);
+ } else if (flag->is_double()) {
+ size_ranges += 2*sizeof(double);
+ size_ranges += sizeof(CommandLineFlagRange*);
+ }
+ }
+ fprintf(stderr, "Size of %d ranges: " SIZE_FORMAT " bytes\n",
+ length(), size_ranges);
+ }
+#endif // PRINT_RANGES_SIZES
+
+ // Check ranges.
+ bool status = true;
+ for (int i=0; i<length(); i++) {
+ CommandLineFlagRange* range = at(i);
+ const char* name = range->name();
+ Flag* flag = Flag::find_flag(name, strlen(name), true, true);
+ if (flag != NULL) {
+ if (flag->is_intx()) {
+ intx value = flag->get_intx();
+ if (range->check_intx(value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_uintx()) {
+ uintx value = flag->get_uintx();
+ if (range->check_uintx(value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_uint64_t()) {
+ uint64_t value = flag->get_uint64_t();
+ if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_size_t()) {
+ size_t value = flag->get_size_t();
+ if (range->check_size_t(value, true) != Flag::SUCCESS) status = false;
+ } else if (flag->is_double()) {
+ double value = flag->get_double();
+ if (range->check_double(value, true) != Flag::SUCCESS) status = false;
+ }
+ }
+ }
+ return status;
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -66,6 +66,8 @@
static CommandLineFlagRange* find(const char* name);
static void add(CommandLineFlagRange* range) { _ranges->append(range); }
static void print(const char* name, outputStream* st, bool unspecified = false);
+ // Check the final values of all flags for ranges.
+ static bool check_ranges();
};
#endif // SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -770,7 +770,7 @@
static Flag::Error apply_constraint_and_check_range_bool(const char* name, bool* new_value, bool verbose = true) {
Flag::Error status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
status = constraint->apply_bool(new_value, verbose);
}
@@ -789,7 +789,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_bool()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_bool(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_bool(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
bool old_value = result->get_bool();
trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
@@ -817,7 +817,7 @@
range_status = range->check_int(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_int(new_value, verbose);
}
@@ -836,7 +836,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_int()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_int(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_int(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
int old_value = result->get_int();
trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
@@ -862,7 +862,7 @@
range_status = range->check_uint(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_uint(new_value, verbose);
}
@@ -881,7 +881,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_uint()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_uint(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_uint(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
uint old_value = result->get_uint();
trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
@@ -915,7 +915,7 @@
range_status = range->check_intx(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_intx(new_value, verbose);
}
@@ -926,7 +926,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_intx()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_intx(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_intx(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
intx old_value = result->get_intx();
trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
@@ -962,7 +962,7 @@
range_status = range->check_uintx(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_uintx(new_value, verbose);
}
@@ -973,7 +973,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_uintx()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_uintx(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_uintx(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
uintx old_value = result->get_uintx();
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1009,7 +1009,7 @@
range_status = range->check_uint64_t(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_uint64_t(new_value, verbose);
}
@@ -1020,7 +1020,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_uint64_t()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_uint64_t(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_uint64_t(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
uint64_t old_value = result->get_uint64_t();
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1056,7 +1056,7 @@
range_status = range->check_size_t(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_size_t(new_value, verbose);
}
@@ -1067,7 +1067,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_size_t()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_size_t(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_size_t(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
size_t old_value = result->get_size_t();
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
@@ -1103,7 +1103,7 @@
range_status = range->check_double(*new_value, verbose);
}
Flag::Error constraint_status = Flag::SUCCESS;
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+ CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
if (constraint != NULL) {
constraint_status = constraint->apply_double(new_value, verbose);
}
@@ -1114,7 +1114,7 @@
Flag* result = Flag::find_flag(name, len);
if (result == NULL) return Flag::INVALID_FLAG;
if (!result->is_double()) return Flag::WRONG_FORMAT;
- Flag::Error check = apply_constraint_and_check_range_double(name, value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_double(name, value, !CommandLineFlagConstraintList::validated_after_ergo());
if (check != Flag::SUCCESS) return check;
double old_value = result->get_double();
trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
@@ -1127,7 +1127,7 @@
Flag::Error CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
Flag* faddr = address_of_flag(flag);
guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
- Flag::Error check = apply_constraint_and_check_range_double(faddr->_name, &value, !CommandLineFlags::finishedInitializing());
+ Flag::Error check = apply_constraint_and_check_range_double(faddr->_name, &value);
if (check != Flag::SUCCESS) return check;
trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin);
faddr->set_double(value);
@@ -1210,129 +1210,6 @@
FREE_C_HEAP_ARRAY(Flag*, array);
}
-bool CommandLineFlags::_finished_initializing = false;
-
-bool CommandLineFlags::check_all_ranges_and_constraints() {
-
-//#define PRINT_RANGES_AND_CONSTRAINTS_SIZES
-#ifdef PRINT_RANGES_AND_CONSTRAINTS_SIZES
- {
- size_t size_ranges = sizeof(CommandLineFlagRangeList);
- for (int i=0; i<CommandLineFlagRangeList::length(); i++) {
- size_ranges += sizeof(CommandLineFlagRange);
- CommandLineFlagRange* range = CommandLineFlagRangeList::at(i);
- const char* name = range->name();
- Flag* flag = Flag::find_flag(name, strlen(name), true, true);
- if (flag->is_intx()) {
- size_ranges += 2*sizeof(intx);
- size_ranges += sizeof(CommandLineFlagRange*);
- } else if (flag->is_uintx()) {
- size_ranges += 2*sizeof(uintx);
- size_ranges += sizeof(CommandLineFlagRange*);
- } else if (flag->is_uint64_t()) {
- size_ranges += 2*sizeof(uint64_t);
- size_ranges += sizeof(CommandLineFlagRange*);
- } else if (flag->is_size_t()) {
- size_ranges += 2*sizeof(size_t);
- size_ranges += sizeof(CommandLineFlagRange*);
- } else if (flag->is_double()) {
- size_ranges += 2*sizeof(double);
- size_ranges += sizeof(CommandLineFlagRange*);
- }
- }
- fprintf(stderr, "Size of %d ranges: " SIZE_FORMAT " bytes\n",
- CommandLineFlagRangeList::length(), size_ranges);
- }
- {
- size_t size_constraints = sizeof(CommandLineFlagConstraintList);
- for (int i=0; i<CommandLineFlagConstraintList::length(); i++) {
- size_constraints += sizeof(CommandLineFlagConstraint);
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::at(i);
- const char* name = constraint->name();
- Flag* flag = Flag::find_flag(name, strlen(name), true, true);
- if (flag->is_bool()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_bool);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- } else if (flag->is_intx()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_intx);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- } else if (flag->is_uintx()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_uintx);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- } else if (flag->is_uint64_t()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_uint64_t);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- } else if (flag->is_size_t()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_size_t);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- } else if (flag->is_double()) {
- size_constraints += sizeof(CommandLineFlagConstraintFunc_double);
- size_constraints += sizeof(CommandLineFlagConstraint*);
- }
- }
- fprintf(stderr, "Size of %d constraints: " SIZE_FORMAT " bytes\n",
- CommandLineFlagConstraintList::length(), size_constraints);
- }
-#endif // PRINT_RANGES_AND_CONSTRAINTS_SIZES
-
- _finished_initializing = true;
-
- bool status = true;
- for (int i=0; i<CommandLineFlagRangeList::length(); i++) {
- CommandLineFlagRange* range = CommandLineFlagRangeList::at(i);
- const char* name = range->name();
- Flag* flag = Flag::find_flag(name, strlen(name), true, true);
- if (flag != NULL) {
- if (flag->is_intx()) {
- intx value = flag->get_intx();
- if (range->check_intx(value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_uintx()) {
- uintx value = flag->get_uintx();
- if (range->check_uintx(value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_uint64_t()) {
- uint64_t value = flag->get_uint64_t();
- if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_size_t()) {
- size_t value = flag->get_size_t();
- if (range->check_size_t(value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_double()) {
- double value = flag->get_double();
- if (range->check_double(value, true) != Flag::SUCCESS) status = false;
- }
- }
- }
- for (int i=0; i<CommandLineFlagConstraintList::length(); i++) {
- CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::at(i);
- const char*name = constraint->name();
- Flag* flag = Flag::find_flag(name, strlen(name), true, true);
- if (flag != NULL) {
- if (flag->is_bool()) {
- bool value = flag->get_bool();
- if (constraint->apply_bool(&value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_intx()) {
- intx value = flag->get_intx();
- if (constraint->apply_intx(&value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_uintx()) {
- uintx value = flag->get_uintx();
- if (constraint->apply_uintx(&value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_uint64_t()) {
- uint64_t value = flag->get_uint64_t();
- if (constraint->apply_uint64_t(&value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_size_t()) {
- size_t value = flag->get_size_t();
- if (constraint->apply_size_t(&value, true) != Flag::SUCCESS) status = false;
- } else if (flag->is_double()) {
- double value = flag->get_double();
- if (constraint->apply_double(&value, true) != Flag::SUCCESS) status = false;
- }
- }
- }
-
- Arguments::post_final_range_and_constraint_check(status);
-
- return status;
-}
-
#ifndef PRODUCT
void CommandLineFlags::verify() {
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -450,7 +450,6 @@
class CommandLineFlags {
- static bool _finished_initializing;
public:
static Flag::Error boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
static Flag::Error boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false) { return boolAt(name, strlen(name), value, allow_locked, return_flag); }
@@ -506,12 +505,6 @@
// printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
static void printFlags(outputStream* out, bool withComments, bool printRanges = false);
- // Returns true if all flags have their final values set (ready for ranges and constraint check)
- static bool finishedInitializing() { return _finished_initializing; }
-
- // Check the final values of all flags for ranges and constraints
- static bool check_all_ranges_and_constraints();
-
static void verify() PRODUCT_RETURN;
};
@@ -640,7 +633,7 @@
lp64_product(intx, ObjectAlignmentInBytes, 8, \
"Default object alignment in bytes, 8 is minimum") \
range(8, 256) \
- constraint(ObjectAlignmentInBytesConstraintFunc) \
+ constraint(ObjectAlignmentInBytesConstraintFunc,AtParse) \
\
product(bool, AssumeMP, false, \
"Instruct the VM to assume multiple processors are available") \
@@ -1286,7 +1279,7 @@
\
experimental(intx, SyncVerbose, 0, "(Unstable)") \
\
- product(bool, InlineNotify, true, "intrinsify subset of notify" ) \
+ diagnostic(bool, InlineNotify, true, "intrinsify subset of notify") \
\
experimental(intx, ClearFPUAtPark, 0, "(Unsafe, Unstable)") \
\
@@ -1396,7 +1389,7 @@
product(intx, ContendedPaddingWidth, 128, \
"How many bytes to pad the fields/classes marked @Contended with")\
range(0, 8192) \
- constraint(ContendedPaddingWidthConstraintFunc) \
+ constraint(ContendedPaddingWidthConstraintFunc,AtParse) \
\
product(bool, EnableContended, true, \
"Enable @Contended annotation support") \
@@ -1597,6 +1590,7 @@
\
product(size_t, YoungPLABSize, 4096, \
"Size of young gen promotion LAB's (in HeapWords)") \
+ constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit) \
\
product(size_t, OldPLABSize, 1024, \
"Size of old gen promotion LAB's (in HeapWords), or Number \
@@ -1735,7 +1729,7 @@
"Minimum size of CMS gen promotion LAB caches per worker " \
"per block size") \
range(1, max_uintx) \
- constraint(CMSOldPLABMinConstraintFunc) \
+ constraint(CMSOldPLABMinConstraintFunc,AfterErgo) \
\
product(uintx, CMSOldPLABNumRefills, 4, \
"Nominal number of refills of CMS gen promotion LAB cache " \
@@ -1931,13 +1925,13 @@
"CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
"ratio") \
range(1, max_uintx) \
- constraint(CMSPrecleanDenominatorConstraintFunc) \
+ constraint(CMSPrecleanDenominatorConstraintFunc,AfterErgo) \
\
product(uintx, CMSPrecleanNumerator, 2, \
"CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
"ratio") \
range(0, max_uintx-1) \
- constraint(CMSPrecleanNumeratorConstraintFunc) \
+ constraint(CMSPrecleanNumeratorConstraintFunc,AfterErgo) \
\
product(bool, CMSPrecleanRefLists1, true, \
"Preclean ref lists during (initial) preclean phase") \
@@ -2649,8 +2643,8 @@
/* because of overflow issue */ \
product(intx, CICompilerCount, CI_COMPILER_COUNT, \
"Number of compiler threads to run") \
- range((intx)Arguments::get_min_number_of_compiler_threads(), \
- max_jint) \
+ range(0, max_jint) \
+ constraint(CICompilerCountConstraintFunc, AtParse) \
\
product(intx, CompilationPolicyChoice, 0, \
"which compilation policy (0-3)") \
@@ -3361,14 +3355,14 @@
" For most GCs this applies to the old generation. In G1 and" \
" ParallelGC it applies to the whole heap.") \
range(0, 100) \
- constraint(MinHeapFreeRatioConstraintFunc) \
+ constraint(MinHeapFreeRatioConstraintFunc,AfterErgo) \
\
manageable(uintx, MaxHeapFreeRatio, 70, \
"The maximum percentage of heap free after GC to avoid shrinking."\
" For most GCs this applies to the old generation. In G1 and" \
" ParallelGC it applies to the whole heap.") \
range(0, 100) \
- constraint(MaxHeapFreeRatioConstraintFunc) \
+ constraint(MaxHeapFreeRatioConstraintFunc,AfterErgo) \
\
product(intx, SoftRefLRUPolicyMSPerMB, 1000, \
"Number of milliseconds per MB of free space in the heap") \
@@ -3383,13 +3377,13 @@
"The maximum percentage of Metaspace free after GC to avoid " \
"shrinking") \
range(0, 100) \
- constraint(MaxMetaspaceFreeRatioConstraintFunc) \
+ constraint(MaxMetaspaceFreeRatioConstraintFunc,AfterErgo) \
\
product(uintx, MinMetaspaceFreeRatio, 40, \
"The minimum percentage of Metaspace free after GC to avoid " \
"expansion") \
range(0, 99) \
- constraint(MinMetaspaceFreeRatioConstraintFunc) \
+ constraint(MinMetaspaceFreeRatioConstraintFunc,AfterErgo) \
\
product(size_t, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \
"The maximum expansion of Metaspace without full GC (in bytes)") \
@@ -3407,12 +3401,12 @@
product(uintx, MaxTenuringThreshold, 15, \
"Maximum value for tenuring threshold") \
range(0, markOopDesc::max_age + 1) \
- constraint(MaxTenuringThresholdConstraintFunc) \
+ constraint(MaxTenuringThresholdConstraintFunc,AfterErgo) \
\
product(uintx, InitialTenuringThreshold, 7, \
"Initial value for tenuring threshold") \
range(0, markOopDesc::max_age + 1) \
- constraint(InitialTenuringThresholdConstraintFunc) \
+ constraint(InitialTenuringThresholdConstraintFunc,AfterErgo) \
\
product(uintx, TargetSurvivorRatio, 50, \
"Desired percentage of survivor space used after scavenge") \
@@ -4090,7 +4084,7 @@
\
experimental(intx, SurvivorAlignmentInBytes, 0, \
"Default survivor space alignment in bytes") \
- constraint(SurvivorAlignmentInBytesConstraintFunc) \
+ constraint(SurvivorAlignmentInBytesConstraintFunc,AfterErgo) \
\
product(bool , AllowNonVirtualCalls, false, \
"Obey the ACC_SUPER flag and allow invokenonvirtual calls") \
@@ -4194,7 +4188,7 @@
// Only materialize src code for range checking when required, ignore otherwise
#define IGNORE_RANGE(a, b)
// Only materialize src code for contraint checking when required, ignore otherwise
-#define IGNORE_CONSTRAINT(func)
+#define IGNORE_CONSTRAINT(func,type)
RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, \
DECLARE_PD_DEVELOPER_FLAG, \
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -83,7 +83,6 @@
Monitor* DirtyCardQ_CBL_mon = NULL;
Mutex* Shared_DirtyCardQ_lock = NULL;
Mutex* ParGCRareEvent_lock = NULL;
-Mutex* EvacFailureStack_lock = NULL;
Mutex* DerivedPointerTableGC_lock = NULL;
Mutex* Compile_lock = NULL;
Monitor* MethodCompileQueue_lock = NULL;
@@ -201,7 +200,6 @@
def(OldSets_lock , Mutex , leaf , true, Monitor::_safepoint_check_never);
def(RootRegionScan_lock , Monitor, leaf , true, Monitor::_safepoint_check_never);
def(MMUTracker_lock , Mutex , leaf , true, Monitor::_safepoint_check_never);
- def(EvacFailureStack_lock , Mutex , nonleaf , true, Monitor::_safepoint_check_never);
def(StringDedupQueue_lock , Monitor, leaf, true, Monitor::_safepoint_check_never);
def(StringDedupTable_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -87,7 +87,6 @@
// non-Java threads.
// (see option ExplicitGCInvokesConcurrent)
extern Mutex* ParGCRareEvent_lock; // Synchronizes various (rare) parallel GC ops.
-extern Mutex* EvacFailureStack_lock; // guards the evac failure scan stack
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
extern Monitor* CompileThread_lock; // a lock held by compile threads during compilation system initialization
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -843,6 +843,28 @@
pd_print_cpu_info(st, buf, buflen);
}
+// Print a one line string summarizing the cpu, number of cores, memory, and operating system version
+void os::print_summary_info(outputStream* st, char* buf, size_t buflen) {
+ st->print("Host: ");
+#ifndef PRODUCT
+ if (get_host_name(buf, buflen)) {
+ st->print("%s, ", buf);
+ }
+#endif // PRODUCT
+ get_summary_cpu_info(buf, buflen);
+ st->print("%s, ", buf);
+ size_t mem = physical_memory()/G;
+ if (mem == 0) { // for low memory systems
+ mem = physical_memory()/M;
+ st->print("%d cores, %dM, ", processor_count(), mem);
+ } else {
+ st->print("%d cores, %dG, ", processor_count(), mem);
+ }
+ get_summary_os_info(buf, buflen);
+ st->print_raw(buf);
+ st->cr();
+}
+
void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
const int secs_per_day = 86400;
const int secs_per_hour = 3600;
@@ -850,12 +872,19 @@
time_t tloc;
(void)time(&tloc);
- st->print("time: %s", ctime(&tloc)); // ctime adds newline.
+ char* timestring = ctime(&tloc); // ctime adds newline.
+ // edit out the newline
+ char* nl = strchr(timestring, '\n');
+ if (nl != NULL) {
+ *nl = '\0';
+ }
struct tm tz;
if (localtime_pd(&tloc, &tz) != NULL) {
::strftime(buf, buflen, "%Z", &tz);
- st->print_cr("timezone: %s", buf);
+ st->print("Time: %s %s", timestring, buf);
+ } else {
+ st->print("Time: %s", timestring);
}
double t = os::elapsedTime();
@@ -872,7 +901,7 @@
int elmins = (eltime - day_secs - hour_secs) / secs_per_min;
int minute_secs = elmins * secs_per_min;
int elsecs = (eltime - day_secs - hour_secs - minute_secs);
- st->print_cr("elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs);
+ st->print_cr(" elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs);
}
// moved from debug.cpp (used to be find()) but still called from there
--- a/hotspot/src/share/vm/runtime/os.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -150,6 +150,11 @@
static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
+ // Get summary strings for system information in buffer provided
+ static bool get_host_name(char* buf, size_t buflen) PRODUCT_RETURN_(return false;); // true if available
+ static void get_summary_cpu_info(char* buf, size_t buflen);
+ static void get_summary_os_info(char* buf, size_t buflen);
+
public:
static void init(void); // Called before command line parsing
static void init_before_ergo(void); // Called after command line parsing
@@ -590,6 +595,7 @@
static void print_os_info_brief(outputStream* st);
static void print_cpu_info(outputStream* st, char* buf, size_t buflen);
static void pd_print_cpu_info(outputStream* st, char* buf, size_t buflen);
+ static void print_summary_info(outputStream* st, char* buf, size_t buflen);
static void print_memory_info(outputStream* st);
static void print_dll_info(outputStream* st);
static void print_environment_variables(outputStream* st, const char** env_list);
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -52,6 +52,8 @@
#include "runtime/arguments.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/biasedLocking.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/frame.inline.hpp"
@@ -2739,6 +2741,9 @@
if (ct->env() != NULL) {
ct->env()->metadata_do(f);
}
+ if (ct->task() != NULL) {
+ ct->task()->metadata_do(f);
+ }
}
}
@@ -3319,8 +3324,15 @@
jint ergo_result = Arguments::apply_ergo();
if (ergo_result != JNI_OK) return ergo_result;
- // Final check of all arguments after ergonomics which may change values.
- if (!CommandLineFlags::check_all_ranges_and_constraints()) {
+ // Final check of all ranges after ergonomics which may change values.
+ if (!CommandLineFlagRangeList::check_ranges()) {
+ return JNI_EINVAL;
+ }
+
+ // Final check of all 'AfterErgo' constraints after ergonomics which may change values.
+ bool constraint_result = CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::AfterErgo);
+ Arguments::post_after_ergo_constraint_check(constraint_result);
+ if (!constraint_result) {
return JNI_EINVAL;
}
--- a/hotspot/src/share/vm/runtime/vframe.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -148,8 +148,7 @@
if (obj.not_null()) {
st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
if (obj->klass() == SystemDictionary::Class_klass()) {
- Klass* target_klass = java_lang_Class::as_Klass(obj());
- st->print_cr("(a java.lang.Class for %s)", InstanceKlass::cast(target_klass)->external_name());
+ st->print_cr("(a java.lang.Class for %s)", java_lang_Class::as_external_name(obj()));
} else {
Klass* k = obj->klass();
st->print_cr("(a %s)", k->external_name());
--- a/hotspot/src/share/vm/services/heapDumper.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/services/heapDumper.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -899,6 +899,11 @@
assert(klass->oop_is_instance(), "not an InstanceKlass");
InstanceKlass* ik = (InstanceKlass*)klass;
+ // Ignore the class if it hasn't been initialized yet
+ if (!ik->is_linked()) {
+ return;
+ }
+
writer->write_u1(HPROF_GC_CLASS_DUMP);
// class ID
--- a/hotspot/src/share/vm/shark/sharkBuilder.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -25,6 +25,8 @@
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTableModRefBS.hpp"
#include "memory/resourceArea.hpp"
#include "oops/method.hpp"
#include "runtime/os.hpp"
@@ -442,7 +444,7 @@
Unimplemented();
CreateStore(
- LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
+ LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
CreateIntToPtr(
CreateAdd(
LLVMValue::intptr_constant(
--- a/hotspot/src/share/vm/shark/sharkBuilder.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/shark/sharkBuilder.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -27,8 +27,6 @@
#define SHARE_VM_SHARK_SHARKBUILDER_HPP
#include "ci/ciType.hpp"
-#include "gc/shared/barrierSet.hpp"
-#include "gc/shared/cardTableModRefBS.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
#include "shark/sharkCodeBuffer.hpp"
@@ -38,6 +36,8 @@
#include "utilities/debug.hpp"
#include "utilities/sizes.hpp"
+class BarrierSet;
+
class SharkBuilder : public llvm::IRBuilder<> {
friend class SharkCompileInvariants;
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Aug 10 18:58:25 2015 -0700
@@ -306,6 +306,30 @@
#endif // ZERO
}
+void VMError::print_oom_reasons(outputStream* st) {
+ st->print_cr("# Possible reasons:");
+ st->print_cr("# The system is out of physical RAM or swap space");
+ st->print_cr("# In 32 bit mode, the process size limit was hit");
+ st->print_cr("# Possible solutions:");
+ st->print_cr("# Reduce memory load on the system");
+ st->print_cr("# Increase physical memory or swap space");
+ st->print_cr("# Check if swap backing store is full");
+ st->print_cr("# Use 64 bit Java on a 64 bit OS");
+ st->print_cr("# Decrease Java heap size (-Xmx/-Xms)");
+ st->print_cr("# Decrease number of Java threads");
+ st->print_cr("# Decrease Java thread stack sizes (-Xss)");
+ st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize=");
+ st->print_cr("# This output file may be truncated or incomplete.");
+}
+
+const char* VMError::gc_mode() {
+ if (UseG1GC) return "g1 gc";
+ if (UseParallelGC) return "parallel gc";
+ if (UseConcMarkSweepGC) return "concurrent mark sweep gc";
+ if (UseSerialGC) return "serial gc";
+ return "ERROR in GC mode";
+}
+
// This is the main function to report a fatal error. Only one thread can
// call this function, so we don't need to worry about MT-safety. But it's
// possible that the error handler itself may crash or die on an internal
@@ -358,21 +382,21 @@
// test secondary error handling. Test it twice, to test that resetting
// error handler after a secondary crash works.
- STEP(11, "(test secondary crash 1)")
+ STEP(20, "(test secondary crash 1)")
if (_verbose && TestCrashInErrorHandler != 0) {
st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
TestCrashInErrorHandler);
controlled_crash(TestCrashInErrorHandler);
}
- STEP(12, "(test secondary crash 2)")
+ STEP(30, "(test secondary crash 2)")
if (_verbose && TestCrashInErrorHandler != 0) {
st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
TestCrashInErrorHandler);
controlled_crash(TestCrashInErrorHandler);
}
- STEP(13, "(test safefetch in error handler)")
+ STEP(40, "(test safefetch in error handler)")
// test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
// to test that resetting the signal handler works correctly.
if (_verbose && TestSafeFetchInErrorHandler) {
@@ -393,7 +417,7 @@
}
#endif // PRODUCT
- STEP(15, "(printing type of error)")
+ STEP(50, "(printing type of error)")
switch(_id) {
case OOM_MALLOC_ERROR:
@@ -418,19 +442,7 @@
}
// In error file give some solutions
if (_verbose) {
- st->print_cr("# Possible reasons:");
- st->print_cr("# The system is out of physical RAM or swap space");
- st->print_cr("# In 32 bit mode, the process size limit was hit");
- st->print_cr("# Possible solutions:");
- st->print_cr("# Reduce memory load on the system");
- st->print_cr("# Increase physical memory or swap space");
- st->print_cr("# Check if swap backing store is full");
- st->print_cr("# Use 64 bit Java on a 64 bit OS");
- st->print_cr("# Decrease Java heap size (-Xmx/-Xms)");
- st->print_cr("# Decrease number of Java threads");
- st->print_cr("# Decrease Java thread stack sizes (-Xss)");
- st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize=");
- st->print_cr("# This output file may be truncated or incomplete.");
+ print_oom_reasons(st);
} else {
return; // that's enough for the screen
}
@@ -440,7 +452,7 @@
break;
}
- STEP(20, "(printing exception/signal name)")
+ STEP(60, "(printing exception/signal name)")
st->print_cr("#");
st->print("# ");
@@ -470,14 +482,14 @@
}
}
- STEP(30, "(printing current thread and pid)")
+ STEP(70, "(printing current thread and pid)")
// process id, thread id
st->print(", pid=%d", os::current_process_id());
st->print(", tid=" INTPTR_FORMAT, os::current_thread_id());
st->cr();
- STEP(40, "(printing error message)")
+ STEP(80, "(printing error message)")
if (should_report_bug(_id)) { // already printed the message.
// error message
@@ -488,7 +500,7 @@
}
}
- STEP(50, "(printing Java version string)")
+ STEP(90, "(printing Java version string)")
// VM version
st->print_cr("#");
@@ -498,15 +510,18 @@
const char* runtime_version = JDK_Version::runtime_version() != NULL ?
JDK_Version::runtime_version() : "";
st->print_cr("# JRE version: %s (%s) (build %s)", runtime_name, buf, runtime_version);
- st->print_cr("# Java VM: %s (%s %s %s %s)",
+ // This is the long version with some default settings added
+ st->print_cr("# Java VM: %s (%s, %s%s%s, %s, %s)",
Abstract_VM_Version::vm_name(),
Abstract_VM_Version::vm_release(),
Abstract_VM_Version::vm_info_string(),
- Abstract_VM_Version::vm_platform_string(),
- UseCompressedOops ? "compressed oops" : ""
+ TieredCompilation ? ", tiered" : "",
+ UseCompressedOops ? ", compressed oops" : "",
+ gc_mode(),
+ Abstract_VM_Version::vm_platform_string()
);
- STEP(60, "(printing problematic frame)")
+ STEP(100, "(printing problematic frame)")
// Print current frame if we have a context (i.e. it's a crash)
if (_context) {
@@ -517,7 +532,8 @@
st->cr();
st->print_cr("#");
}
- STEP(63, "(printing core file information)")
+
+ STEP(110, "(printing core file information)")
st->print("# ");
if (CreateCoredumpOnCrash) {
if (coredump_status) {
@@ -531,13 +547,42 @@
st->cr();
st->print_cr("#");
- STEP(65, "(printing bug submit message)")
+ STEP(120, "(printing bug submit message)")
if (should_report_bug(_id) && _verbose) {
print_bug_submit_message(st, _thread);
}
- STEP(70, "(printing thread)" )
+ STEP(130, "(printing summary)" )
+
+ if (_verbose) {
+ st->cr();
+ st->print_cr("--------------- S U M M A R Y ------------");
+ st->cr();
+ }
+
+ STEP(140, "(printing VM option summary)" )
+
+ if (_verbose) {
+ // VM options
+ Arguments::print_summary_on(st);
+ st->cr();
+ }
+
+ STEP(150, "(printing summary machine and OS info)")
+
+ if (_verbose) {
+ os::print_summary_info(st, buf, sizeof(buf));
+ }
+
+
+ STEP(160, "(printing date and time)" )
+
+ if (_verbose) {
+ os::print_date_and_time(st, buf, sizeof(buf));
+ }
+
+ STEP(170, "(printing thread)" )
if (_verbose) {
st->cr();
@@ -545,7 +590,7 @@
st->cr();
}
- STEP(80, "(printing current thread)" )
+ STEP(180, "(printing current thread)" )
// current thread
if (_verbose) {
@@ -559,31 +604,20 @@
st->cr();
}
- STEP(90, "(printing siginfo)" )
+ STEP(190, "(printing current compile task)" )
- // signal no, signal code, address that caused the fault
- if (_verbose && _siginfo) {
- os::print_siginfo(st, _siginfo);
- st->cr();
+ if (_verbose && _thread && _thread->is_Compiler_thread()) {
+ CompilerThread* t = (CompilerThread*)_thread;
+ if (t->task()) {
+ st->cr();
+ st->print_cr("Current CompileTask:");
+ t->task()->print_line_on_error(st, buf, sizeof(buf));
+ st->cr();
+ }
}
- STEP(100, "(printing registers, top of stack, instructions near pc)")
- // registers, top of stack, instructions near pc
- if (_verbose && _context) {
- os::print_context(st, _context);
- st->cr();
- }
-
- STEP(105, "(printing register info)")
-
- // decode register contents if possible
- if (_verbose && _context && Universe::is_fully_initialized()) {
- os::print_register_info(st, _context);
- st->cr();
- }
-
- STEP(110, "(printing stack bounds)" )
+ STEP(200, "(printing stack bounds)" )
if (_verbose) {
st->print("Stack: ");
@@ -614,7 +648,7 @@
st->cr();
}
- STEP(120, "(printing native stack)" )
+ STEP(210, "(printing native stack)" )
if (_verbose) {
if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
@@ -628,13 +662,13 @@
}
}
- STEP(130, "(printing Java stack)" )
+ STEP(220, "(printing Java stack)" )
if (_verbose && _thread && _thread->is_Java_thread()) {
print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
}
- STEP(135, "(printing target Java thread stack)" )
+ STEP(230, "(printing target Java thread stack)" )
// printing Java thread stack trace if it is involved in GC crash
if (_verbose && _thread && (_thread->is_Named_thread())) {
@@ -645,7 +679,32 @@
}
}
- STEP(140, "(printing VM operation)" )
+ STEP(240, "(printing siginfo)" )
+
+ // signal no, signal code, address that caused the fault
+ if (_verbose && _siginfo) {
+ st->cr();
+ os::print_siginfo(st, _siginfo);
+ st->cr();
+ }
+
+ STEP(250, "(printing register info)")
+
+ // decode register contents if possible
+ if (_verbose && _context && Universe::is_fully_initialized()) {
+ os::print_register_info(st, _context);
+ st->cr();
+ }
+
+ STEP(260, "(printing registers, top of stack, instructions near pc)")
+
+ // registers, top of stack, instructions near pc
+ if (_verbose && _context) {
+ os::print_context(st, _context);
+ st->cr();
+ }
+
+ STEP(270, "(printing VM operation)" )
if (_verbose && _thread && _thread->is_VM_thread()) {
VMThread* t = (VMThread*)_thread;
@@ -657,19 +716,7 @@
}
}
- STEP(150, "(printing current compile task)" )
-
- if (_verbose && _thread && _thread->is_Compiler_thread()) {
- CompilerThread* t = (CompilerThread*)_thread;
- if (t->task()) {
- st->cr();
- st->print_cr("Current CompileTask:");
- t->task()->print_line_on_error(st, buf, sizeof(buf));
- st->cr();
- }
- }
-
- STEP(160, "(printing process)" )
+ STEP(280, "(printing process)" )
if (_verbose) {
st->cr();
@@ -677,7 +724,7 @@
st->cr();
}
- STEP(170, "(printing all threads)" )
+ STEP(290, "(printing all threads)" )
// all threads
if (_verbose && _thread) {
@@ -685,7 +732,7 @@
st->cr();
}
- STEP(175, "(printing VM state)" )
+ STEP(300, "(printing VM state)" )
if (_verbose) {
// Safepoint state
@@ -707,7 +754,7 @@
st->cr();
}
- STEP(180, "(printing owned locks on error)" )
+ STEP(310, "(printing owned locks on error)" )
// mutexes/monitors that currently have an owner
if (_verbose) {
@@ -715,7 +762,7 @@
st->cr();
}
- STEP(182, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
+ STEP(320, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
if (_verbose && Exceptions::has_exception_counts()) {
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
@@ -723,7 +770,7 @@
st->cr();
}
- STEP(185, "(printing compressed oops mode")
+ STEP(330, "(printing compressed oops mode")
if (_verbose && UseCompressedOops) {
Universe::print_compressed_oops_mode(st);
@@ -733,7 +780,7 @@
st->cr();
}
- STEP(190, "(printing heap information)" )
+ STEP(340, "(printing heap information)" )
if (_verbose && Universe::is_fully_initialized()) {
Universe::heap()->print_on_error(st);
@@ -743,7 +790,7 @@
st->cr();
}
- STEP(195, "(printing code cache information)" )
+ STEP(350, "(printing code cache information)" )
if (_verbose && Universe::is_fully_initialized()) {
// print code cache information before vm abort
@@ -751,14 +798,14 @@
st->cr();
}
- STEP(200, "(printing ring buffers)" )
+ STEP(360, "(printing ring buffers)" )
if (_verbose) {
Events::print_all(st);
st->cr();
}
- STEP(205, "(printing dynamic libraries)" )
+ STEP(370, "(printing dynamic libraries)" )
if (_verbose) {
// dynamic libraries, or memory map
@@ -766,7 +813,7 @@
st->cr();
}
- STEP(210, "(printing VM options)" )
+ STEP(380, "(printing VM options)" )
if (_verbose) {
// VM options
@@ -774,33 +821,33 @@
st->cr();
}
- STEP(215, "(printing warning if internal testing API used)" )
+ STEP(390, "(printing warning if internal testing API used)" )
if (WhiteBox::used()) {
st->print_cr("Unsupported internal testing APIs have been used.");
st->cr();
}
- STEP(220, "(printing environment variables)" )
+ STEP(400, "(printing all environment variables)" )
if (_verbose) {
os::print_environment_variables(st, env_list);
st->cr();
}
- STEP(225, "(printing signal handlers)" )
+ STEP(410, "(printing signal handlers)" )
if (_verbose) {
os::print_signal_handlers(st, buf, sizeof(buf));
st->cr();
}
- STEP(228, "(Native Memory Tracking)" )
+ STEP(420, "(Native Memory Tracking)" )
if (_verbose) {
MemTracker::error_report(st);
}
- STEP(230, "" )
+ STEP(430, "(printing system)" )
if (_verbose) {
st->cr();
@@ -808,48 +855,39 @@
st->cr();
}
- STEP(240, "(printing OS information)" )
+ STEP(440, "(printing OS information)" )
if (_verbose) {
os::print_os_info(st);
st->cr();
}
- STEP(250, "(printing CPU info)" )
+ STEP(450, "(printing CPU info)" )
if (_verbose) {
os::print_cpu_info(st, buf, sizeof(buf));
st->cr();
}
- STEP(260, "(printing memory info)" )
+ STEP(460, "(printing memory info)" )
if (_verbose) {
os::print_memory_info(st);
st->cr();
}
- STEP(270, "(printing internal vm info)" )
+ STEP(470, "(printing internal vm info)" )
if (_verbose) {
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
st->cr();
}
- STEP(280, "(printing date and time)" )
-
- if (_verbose) {
- os::print_date_and_time(st, buf, sizeof(buf));
- st->cr();
- }
-
-#ifndef PRODUCT
// print a defined marker to show that error handling finished correctly.
- STEP(290, "(printing end marker)" )
+ STEP(480, "(printing end marker)" )
if (_verbose) {
st->print_cr("END.");
}
-#endif
END
--- a/hotspot/src/share/vm/utilities/vmError.hpp Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.hpp Mon Aug 10 18:58:25 2015 -0700
@@ -89,6 +89,9 @@
static void print_stack_trace(outputStream* st, JavaThread* jt,
char* buf, int buflen, bool verbose = false);
+ static const char* gc_mode();
+ static void print_oom_reasons(outputStream* st);
+
// accessor
const char* message() const { return _message; }
const char* detail_msg() const { return _detail_msg; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,135 @@
+/*
+ * 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 jdk.test.lib.*;
+
+/*
+ * @test CheckCheckCICompilerCount
+ * @bug 8130858
+ * @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ * @run main CheckCICompilerCount
+ */
+
+public class CheckCICompilerCount {
+ private static final String[][] NON_TIERED_ARGUMENTS = {
+ {
+ "-XX:-TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=0",
+ "-version"
+ },
+ {
+ "-XX:-TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-version"
+ }
+ };
+
+ private static final String[][] NON_TIERED_EXPECTED_OUTPUTS = {
+ {
+ "CICompilerCount=0 must be at least 1",
+ "Improperly specified VM option 'CICompilerCount=0'"
+ },
+ {
+ "intx CICompilerCount := 1 {product}"
+ }
+ };
+
+ private static final int[] NON_TIERED_EXIT = {
+ 1,
+ 0
+ };
+
+ private static final String[][] TIERED_ARGUMENTS = {
+ {
+ "-XX:+TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-version"
+ },
+ {
+ "-XX:+TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=2",
+ "-version"
+ }
+ };
+
+ private static final String[][] TIERED_EXPECTED_OUTPUTS = {
+ {
+ "CICompilerCount=1 must be at least 2",
+ "Improperly specified VM option 'CICompilerCount=1'"
+ },
+ {
+ "intx CICompilerCount := 2 {product}"
+ }
+ };
+
+ private static final int[] TIERED_EXIT = {
+ 1,
+ 0
+ };
+
+ private static void verifyValidOption(String[] arguments, String[] expected_outputs, int exit, boolean tiered) throws Exception {
+ ProcessBuilder pb;
+ OutputAnalyzer out;
+
+ pb = ProcessTools.createJavaProcessBuilder(arguments);
+ out = new OutputAnalyzer(pb.start());
+
+ try {
+ out.shouldHaveExitValue(exit);
+ for (String expected_output : expected_outputs) {
+ out.shouldContain(expected_output);
+ }
+ } catch (RuntimeException e) {
+ // Check if tiered compilation is available in this JVM
+ // Version. Throw exception only if it is available.
+ if (!(tiered && out.getOutput().contains("TieredCompilation is disabled in this release."))) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (NON_TIERED_ARGUMENTS.length != NON_TIERED_EXPECTED_OUTPUTS.length || NON_TIERED_ARGUMENTS.length != NON_TIERED_EXIT.length) {
+ throw new RuntimeException("Test is set up incorrectly: length of arguments, expected outputs and exit codes in non-tiered mode of operation do not match.");
+ }
+
+ if (TIERED_ARGUMENTS.length != TIERED_EXPECTED_OUTPUTS.length || TIERED_ARGUMENTS.length != TIERED_EXIT.length) {
+ throw new RuntimeException("Test is set up incorrectly: length of arguments, expected outputs and exit codes in tiered mode of operation do not match.");
+ }
+
+ for (int i = 0; i < NON_TIERED_ARGUMENTS.length; i++) {
+ verifyValidOption(NON_TIERED_ARGUMENTS[i], NON_TIERED_EXPECTED_OUTPUTS[i], NON_TIERED_EXIT[i], false);
+ }
+
+ for (int i = 0; i < TIERED_ARGUMENTS.length; i++) {
+ verifyValidOption(TIERED_ARGUMENTS[i], TIERED_EXPECTED_OUTPUTS[i], TIERED_EXIT[i], true);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,126 @@
+/*
+ * 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.lang.reflect.Executable;
+import java.util.concurrent.Callable;
+import java.util.Objects;
+/*
+ * @test
+ * @bug 8130832
+ * @library /testlibrary /../../test/lib /compiler/whitebox /compiler/testlibrary
+ * @build IntrinsicAvailableTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * -XX:+UseCRC32Intrinsics
+ * IntrinsicAvailableTest
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * -XX:-UseCRC32Intrinsics
+ * IntrinsicAvailableTest
+ */
+public class IntrinsicAvailableTest extends CompilerWhiteBoxTest {
+ protected String VMName;
+
+ public IntrinsicAvailableTest(IntrinsicAvailableTestTestCase testCase) {
+ super(testCase);
+ VMName = System.getProperty("java.vm.name");
+ }
+
+ public static class IntrinsicAvailableTestTestCase implements TestCase {
+
+ public String name() {
+ return "IntrinsicAvailableTestTestCase";
+ }
+
+ public Executable getExecutable() {
+ // Using a single method to test the
+ // WhiteBox.isIntrinsicAvailable(Executable method, int compLevel)
+ // call for the compilation level corresponding to both the C1 and C2
+ // compiler keeps the current test simple.
+ //
+ // The tested method is java.util.zip.CRC32.update(int, int) because
+ // both C1 and C2 define an intrinsic for the method and
+ // the UseCRC32Intrinsics flag can be used to enable/disable
+ // intrinsification of the method in both product and fastdebug
+ // builds.
+ try {
+ return Class.forName("java.util.zip.CRC32").getDeclaredMethod("update", int.class, int.class);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, method unavailable. " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, class unavailable. " + e);
+ }
+ }
+
+ public Callable<Integer> getCallable() {
+ return null;
+ }
+
+ public boolean isOsr() {
+ return false;
+ }
+
+ }
+
+ protected void checkIntrinsicForCompilationLevel(Executable method, int compLevel) throws Exception {
+ boolean intrinsicEnabled = Boolean.valueOf(getVMOption("UseCRC32Intrinsics"));
+ boolean intrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(method,
+ compLevel);
+
+ String intrinsicEnabledMessage = intrinsicEnabled ? "enabled" : "disabled";
+ String intrinsicAvailableMessage = intrinsicAvailable ? "available" : "not available";
+
+ if (intrinsicEnabled == intrinsicAvailable) {
+ System.out.println("Expected result: intrinsic for java.util.zip.CRC32.update() is " +
+ intrinsicEnabledMessage + " and intrinsic is " + intrinsicAvailableMessage +
+ " at compilation level " + compLevel);
+ } else {
+ throw new RuntimeException("Unexpected result: intrinsic for java.util.zip.CRC32.update() is " +
+ intrinsicEnabledMessage + " but intrinsic is " + intrinsicAvailableMessage +
+ " at compilation level " + compLevel);
+ }
+ }
+
+ protected boolean isServerVM() {
+ return VMName.toLowerCase().contains("server");
+ }
+
+ public void test() throws Exception {
+ Executable intrinsicMethod = testCase.getExecutable();
+ if (isServerVM()) {
+ if (TIERED_COMPILATION) {
+ checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+ }
+ checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_FULL_OPTIMIZATION);
+ } else {
+ checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+ }
+ }
+
+ public static void main(String args[]) throws Exception {
+ new IntrinsicAvailableTest(new IntrinsicAvailableTestTestCase()).test();
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Mon Aug 10 18:58:25 2015 -0700
@@ -67,7 +67,7 @@
compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
}
- if (!isIntrinsicSupported()) {
+ if (!isIntrinsicAvailable()) {
expectedIntrinsicCount = 0;
}
break;
@@ -114,7 +114,11 @@
}
}
- protected abstract boolean isIntrinsicSupported();
+ // An intrinsic is available if:
+ // - the intrinsic is enabled (by using the appropriate command-line flag) and
+ // - the intrinsic is supported by the VM (i.e., the platform on which the VM is
+ // running provides the instructions necessary for the VM to generate the intrinsic).
+ protected abstract boolean isIntrinsicAvailable();
protected abstract String getIntrinsicId();
@@ -123,14 +127,20 @@
}
static class IntTest extends IntrinsicBase {
+
+ protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
+
protected IntTest(MathIntrinsic.IntIntrinsic testCase) {
super(testCase);
+ // Only the C2 compiler intrinsifies exact math methods
+ // so check if the intrinsics are available with C2.
+ isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
+ COMP_LEVEL_FULL_OPTIMIZATION);
}
@Override
- protected boolean isIntrinsicSupported() {
- return isServerVM() && Boolean.valueOf(useMathExactIntrinsics)
- && (Platform.isX86() || Platform.isX64() || Platform.isAArch64());
+ protected boolean isIntrinsicAvailable() {
+ return isIntrinsicAvailable;
}
@Override
@@ -140,14 +150,20 @@
}
static class LongTest extends IntrinsicBase {
+
+ protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
+
protected LongTest(MathIntrinsic.LongIntrinsic testCase) {
super(testCase);
+ // Only the C2 compiler intrinsifies exact math methods
+ // so check if the intrinsics are available with C2.
+ isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
+ COMP_LEVEL_FULL_OPTIMIZATION);
}
@Override
- protected boolean isIntrinsicSupported() {
- return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) &&
- (Platform.isX64() || Platform.isPPC() || Platform.isAArch64());
+ protected boolean isIntrinsicAvailable() {
+ return isIntrinsicAvailable;
}
@Override
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MathIntrinsic.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MathIntrinsic.java Mon Aug 10 18:58:25 2015 -0700
@@ -29,11 +29,21 @@
enum IntIntrinsic implements CompilerWhiteBoxTest.TestCase {
Add {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("addExact", int.class, int.class);
+ }
+
+ @Override
Object execMathMethod() {
return intR = Math.addExact(int1, int2);
}
},
- Subtract {
+ Subtract {
+ @Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("subtractExact", int.class, int.class);
+ }
+
@Override
Object execMathMethod() {
return intR = Math.subtractExact(int1, int2);
@@ -41,34 +51,66 @@
},
Multiply {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("multiplyExact", int.class, int.class);
+ }
+
+ @Override
Object execMathMethod() {
return intR = Math.multiplyExact(int1, int2);
}
},
Increment {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("incrementExact", int.class);
+ }
+
+ @Override
Object execMathMethod() {
return intR = Math.incrementExact(int1);
}
},
Decrement {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("decrementExact", int.class);
+ }
+
+ @Override
Object execMathMethod() {
return intR = Math.decrementExact(int1);
}
},
Negate {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("negateExact", int.class);
+ }
+
+ @Override
Object execMathMethod() {
return intR = Math.negateExact(int1);
}
};
+
protected int int1;
protected int int2;
protected int intR;
+ abstract Executable testMethod() throws NoSuchMethodException, ClassNotFoundException;
abstract Object execMathMethod();
+ public Executable getTestMethod() {
+ try {
+ return testMethod();
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, no such method: " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, no such class: " + e);
+ }
+ }
+
@Override
public Executable getExecutable() {
try {
@@ -93,36 +135,66 @@
enum LongIntrinsic implements CompilerWhiteBoxTest.TestCase {
Add {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("addExact", long.class, long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.addExact(long1, long2);
}
},
Subtract {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("subtractExact", long.class, long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.subtractExact(long1, long2);
}
},
Multiply {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("multiplyExact", long.class, long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.multiplyExact(long1, long2);
}
},
Increment {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("incrementExact", long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.incrementExact(long1);
}
},
Decrement {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("decrementExact", long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.decrementExact(long1);
}
},
Negate {
@Override
+ Executable testMethod() throws NoSuchMethodException, ClassNotFoundException {
+ return Class.forName("java.lang.Math").getDeclaredMethod("negateExact", long.class);
+ }
+
+ @Override
Object execMathMethod() {
return longR = Math.negateExact(long1);
}
@@ -131,8 +203,19 @@
protected long long2;
protected long longR;
+ abstract Executable testMethod() throws NoSuchMethodException, ClassNotFoundException;
abstract Object execMathMethod();
+ public Executable getTestMethod() {
+ try {
+ return testMethod();
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, no such method: " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, no such class: " + e);
+ }
+ }
+
@Override
public Executable getExecutable() {
try {
--- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java Mon Aug 10 18:58:25 2015 -0700
@@ -94,29 +94,47 @@
output.shouldHaveExitValue(0);
}
+ private static long gcd(long x, long y) {
+ while (x > 0) {
+ long t = x;
+ x = y % x;
+ y = t;
+ }
+ return y;
+ }
+
+ private static long lcm(long x, long y) {
+ return x * (y / gcd(x, y));
+ }
+
public static void main(String[] args) throws Exception {
if (!Platform.isDebugBuild()) {
System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option.");
return;
}
+ // Size that a single card covers.
+ final int cardSize = 512;
WhiteBox wb = WhiteBox.getWhiteBox();
smallPageSize = wb.getVMPageSize();
largePageSize = wb.getVMLargePageSize();
allocGranularity = wb.getVMAllocationGranularity();
+ final long heapAlignment = lcm(cardSize * smallPageSize, largePageSize);
if (largePageSize == 0) {
System.out.println("Skip tests because large page support does not seem to be available on this platform.");
return;
}
+ if (largePageSize == smallPageSize) {
+ System.out.println("Skip tests because large page support does not seem to be available on this platform." +
+ "Small and large page size are the same.");
+ return;
+ }
// To get large pages for the card table etc. we need at least a 1G heap (with 4k page size).
// 32 bit systems will have problems reserving such an amount of contiguous space, so skip the
// test there.
if (!Platform.is32bit()) {
- // Size that a single card covers.
- final int cardSize = 512;
-
final long heapSizeForCardTableUsingLargePages = largePageSize * cardSize;
final long heapSizeDiffForCardTable = Math.max(Math.max(allocGranularity * cardSize, HEAP_REGION_SIZE), largePageSize);
@@ -131,7 +149,8 @@
// everywhere.
final int bitmapTranslationFactor = 8 * 8; // ObjectAlignmentInBytes * BitsPerByte
final long heapSizeForBitmapUsingLargePages = largePageSize * bitmapTranslationFactor;
- final long heapSizeDiffForBitmap = Math.max(Math.max(allocGranularity * bitmapTranslationFactor, HEAP_REGION_SIZE), largePageSize);
+ final long heapSizeDiffForBitmap = Math.max(Math.max(allocGranularity * bitmapTranslationFactor, HEAP_REGION_SIZE),
+ Math.max(largePageSize, heapAlignment));
Asserts.assertGT(heapSizeForBitmapUsingLargePages, heapSizeDiffForBitmap,
"To test we would require to use an invalid heap size");
--- a/hotspot/test/runtime/CompressedOops/ObjectAlignment.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/runtime/CompressedOops/ObjectAlignment.java Mon Aug 10 18:58:25 2015 -0700
@@ -48,7 +48,6 @@
.shouldHaveExitValue(1);
testObjectAlignment(-1)
- .shouldContain("must be power of 2")
.shouldContain("outside the allowed range")
.shouldHaveExitValue(1);
@@ -75,4 +74,4 @@
"-version");
return new OutputAnalyzer(pb.start());
}
-}
\ No newline at end of file
+}
--- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Mon Aug 10 18:58:25 2015 -0700
@@ -38,7 +38,7 @@
public class CreateCoredumpOnCrash {
private static class Crasher {
public static void main(String[] args) {
- Utils.getUnsafe().getInt(0);
+ Utils.getUnsafe().putInt(0L, 0);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,193 @@
+/*
+ * 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 8087315
+ * @summary Get old method's stack trace elements after GC
+ * @library /testlibrary
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+public class RedefineRunningMethodsWithBacktrace {
+
+ public static String newB =
+ "class RedefineRunningMethodsWithBacktrace$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethodsWithBacktrace$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ static class B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try {
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void throwable() {
+ // add some stuff to the original constant pool
+ String s1 = new String ("string1");
+ String s2 = new String ("string2");
+ String s3 = new String ("string3");
+ String s4 = new String ("string4");
+ String s5 = new String ("string5");
+ String s6 = new String ("string6");
+ String s7 = new String ("string7");
+ String s8 = new String ("string8");
+ String s9 = new String ("string9");
+ String s10 = new String ("string10");
+ String s11 = new String ("string11");
+ String s12 = new String ("string12");
+ String s13 = new String ("string13");
+ String s14 = new String ("string14");
+ String s15 = new String ("string15");
+ String s16 = new String ("string16");
+ String s17 = new String ("string17");
+ String s18 = new String ("string18");
+ String s19 = new String ("string19");
+ throw new RuntimeException("throwable called");
+ }
+ }
+
+ private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
+ System.out.println("touchRedefinedMethodInBacktrace: ");
+ throwable.printStackTrace(); // this actually crashes with the bug in
+ // java_lang_StackTraceElement::create()
+
+ // Make sure that we can convert the backtrace, which is referring to
+ // the redefined method, to a StrackTraceElement[] without crashing.
+ StackTraceElement[] stackTrace = throwable.getStackTrace();
+ for (int i = 0; i < stackTrace.length; i++) {
+ StackTraceElement frame = stackTrace[i];
+ assertNotNull(frame.getClassName(),
+ "\nTest failed: trace[" + i + "].getClassName() returned null");
+ assertNotNull(frame.getMethodName(),
+ "\nTest failed: trace[" + i + "].getMethodName() returned null");
+ }
+ }
+
+ private static Throwable getThrowableInB() {
+ Throwable t = null;
+ try {
+ B.throwable();
+ } catch (Exception e) {
+ t = e;
+ // Don't print here because Throwable will cache the constructed stacktrace
+ // e.printStackTrace();
+ }
+ return t;
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ B.infinite();
+ }
+ }.start();
+
+ Throwable t1 = getThrowableInB();
+
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ System.gc();
+
+ Throwable t2 = getThrowableInB();
+
+ B.infinite();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(B.class, evenNewerB);
+ System.gc();
+
+ Throwable t3 = getThrowableInB();
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ touchRedefinedMethodInBacktrace(t1);
+ touchRedefinedMethodInBacktrace(t2);
+ touchRedefinedMethodInBacktrace(t3);
+
+ // purge should clean everything up.
+ B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- a/hotspot/test/runtime/contended/Options.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/runtime/contended/Options.java Mon Aug 10 18:58:25 2015 -0700
@@ -55,7 +55,6 @@
output = new OutputAnalyzer(pb.start());
output.shouldContain("ContendedPaddingWidth");
output.shouldContain("outside the allowed range");
- output.shouldContain("must be a multiple of 8");
output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=0", "-version");
@@ -90,7 +89,6 @@
output = new OutputAnalyzer(pb.start());
output.shouldContain("ContendedPaddingWidth");
output.shouldContain("outside the allowed range");
- output.shouldContain("must be a multiple of 8");
output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8200", "-version"); // 8192+8 = 8200
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/PrimIntArray.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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 8129895
+ * @summary Throw VerifyError when checking assignability of primitive arrays
+ * that are not identical. For example, [I is not assignable to [B.
+ * @compile primArray.jasm
+ * @compile primArray49.jasm
+ * @run main/othervm -Xverify:all PrimIntArray
+ */
+
+// Test that an int[] is not assignable to byte[].
+public class PrimIntArray {
+
+ public static void main(String args[]) throws Throwable {
+ System.out.println("Regression test for bug 8129895");
+
+ try {
+ Class newClass = Class.forName("primArray");
+ throw new RuntimeException("Expected VerifyError exception not thrown with new verifier");
+ } catch (java.lang.VerifyError e) {
+ System.out.println("Test PrimIntArray passed with new verifier");
+ }
+
+ try {
+ Class newClass = Class.forName("primArray49");
+ throw new RuntimeException("Expected VerifyError exception not thrown by old verifier");
+ } catch (java.lang.VerifyError e) {
+ System.out.println("Test PrimIntArray passed with old verifier");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/primArray.jasm Mon Aug 10 18:58:25 2015 -0700
@@ -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.
+ *
+ */
+
+// Method castToByteArray() tries to return an array of ints when an array
+// of bytes is expected.
+super class primArray
+version 52:0
+{
+
+ public Method "<init>":"()V"
+ stack 1 locals 1
+ {
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+ }
+
+ public static Method castToByteArray:"([I)[B"
+ stack 1 locals 1
+ {
+ aload_0;
+ areturn;
+ }
+
+} // end Class primArray
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/verifier/primArray49.jasm Mon Aug 10 18:58:25 2015 -0700
@@ -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.
+ *
+ */
+
+// Method castToByteArray() tries to return an array of ints when an array
+// of bytes is expected.
+super class primArray49
+version 49:0
+{
+
+ public Method "<init>":"()V"
+ stack 1 locals 1
+ {
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+ }
+
+ public static Method castToByteArray:"([I)[B"
+ stack 1 locals 1
+ {
+ aload_0;
+ areturn;
+ }
+
+} // end Class primArray49
--- a/hotspot/test/serviceability/sa/TestStackTrace.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java Mon Aug 10 18:58:25 2015 -0700
@@ -34,7 +34,6 @@
* @test
* @library /../../test/lib/share/classes
* @library /testlibrary
- * @ignore 8129971
* @build jdk.test.lib.*
* @build jdk.test.lib.apps.*
* @run main TestStackTrace
--- a/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java Mon Aug 10 18:58:25 2015 -0700
@@ -31,11 +31,9 @@
import java.util.Arrays;
import javax.tools.ForwardingJavaFileManager;
-import javax.tools.ForwardingJavaFileManager;
import javax.tools.FileObject;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
-import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
--- a/hotspot/test/testlibrary/jdk/test/lib/Platform.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/Platform.java Mon Aug 10 18:58:25 2015 -0700
@@ -24,7 +24,6 @@
package jdk.test.lib;
import java.util.regex.Pattern;
-import jdk.test.lib.Utils;
public class Platform {
private static final String osName = System.getProperty("os.name");
--- a/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Mon Aug 10 18:58:25 2015 -0700
@@ -27,8 +27,6 @@
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Aug 06 13:00:45 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Mon Aug 10 18:58:25 2015 -0700
@@ -24,9 +24,6 @@
package jdk.test.lib;
import static jdk.test.lib.Asserts.assertTrue;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
@@ -58,12 +55,12 @@
public static final String NEW_LINE = System.getProperty("line.separator");
/**
- * Returns the value of 'test.vm.opts'system property.
+ * Returns the value of 'test.vm.opts' system property.
*/
public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
/**
- * Returns the value of 'test.java.opts'system property.
+ * Returns the value of 'test.java.opts' system property.
*/
public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
@@ -129,7 +126,7 @@
/**
* Returns the default JTReg arguments for a jvm running a test.
* This is the combination of JTReg arguments test.vm.opts and test.java.opts.
- * @return An array of options, or an empty array if no opptions.
+ * @return An array of options, or an empty array if no options.
*/
public static String[] getTestJavaOpts() {
List<String> opts = new ArrayList<String>();
@@ -276,7 +273,7 @@
* 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
*
* @param key A regular expression to search for.
- * @return The found pid, or -1 if Enot found.
+ * @return The found pid, or -1 if not found.
* @throws Exception If multiple matching jvms are found.
*/
public static int tryFindJvmPid(String key) throws Throwable {
@@ -392,7 +389,7 @@
* @param condition, a condition to wait for
* @param timeout a time in milliseconds to wait for condition to be true
* specifying -1 will wait forever
- * @return condition value, to determine if wait was successfull
+ * @return condition value, to determine if wait was successful
*/
public static final boolean waitForCondition(BooleanSupplier condition,
long timeout) {
@@ -406,7 +403,7 @@
* @param timeout a time in milliseconds to wait for condition to be true,
* specifying -1 will wait forever
* @param sleepTime a time to sleep value in milliseconds
- * @return condition value, to determine if wait was successfull
+ * @return condition value, to determine if wait was successful
*/
public static final boolean waitForCondition(BooleanSupplier condition,
long timeout, long sleepTime) {
--- a/jaxp/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/jaxp/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -318,3 +318,4 @@
be5efc34a43bdd982d1cbe11cb2f6d6a060dde60 jdk9-b73
eadcb2b55cd1daf77625813aad0f6f3967b1528a jdk9-b74
16b5e696f948cd8aa9b3afdb686ddffd48bd17a8 jdk9-b75
+36801a89a04201b59874ec776ffe85d6253c9ab5 jdk9-b76
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/Version.java Thu Aug 06 13:00:45 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2003-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: Version.java,v 1.1.2.1 2005/08/01 02:11:19 jeffsuttor Exp $
- */
-package com.sun.org.apache.xalan.internal;
-
-/**
- * Administrative class to keep track of the version number of
- * the Xalan release.
- * <P>This class implements the upcoming standard of having
- * org.apache.project-name.Version.getVersion() be a standard way
- * to get version information. This class will replace the older
- * com.sun.org.apache.xalan.internal.processor.Version class.</P>
- * <P>See also: com/sun/org/apache/xalan/internal/res/XSLTInfo.properties for
- * information about the version of the XSLT spec we support.</P>
- * @xsl.usage general
- */
-public class Version
-{
-
- /**
- * Get the basic version string for the current Xalan release.
- * Version String formatted like
- * <CODE>"<B>Xalan</B> <B>Java</B> v.r[.dd| <B>D</B>nn]"</CODE>.
- *
- * Futurework: have this read version info from jar manifest.
- *
- * @return String denoting our current version
- */
- public static String getVersion()
- {
- return getProduct()+" "+getImplementationLanguage()+" "
- +getMajorVersionNum()+"."+getReleaseVersionNum()+"."
- +( (getDevelopmentVersionNum() > 0) ?
- ("D"+getDevelopmentVersionNum()) : (""+getMaintenanceVersionNum()));
- }
-
- /**
- * Print the processor version to the command line.
- *
- * @param argv command line arguments, unused.
- */
- public static void _main(String argv[])
- {
- System.out.println(getVersion());
- }
-
- /**
- * Name of product: Xalan.
- */
- public static String getProduct()
- {
- return "Xalan";
- }
-
- /**
- * Implementation Language: Java.
- */
- public static String getImplementationLanguage()
- {
- return "Java";
- }
-
-
- /**
- * Major version number.
- * Version number. This changes only when there is a
- * significant, externally apparent enhancement from
- * the previous release. 'n' represents the n'th
- * version.
- *
- * Clients should carefully consider the implications
- * of new versions as external interfaces and behaviour
- * may have changed.
- */
- public static int getMajorVersionNum()
- {
- return 2;
-
- }
-
- /**
- * Release Number.
- * Release number. This changes when:
- * - a new set of functionality is to be added, eg,
- * implementation of a new W3C specification.
- * - API or behaviour change.
- * - its designated as a reference release.
- */
- public static int getReleaseVersionNum()
- {
- return 7;
- }
-
- /**
- * Maintenance Drop Number.
- * Optional identifier used to designate maintenance
- * drop applied to a specific release and contains
- * fixes for defects reported. It maintains compatibility
- * with the release and contains no API changes.
- * When missing, it designates the final and complete
- * development drop for a release.
- */
- public static int getMaintenanceVersionNum()
- {
- return 0;
- }
-
- /**
- * Development Drop Number.
- * Optional identifier designates development drop of
- * a specific release. D01 is the first development drop
- * of a new release.
- *
- * Development drops are works in progress towards a
- * compeleted, final release. A specific development drop
- * may not completely implement all aspects of a new
- * feature, which may take several development drops to
- * complete. At the point of the final drop for the
- * release, the D suffix will be omitted.
- *
- * Each 'D' drops can contain functional enhancements as
- * well as defect fixes. 'D' drops may not be as stable as
- * the final releases.
- */
- public static int getDevelopmentVersionNum()
- {
- try {
- if ((new String("")).length() == 0)
- return 0;
- else
- return Integer.parseInt("");
- } catch (NumberFormatException nfe) {
- return 0;
- }
- }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xslt/Process.java Thu Aug 06 13:00:45 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1226 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: Process.java,v 1.2.4.2 2005/09/15 18:21:57 jeffsuttor Exp $
- */
-package com.sun.org.apache.xalan.internal.xslt;
-
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.Vector;
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Source;
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.URIResolver;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import com.sun.org.apache.xalan.internal.Version;
-import com.sun.org.apache.xalan.internal.res.XSLMessages;
-import com.sun.org.apache.xalan.internal.res.XSLTErrorResources;
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.utils.ConfigurationError;
-import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
-
-//J2SE does not support Xalan interpretive
-/*
-import com.sun.org.apache.xalan.internal.trace.PrintTraceListener;
-import com.sun.org.apache.xalan.internal.trace.TraceManager;
-import com.sun.org.apache.xalan.internal.transformer.XalanProperties;
-*/
-
-import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- * The main() method handles the Xalan command-line interface.
- * @xsl.usage general
- */
-public class Process
-{
- /**
- * Prints argument options.
- *
- * @param resbundle Resource bundle
- */
- protected static void printArgOptions(ResourceBundle resbundle)
- {
- System.out.println(resbundle.getString("xslProc_option")); //"xslproc options: ");
- System.out.println("\n\t\t\t" + resbundle.getString("xslProc_common_options") + "\n");
- System.out.println(resbundle.getString("optionXSLTC")); //" [-XSLTC (use XSLTC for transformation)]
- System.out.println(resbundle.getString("optionIN")); //" [-IN inputXMLURL]");
- System.out.println(resbundle.getString("optionXSL")); //" [-XSL XSLTransformationURL]");
- System.out.println(resbundle.getString("optionOUT")); //" [-OUT outputFileName]");
-
- // System.out.println(resbundle.getString("optionE")); //" [-E (Do not expand entity refs)]");
- System.out.println(resbundle.getString("optionV")); //" [-V (Version info)]");
-
- // System.out.println(resbundle.getString("optionVALIDATE")); //" [-VALIDATE (Set whether validation occurs. Validation is off by default.)]");
- System.out.println(resbundle.getString("optionEDUMP")); //" [-EDUMP {optional filename} (Do stackdump on error.)]");
- System.out.println(resbundle.getString("optionXML")); //" [-XML (Use XML formatter and add XML header.)]");
- System.out.println(resbundle.getString("optionTEXT")); //" [-TEXT (Use simple Text formatter.)]");
- System.out.println(resbundle.getString("optionHTML")); //" [-HTML (Use HTML formatter.)]");
- System.out.println(resbundle.getString("optionPARAM")); //" [-PARAM name expression (Set a stylesheet parameter)]");
-
- System.out.println(resbundle.getString("optionMEDIA"));
- System.out.println(resbundle.getString("optionFLAVOR"));
- System.out.println(resbundle.getString("optionDIAG"));
- System.out.println(resbundle.getString("optionURIRESOLVER")); //" [-URIRESOLVER full class name (URIResolver to be used to resolve URIs)]");
- System.out.println(resbundle.getString("optionENTITYRESOLVER")); //" [-ENTITYRESOLVER full class name (EntityResolver to be used to resolve entities)]");
- waitForReturnKey(resbundle);
- System.out.println(resbundle.getString("optionCONTENTHANDLER")); //" [-CONTENTHANDLER full class name (ContentHandler to be used to serialize output)]");
- System.out.println(resbundle.getString("optionSECUREPROCESSING")); //" [-SECURE (set the secure processing feature to true)]");
-
- // J2SE does not support Xalan interpretive
- /*
- System.out.println("\n\t\t\t" + resbundle.getString("xslProc_xalan_options") + "\n");
-
- System.out.println(resbundle.getString("optionQC")); //" [-QC (Quiet Pattern Conflicts Warnings)]");
-
- // System.out.println(resbundle.getString("optionQ")); //" [-Q (Quiet Mode)]"); // sc 28-Feb-01 commented out
- System.out.println(resbundle.getString("optionTT")); //" [-TT (Trace the templates as they are being called.)]");
- System.out.println(resbundle.getString("optionTG")); //" [-TG (Trace each generation event.)]");
- System.out.println(resbundle.getString("optionTS")); //" [-TS (Trace each selection event.)]");
- System.out.println(resbundle.getString("optionTTC")); //" [-TTC (Trace the template children as they are being processed.)]");
- System.out.println(resbundle.getString("optionTCLASS")); //" [-TCLASS (TraceListener class for trace extensions.)]");
- System.out.println(resbundle.getString("optionLINENUMBERS")); //" [-L use line numbers]"
- System.out.println(resbundle.getString("optionINCREMENTAL"));
- System.out.println(resbundle.getString("optionNOOPTIMIMIZE"));
- System.out.println(resbundle.getString("optionRL"));
- */
-
- System.out.println("\n\t\t\t" + resbundle.getString("xslProc_xsltc_options") + "\n");
- System.out.println(resbundle.getString("optionXO"));
- waitForReturnKey(resbundle);
- System.out.println(resbundle.getString("optionXD"));
- System.out.println(resbundle.getString("optionXJ"));
- System.out.println(resbundle.getString("optionXP"));
- System.out.println(resbundle.getString("optionXN"));
- System.out.println(resbundle.getString("optionXX"));
- System.out.println(resbundle.getString("optionXT"));
- }
-
- /**
- * Command line interface to transform an XML document according to
- * the instructions found in an XSL stylesheet.
- * <p>The Process class provides basic functionality for
- * performing transformations from the command line. To see a
- * list of arguments supported, call with zero arguments.</p>
- * <p>To set stylesheet parameters from the command line, use
- * <code>-PARAM name expression</code>. If you want to set the
- * parameter to a string value, simply pass the string value
- * as-is, and it will be interpreted as a string. (Note: if
- * the value has spaces in it, you may need to quote it depending
- * on your shell environment).</p>
- *
- * @param argv Input parameters from command line
- */
- // J2SE does not support Xalan interpretive
- // main -> _main
- public static void _main(String argv[])
- {
-
- // Runtime.getRuntime().traceMethodCalls(false); // turns Java tracing off
- boolean doStackDumpOnError = false;
- boolean setQuietMode = false;
- boolean doDiag = false;
- String msg = null;
- boolean isSecureProcessing = false;
-
- // Runtime.getRuntime().traceMethodCalls(false);
- // Runtime.getRuntime().traceInstructions(false);
-
- /**
- * The default diagnostic writer...
- */
- java.io.PrintWriter diagnosticsWriter = new PrintWriter(System.err, true);
- java.io.PrintWriter dumpWriter = diagnosticsWriter;
- ResourceBundle resbundle =
- (SecuritySupport.getResourceBundle(
- com.sun.org.apache.xml.internal.utils.res.XResourceBundle.ERROR_RESOURCES));
- String flavor = "s2s";
-
- if (argv.length < 1)
- {
- printArgOptions(resbundle);
- }
- else
- {
- // J2SE does not support Xalan interpretive
- // false -> true
- boolean useXSLTC = true;
- for (int i = 0; i < argv.length; i++)
- {
- if ("-XSLTC".equalsIgnoreCase(argv[i]))
- {
- useXSLTC = true;
- }
- }
-
- TransformerFactory tfactory;
- if (useXSLTC)
- {
- String key = "javax.xml.transform.TransformerFactory";
- String value = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
- Properties props = System.getProperties();
- props.put(key, value);
- System.setProperties(props);
- }
-
- try
- {
- tfactory = TransformerFactory.newInstance();
- tfactory.setErrorListener(new DefaultErrorHandler());
- }
- catch (TransformerFactoryConfigurationError pfe)
- {
- pfe.printStackTrace(dumpWriter);
-// "XSL Process was not successful.");
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_NOT_SUCCESSFUL, null);
- diagnosticsWriter.println(msg);
-
- tfactory = null; // shut up compiler
-
- doExit(msg);
- }
-
- boolean formatOutput = false;
- boolean useSourceLocation = false;
- String inFileName = null;
- String outFileName = null;
- String dumpFileName = null;
- String xslFileName = null;
- String treedumpFileName = null;
- // J2SE does not support Xalan interpretive
- /*
- PrintTraceListener tracer = null;
- */
- String outputType = null;
- String media = null;
- Vector params = new Vector();
- boolean quietConflictWarnings = false;
- URIResolver uriResolver = null;
- EntityResolver entityResolver = null;
- ContentHandler contentHandler = null;
- int recursionLimit=-1;
-
- for (int i = 0; i < argv.length; i++)
- {
- if ("-XSLTC".equalsIgnoreCase(argv[i]))
- {
- // The -XSLTC option has been processed.
- }
- // J2SE does not support Xalan interpretive
- /*
- else if ("-TT".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- {
- if (null == tracer)
- tracer = new PrintTraceListener(diagnosticsWriter);
-
- tracer.m_traceTemplates = true;
- }
- else
- printInvalidXSLTCOption("-TT");
-
- // tfactory.setTraceTemplates(true);
- }
- else if ("-TG".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- {
- if (null == tracer)
- tracer = new PrintTraceListener(diagnosticsWriter);
-
- tracer.m_traceGeneration = true;
- }
- else
- printInvalidXSLTCOption("-TG");
-
- // tfactory.setTraceSelect(true);
- }
- else if ("-TS".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- {
- if (null == tracer)
- tracer = new PrintTraceListener(diagnosticsWriter);
-
- tracer.m_traceSelection = true;
- }
- else
- printInvalidXSLTCOption("-TS");
-
- // tfactory.setTraceTemplates(true);
- }
- else if ("-TTC".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- {
- if (null == tracer)
- tracer = new PrintTraceListener(diagnosticsWriter);
-
- tracer.m_traceElements = true;
- }
- else
- printInvalidXSLTCOption("-TTC");
-
- // tfactory.setTraceTemplateChildren(true);
- }
- */
- else if ("-INDENT".equalsIgnoreCase(argv[i]))
- {
- int indentAmount;
-
- if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-'))
- {
- indentAmount = Integer.parseInt(argv[++i]);
- }
- else
- {
- indentAmount = 0;
- }
-
- // TBD:
- // xmlProcessorLiaison.setIndent(indentAmount);
- }
- else if ("-IN".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- inFileName = argv[++i];
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-IN" })); //"Missing argument for);
- }
- else if ("-MEDIA".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length)
- media = argv[++i];
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-MEDIA" })); //"Missing argument for);
- }
- else if ("-OUT".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- outFileName = argv[++i];
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-OUT" })); //"Missing argument for);
- }
- else if ("-XSL".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- xslFileName = argv[++i];
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-XSL" })); //"Missing argument for);
- }
- else if ("-FLAVOR".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length)
- {
- flavor = argv[++i];
- }
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-FLAVOR" })); //"Missing argument for);
- }
- else if ("-PARAM".equalsIgnoreCase(argv[i]))
- {
- if (i + 2 < argv.length)
- {
- String name = argv[++i];
-
- params.addElement(name);
-
- String expression = argv[++i];
-
- params.addElement(expression);
- }
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-PARAM" })); //"Missing argument for);
- }
- else if ("-E".equalsIgnoreCase(argv[i]))
- {
-
- // TBD:
- // xmlProcessorLiaison.setShouldExpandEntityRefs(false);
- }
- else if ("-V".equalsIgnoreCase(argv[i]))
- {
- diagnosticsWriter.println(resbundle.getString("version") //">>>>>>> Xalan Version "
- + Version.getVersion() + ", " +
-
- /* xmlProcessorLiaison.getParserDescription()+ */
- resbundle.getString("version2")); // "<<<<<<<");
- }
- // J2SE does not support Xalan interpretive
- /*
- else if ("-QC".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- quietConflictWarnings = true;
- else
- printInvalidXSLTCOption("-QC");
- }
- */
- else if ("-Q".equalsIgnoreCase(argv[i]))
- {
- setQuietMode = true;
- }
- else if ("-DIAG".equalsIgnoreCase(argv[i]))
- {
- doDiag = true;
- }
- else if ("-XML".equalsIgnoreCase(argv[i]))
- {
- outputType = "xml";
- }
- else if ("-TEXT".equalsIgnoreCase(argv[i]))
- {
- outputType = "text";
- }
- else if ("-HTML".equalsIgnoreCase(argv[i]))
- {
- outputType = "html";
- }
- else if ("-EDUMP".equalsIgnoreCase(argv[i]))
- {
- doStackDumpOnError = true;
-
- if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-'))
- {
- dumpFileName = argv[++i];
- }
- }
- else if ("-URIRESOLVER".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length)
- {
- try
- {
- uriResolver = (URIResolver) ObjectFactory.newInstance(argv[++i], true);
-
- tfactory.setURIResolver(uriResolver);
- }
- catch (ConfigurationError cnfe)
- {
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
- new Object[]{ "-URIResolver" });
- System.err.println(msg);
- doExit(msg);
- }
- }
- else
- {
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-URIResolver" }); //"Missing argument for);
- System.err.println(msg);
- doExit(msg);
- }
- }
- else if ("-ENTITYRESOLVER".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length)
- {
- try
- {
- entityResolver = (EntityResolver) ObjectFactory.newInstance(argv[++i], true);
- }
- catch (ConfigurationError cnfe)
- {
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
- new Object[]{ "-EntityResolver" });
- System.err.println(msg);
- doExit(msg);
- }
- }
- else
- {
-// "Missing argument for);
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-EntityResolver" });
- System.err.println(msg);
- doExit(msg);
- }
- }
- else if ("-CONTENTHANDLER".equalsIgnoreCase(argv[i]))
- {
- if (i + 1 < argv.length)
- {
- try
- {
- contentHandler = (ContentHandler) ObjectFactory.newInstance(argv[++i], true);
- }
- catch (ConfigurationError cnfe)
- {
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
- new Object[]{ "-ContentHandler" });
- System.err.println(msg);
- doExit(msg);
- }
- }
- else
- {
-// "Missing argument for);
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-ContentHandler" });
- System.err.println(msg);
- doExit(msg);
- }
- }
- // J2SE does not support Xalan interpretive
- /*
- else if ("-L".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- tfactory.setAttribute(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
- else
- printInvalidXSLTCOption("-L");
- }
- else if ("-INCREMENTAL".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- tfactory.setAttribute
- ("http://xml.apache.org/xalan/features/incremental",
- java.lang.Boolean.TRUE);
- else
- printInvalidXSLTCOption("-INCREMENTAL");
- }
- else if ("-NOOPTIMIZE".equalsIgnoreCase(argv[i]))
- {
- // Default is true.
- //
- // %REVIEW% We should have a generalized syntax for negative
- // switches... and probably should accept the inverse even
- // if it is the default.
- if (!useXSLTC)
- tfactory.setAttribute
- ("http://xml.apache.org/xalan/features/optimize",
- java.lang.Boolean.FALSE);
- else
- printInvalidXSLTCOption("-NOOPTIMIZE");
- }
- else if ("-RL".equalsIgnoreCase(argv[i]))
- {
- if (!useXSLTC)
- {
- if (i + 1 < argv.length)
- recursionLimit = Integer.parseInt(argv[++i]);
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-rl" })); //"Missing argument for);
- }
- else
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- i++;
-
- printInvalidXSLTCOption("-RL");
- }
- }
- */
- // Generate the translet class and optionally specify the name
- // of the translet class.
- else if ("-XO".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
- {
- tfactory.setAttribute("generate-translet", "true");
- tfactory.setAttribute("translet-name", argv[++i]);
- }
- else
- tfactory.setAttribute("generate-translet", "true");
- }
- else
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- i++;
- printInvalidXalanOption("-XO");
- }
- }
- // Specify the destination directory for the translet classes.
- else if ("-XD".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
- tfactory.setAttribute("destination-directory", argv[++i]);
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-XD" })); //"Missing argument for);
-
- }
- else
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- i++;
-
- printInvalidXalanOption("-XD");
- }
- }
- // Specify the jar file name which the translet classes are packaged into.
- else if ("-XJ".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
- {
- tfactory.setAttribute("generate-translet", "true");
- tfactory.setAttribute("jar-name", argv[++i]);
- }
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-XJ" })); //"Missing argument for);
- }
- else
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- i++;
-
- printInvalidXalanOption("-XJ");
- }
-
- }
- // Specify the package name prefix for the generated translet classes.
- else if ("-XP".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
- tfactory.setAttribute("package-name", argv[++i]);
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
- new Object[]{ "-XP" })); //"Missing argument for);
- }
- else
- {
- if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
- i++;
-
- printInvalidXalanOption("-XP");
- }
-
- }
- // Enable template inlining.
- else if ("-XN".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- tfactory.setAttribute("enable-inlining", "true");
- }
- else
- printInvalidXalanOption("-XN");
- }
- // Turns on additional debugging message output
- else if ("-XX".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- tfactory.setAttribute("debug", "true");
- }
- else
- printInvalidXalanOption("-XX");
- }
- // Create the Transformer from the translet if the translet class is newer
- // than the stylesheet.
- else if ("-XT".equalsIgnoreCase(argv[i]))
- {
- if (useXSLTC)
- {
- tfactory.setAttribute("auto-translet", "true");
- }
- else
- printInvalidXalanOption("-XT");
- }
- else if ("-SECURE".equalsIgnoreCase(argv[i]))
- {
- isSecureProcessing = true;
- try
- {
- tfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- }
- catch (TransformerConfigurationException e) {}
- }
- else
- System.err.println(
- XSLMessages.createMessage(
- XSLTErrorResources.ER_INVALID_OPTION, new Object[]{ argv[i] })); //"Invalid argument:);
- }
-
- // Print usage instructions if no xml and xsl file is specified in the command line
- if (inFileName == null && xslFileName == null)
- {
- msg = resbundle.getString("xslProc_no_input");
- System.err.println(msg);
- doExit(msg);
- }
-
- // Note that there are usage cases for calling us without a -IN arg
- // The main XSL transformation occurs here!
- try
- {
- long start = System.currentTimeMillis();
-
- if (null != dumpFileName)
- {
- dumpWriter = new PrintWriter(new FileWriter(dumpFileName));
- }
-
- Templates stylesheet = null;
-
- if (null != xslFileName)
- {
- if (flavor.equals("d2d"))
- {
-
- // Parse in the xml data into a DOM
- DocumentBuilderFactory dfactory =
- DocumentBuilderFactory.newInstance();
-
- dfactory.setNamespaceAware(true);
-
- if (isSecureProcessing)
- {
- try
- {
- dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- }
- catch (ParserConfigurationException pce) {}
- }
-
- DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
- Node xslDOM = docBuilder.parse(new InputSource(xslFileName));
-
- stylesheet = tfactory.newTemplates(new DOMSource(xslDOM,
- xslFileName));
- }
- else
- {
- // System.out.println("Calling newTemplates: "+xslFileName);
- stylesheet = tfactory.newTemplates(new StreamSource(xslFileName));
- // System.out.println("Done calling newTemplates: "+xslFileName);
- }
- }
-
- PrintWriter resultWriter;
- StreamResult strResult;
-
- if (null != outFileName)
- {
- strResult = new StreamResult(new FileOutputStream(outFileName));
- // One possible improvement might be to ensure this is
- // a valid URI before setting the systemId, but that
- // might have subtle changes that pre-existing users
- // might notice; we can think about that later -sc r1.46
- strResult.setSystemId(outFileName);
- }
- else
- {
- strResult = new StreamResult(System.out);
- // We used to default to incremental mode in this case.
- // We've since decided that since the -INCREMENTAL switch is
- // available, that default is probably not necessary nor
- // necessarily a good idea.
- }
-
- SAXTransformerFactory stf = (SAXTransformerFactory) tfactory;
-
- // J2SE does not support Xalan interpretive
- /*
- // This is currently controlled via TransformerFactoryImpl.
- if (!useXSLTC && useSourceLocation)
- stf.setAttribute(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
- */
-
- // Did they pass in a stylesheet, or should we get it from the
- // document?
- if (null == stylesheet)
- {
- Source source =
- stf.getAssociatedStylesheet(new StreamSource(inFileName), media,
- null, null);
-
- if (null != source)
- stylesheet = tfactory.newTemplates(source);
- else
- {
- if (null != media)
- throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_STYLESHEET_IN_MEDIA, new Object[]{inFileName, media})); //"No stylesheet found in: "
- // + inFileName + ", media="
- // + media);
- else
- throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_STYLESHEET_PI, new Object[]{inFileName})); //"No xml-stylesheet PI found in: "
- //+ inFileName);
- }
- }
-
- if (null != stylesheet)
- {
- Transformer transformer = flavor.equals("th") ? null : stylesheet.newTransformer();
- transformer.setErrorListener(new DefaultErrorHandler());
-
- // Override the output format?
- if (null != outputType)
- {
- transformer.setOutputProperty(OutputKeys.METHOD, outputType);
- }
-
- // J2SE does not support Xalan interpretive
- /*
- if (transformer instanceof com.sun.org.apache.xalan.internal.transformer.TransformerImpl)
- {
- com.sun.org.apache.xalan.internal.transformer.TransformerImpl impl = (com.sun.org.apache.xalan.internal.transformer.TransformerImpl)transformer;
- TraceManager tm = impl.getTraceManager();
-
- if (null != tracer)
- tm.addTraceListener(tracer);
-
- impl.setQuietConflictWarnings(quietConflictWarnings);
-
- // This is currently controlled via TransformerFactoryImpl.
- if (useSourceLocation)
- impl.setProperty(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
-
- if(recursionLimit>0)
- impl.setRecursionLimit(recursionLimit);
-
- // sc 28-Feb-01 if we re-implement this, please uncomment helpmsg in printArgOptions
- // impl.setDiagnosticsOutput( setQuietMode ? null : diagnosticsWriter );
- }
- */
-
- int nParams = params.size();
-
- for (int i = 0; i < nParams; i += 2)
- {
- transformer.setParameter((String) params.elementAt(i),
- (String) params.elementAt(i + 1));
- }
-
- if (uriResolver != null)
- transformer.setURIResolver(uriResolver);
-
- if (null != inFileName)
- {
- if (flavor.equals("d2d"))
- {
-
- // Parse in the xml data into a DOM
- DocumentBuilderFactory dfactory =
- DocumentBuilderFactory.newInstance();
-
- dfactory.setCoalescing(true);
- dfactory.setNamespaceAware(true);
-
- if (isSecureProcessing)
- {
- try
- {
- dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- }
- catch (ParserConfigurationException pce) {}
- }
-
- DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
-
- if (entityResolver != null)
- docBuilder.setEntityResolver(entityResolver);
-
- Node xmlDoc = docBuilder.parse(new InputSource(inFileName));
- Document doc = docBuilder.newDocument();
- org.w3c.dom.DocumentFragment outNode =
- doc.createDocumentFragment();
-
- transformer.transform(new DOMSource(xmlDoc, inFileName),
- new DOMResult(outNode));
-
- // Now serialize output to disk with identity transformer
- Transformer serializer = stf.newTransformer();
- serializer.setErrorListener(new DefaultErrorHandler());
-
- Properties serializationProps =
- stylesheet.getOutputProperties();
-
- serializer.setOutputProperties(serializationProps);
-
- if (contentHandler != null)
- {
- SAXResult result = new SAXResult(contentHandler);
-
- serializer.transform(new DOMSource(outNode), result);
- }
- else
- serializer.transform(new DOMSource(outNode), strResult);
- }
- else if (flavor.equals("th"))
- {
- for (int i = 0; i < 1; i++) // Loop for diagnosing bugs with inconsistent behavior
- {
- // System.out.println("Testing the TransformerHandler...");
-
- XMLReader reader = null;
-
- // Use JAXP1.1 ( if possible )
- try
- {
- javax.xml.parsers.SAXParserFactory factory =
- javax.xml.parsers.SAXParserFactory.newInstance();
-
- factory.setNamespaceAware(true);
-
- if (isSecureProcessing)
- {
- try
- {
- factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- }
- catch (org.xml.sax.SAXException se) {}
- }
-
- javax.xml.parsers.SAXParser jaxpParser =
- factory.newSAXParser();
-
- reader = jaxpParser.getXMLReader();
- }
- catch (javax.xml.parsers.ParserConfigurationException ex)
- {
- throw new org.xml.sax.SAXException(ex);
- }
- catch (javax.xml.parsers.FactoryConfigurationError ex1)
- {
- throw new org.xml.sax.SAXException(ex1.toString());
- }
- catch (NoSuchMethodError ex2){}
- catch (AbstractMethodError ame){}
-
- if (null == reader)
- {
- reader = XMLReaderFactory.createXMLReader();
- }
-
- // J2SE does not support Xalan interpretive
- /*
- if (!useXSLTC)
- stf.setAttribute(com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.FEATURE_INCREMENTAL,
- Boolean.TRUE);
- */
-
- TransformerHandler th = stf.newTransformerHandler(stylesheet);
-
- reader.setContentHandler(th);
- reader.setDTDHandler(th);
-
- if(th instanceof org.xml.sax.ErrorHandler)
- reader.setErrorHandler((org.xml.sax.ErrorHandler)th);
-
- try
- {
- reader.setProperty(
- "http://xml.org/sax/properties/lexical-handler", th);
- }
- catch (org.xml.sax.SAXNotRecognizedException e){}
- catch (org.xml.sax.SAXNotSupportedException e){}
- try
- {
- reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
- true);
- } catch (org.xml.sax.SAXException se) {}
-
- th.setResult(strResult);
-
- reader.parse(new InputSource(inFileName));
- }
- }
- else
- {
- if (entityResolver != null)
- {
- XMLReader reader = null;
-
- // Use JAXP1.1 ( if possible )
- try
- {
- javax.xml.parsers.SAXParserFactory factory =
- javax.xml.parsers.SAXParserFactory.newInstance();
-
- factory.setNamespaceAware(true);
-
- if (isSecureProcessing)
- {
- try
- {
- factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
- }
- catch (org.xml.sax.SAXException se) {}
- }
-
- javax.xml.parsers.SAXParser jaxpParser =
- factory.newSAXParser();
-
- reader = jaxpParser.getXMLReader();
- }
- catch (javax.xml.parsers.ParserConfigurationException ex)
- {
- throw new org.xml.sax.SAXException(ex);
- }
- catch (javax.xml.parsers.FactoryConfigurationError ex1)
- {
- throw new org.xml.sax.SAXException(ex1.toString());
- }
- catch (NoSuchMethodError ex2){}
- catch (AbstractMethodError ame){}
-
- if (null == reader)
- {
- reader = XMLReaderFactory.createXMLReader();
- }
-
- reader.setEntityResolver(entityResolver);
-
- if (contentHandler != null)
- {
- SAXResult result = new SAXResult(contentHandler);
-
- transformer.transform(
- new SAXSource(reader, new InputSource(inFileName)),
- result);
- }
- else
- {
- transformer.transform(
- new SAXSource(reader, new InputSource(inFileName)),
- strResult);
- }
- }
- else if (contentHandler != null)
- {
- SAXResult result = new SAXResult(contentHandler);
-
- transformer.transform(new StreamSource(inFileName), result);
- }
- else
- {
- // System.out.println("Starting transform");
- transformer.transform(new StreamSource(inFileName),
- strResult);
- // System.out.println("Done with transform");
- }
- }
- }
- else
- {
- StringReader reader =
- new StringReader("<?xml version=\"1.0\"?> <doc/>");
-
- transformer.transform(new StreamSource(reader), strResult);
- }
- }
- else
- {
-// "XSL Process was not successful.");
- msg = XSLMessages.createMessage(
- XSLTErrorResources.ER_NOT_SUCCESSFUL, null);
- diagnosticsWriter.println(msg);
- doExit(msg);
- }
-
- // close output streams
- if (null != outFileName && strResult!=null)
- {
- java.io.OutputStream out = strResult.getOutputStream();
- java.io.Writer writer = strResult.getWriter();
- try
- {
- if (out != null) out.close();
- if (writer != null) writer.close();
- }
- catch(java.io.IOException ie) {}
- }
-
- long stop = System.currentTimeMillis();
- long millisecondsDuration = stop - start;
-
- if (doDiag)
- {
- Object[] msgArgs = new Object[]{ inFileName, xslFileName, new Long(millisecondsDuration) };
- msg = XSLMessages.createMessage("diagTiming", msgArgs);
- diagnosticsWriter.println('\n');
- diagnosticsWriter.println(msg);
- }
-
- }
- catch (Throwable throwable)
- {
- while (throwable
- instanceof com.sun.org.apache.xml.internal.utils.WrappedRuntimeException)
- {
- throwable =
- ((com.sun.org.apache.xml.internal.utils.WrappedRuntimeException) throwable).getException();
- }
-
- if ((throwable instanceof NullPointerException)
- || (throwable instanceof ClassCastException))
- doStackDumpOnError = true;
-
- diagnosticsWriter.println();
-
- if (doStackDumpOnError)
- throwable.printStackTrace(dumpWriter);
- else
- {
- DefaultErrorHandler.printLocation(diagnosticsWriter, throwable);
- diagnosticsWriter.println(
- XSLMessages.createMessage(XSLTErrorResources.ER_XSLT_ERROR, null)
- + " (" + throwable.getClass().getName() + "): "
- + throwable.getMessage());
- }
-
- // diagnosticsWriter.println(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUCCESSFUL, null)); //"XSL Process was not successful.");
- if (null != dumpFileName)
- {
- dumpWriter.close();
- }
-
- doExit(throwable.getMessage());
- }
-
- if (null != dumpFileName)
- {
- dumpWriter.close();
- }
-
- if (null != diagnosticsWriter)
- {
-
- // diagnosticsWriter.close();
- }
-
- // if(!setQuietMode)
- // diagnosticsWriter.println(resbundle.getString("xsldone")); //"Xalan: done");
- // else
- // diagnosticsWriter.println(""); //"Xalan: done");
- }
- }
-
- /** It is _much_ easier to debug under VJ++ if I can set a single breakpoint
- * before this blows itself out of the water...
- * (I keep checking this in, it keeps vanishing. Grr!)
- * */
- static void doExit(String msg)
- {
- throw new RuntimeException(msg);
- }
-
- /**
- * Wait for a return key to continue
- *
- * @param resbundle The resource bundle
- */
- private static void waitForReturnKey(ResourceBundle resbundle)
- {
- System.out.println(resbundle.getString("xslProc_return_to_continue"));
- try
- {
- while (System.in.read() != '\n');
- }
- catch (java.io.IOException e) { }
- }
-
- /**
- * Print a message if an option cannot be used with -XSLTC.
- *
- * @param option The option String
- */
- private static void printInvalidXSLTCOption(String option)
- {
- System.err.println(XSLMessages.createMessage("xslProc_invalid_xsltc_option", new Object[]{option}));
- }
-
- /**
- * Print a message if an option can only be used with -XSLTC.
- *
- * @param option The option String
- */
- private static void printInvalidXalanOption(String option)
- {
- System.err.println(XSLMessages.createMessage("xslProc_invalid_xalan_option", new Object[]{option}));
- }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Version.java Thu Aug 06 13:00:45 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
- * ITS 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-package com.sun.org.apache.xerces.internal.impl;
-
-/**
- * This class defines the version number of the parser.
- *
- */
-public class Version {
-
- //
- // Data
- //
-
- /** Version string.
- * @deprecated getVersion() should be used instead. */
- public static final String fVersion = getVersion();
-
- private static final String fImmutableVersion = "Xerces-J 2.7.1";
-
- // public methods
-
- /* Print out the version information.
- * @return the version of the parser.
- */
- public static String getVersion() {
- return fImmutableVersion;
- } // getVersion(): String
-
- //
- // MAIN
- //
-
- /**
- * Prints out the version number to System.out. This is needed
- * for the build system.
- */
- public static void main(String argv[]) {
- System.out.println(fVersion);
- }
-
-} // class Version
--- a/jaxp/test/javax/xml/jaxp/internaltest/javax/xml/common/bug6979306/Bug6979306Test.java Thu Aug 06 13:00:45 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +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.
- *
- * 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
- * @modules java.xml/com.sun.org.apache.xerces.internal.impl
- * java.xml/com.sun.org.apache.xalan.internal
- * @bug 6979306
- * @summary Test JAXP component version.
- */
-
-import org.testng.annotations.Test;
-
-public class Bug6979306Test {
-
- @Test
- public void test() {
- String[] input = {};
- com.sun.org.apache.xerces.internal.impl.Version.main(input);
- com.sun.org.apache.xalan.internal.Version._main(input);
- }
-
-}
--- a/jaxp/test/javax/xml/jaxp/internaltest/javax/xml/transform/cli/CLITest.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jaxp/test/javax/xml/jaxp/internaltest/javax/xml/transform/cli/CLITest.java Mon Aug 10 18:58:25 2015 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @modules java.xml/com.sun.org.apache.xalan.internal.xslt
+ * @modules java.xml/com.sun.org.apache.xml.internal.utils
* @summary Test internal transform CLI.
*/
@@ -37,7 +37,7 @@
try {
String[] args = new String[] { "-XSLTC", "-XSL", getClass().getResource("tigertest.xsl").toString(), "-IN",
getClass().getResource("tigertest-in.xml").toString(), };
- com.sun.org.apache.xalan.internal.xslt.Process._main(args);
+ ProcessXSLT.main(args);
} catch (Exception e) {
Assert.fail(e.getMessage());
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/internaltest/javax/xml/transform/cli/ProcessXSLT.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,913 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id: Process.java,v 1.2.4.2 2005/09/15 18:21:57 jeffsuttor Exp $
+ */
+
+// This file is a copied and modified version of
+// com/sun/org/apache/xalan/internal/xslt/Process.java
+// which has been modified to only use public exported APIs.
+// The only adherence is with
+// com.sun.org.apache.xml.internal.utils.DefaultErrorHandler
+// which we try to instantiate using reflection, as that class
+// can do a better job at reporting error location.
+// We however don't have a hard dependency on it. We will use
+// our own ErrorHandler if the default one is not accessible.
+//
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.Properties;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.SourceLocator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * The main() method handles the Xalan command-line interface.
+ */
+public class ProcessXSLT
+{
+
+ /**
+ * Prints argument options.
+ *
+ */
+ protected static void printArgOptions() {
+ System.out.println("xslproc options: ");
+ System.out.println("\n\t\t\t" + "-Common Options-" + "\n");
+ System.out.println(" [-XSLTC (use XSLTC for transformation)]"); //" [-XSLTC (use XSLTC for transformation)]
+ System.out.println(" [-IN inputXMLURL]"); //" [-IN inputXMLURL]");
+ System.out.println(" [-XSL XSLTransformationURL]"); //" [-XSL XSLTransformationURL]");
+ System.out.println(" [-OUT outputFileName]"); //" [-OUT outputFileName]");
+
+ System.out.println(" [-E (Do not expand entity refs)]"); //" [-V (Version info)]");
+
+ System.out.println(" [-EDUMP {optional filename} (Do stackdump on error.)]"); //" [-EDUMP {optional filename} (Do stackdump on error.)]");
+ System.out.println(" [-XML (Use XML formatter and add XML header.)]"); //" [-XML (Use XML formatter and add XML header.)]");
+ System.out.println(" [-TEXT (Use simple Text formatter.)]"); //" [-TEXT (Use simple Text formatter.)]");
+ System.out.println(" [-HTML (Use HTML formatter.)]"); //" [-HTML (Use HTML formatter.)]");
+ System.out.println( " [-PARAM name expression (Set a stylesheet parameter)]"); //" [-PARAM name expression (Set a stylesheet parameter)]");
+
+ System.out.println(" [-MEDIA mediaType (use media attribute to find stylesheet associated with a document.)]");
+ System.out.println(" [-FLAVOR flavorName (Explicitly use s2s=SAX or d2d=DOM to do transform.)] ");
+ System.out.println(" [-DIAG (Print overall milliseconds transform took.)]");
+ System.out.println(" [-URIRESOLVER full class name (URIResolver to be used to resolve URIs)]"); //" [-URIRESOLVER full class name (URIResolver to be used to resolve URIs)]");
+ System.out.println(" [-ENTITYRESOLVER full class name (EntityResolver to be used to resolve entities)]"); //" [-ENTITYRESOLVER full class name (EntityResolver to be used to resolve entities)]");
+ waitForReturnKey();
+ System.out.println(" [-CONTENTHANDLER full class name (ContentHandler to be used to serialize output)]"); //" [-CONTENTHANDLER full class name (ContentHandler to be used to serialize output)]");
+ System.out.println(" [-SECURE (set the secure processing feature to true.)]"); //" [-SECURE (set the secure processing feature to true)]");
+
+
+ System.out.println("\n\t\t\t"+ "-Options for XSLTC-" + "\n");
+ System.out.println(" [-XO [transletName] (assign the name to the generated translet)]");
+ waitForReturnKey();
+ System.out.println(" [-XD destinationDirectory (specify a destination directory for translet)]");
+ System.out.println(" [-XJ jarfile (packages translet classes into a jar file of name <jarfile>)]");
+ System.out.println(" [-XP package (specifies a package name prefix for all generated translet classes)]");
+ System.out.println(" [-XN (enables template inlining)]");
+ System.out.println(" [-XX (turns on additional debugging message output)]");
+ System.out.println(" [-XT (use translet to transform if possible)]");
+ }
+
+ /**
+ * Command line interface to transform an XML document according to
+ * the instructions found in an XSL stylesheet.
+ * <p>The Process class provides basic functionality for
+ * performing transformations from the command line. To see a
+ * list of arguments supported, call with zero arguments.</p>
+ * <p>To set stylesheet parameters from the command line, use
+ * <code>-PARAM name expression</code>. If you want to set the
+ * parameter to a string value, simply pass the string value
+ * as-is, and it will be interpreted as a string. (Note: if
+ * the value has spaces in it, you may need to quote it depending
+ * on your shell environment).</p>
+ *
+ * @param argv Input parameters from command line
+ */
+ public static void main(String argv[]) {
+
+ // Runtime.getRuntime().traceMethodCalls(false); // turns Java tracing off
+ boolean doStackDumpOnError = false;
+ boolean doDiag = false;
+ boolean setQuietMode = false;
+ String msg = null;
+ boolean isSecureProcessing = false;
+
+ // Runtime.getRuntime().traceMethodCalls(false);
+ // Runtime.getRuntime().traceInstructions(false);
+ /**
+ * The default diagnostic writer...
+ */
+ java.io.PrintWriter diagnosticsWriter = new PrintWriter(System.err, true);
+ java.io.PrintWriter dumpWriter = diagnosticsWriter;
+ String flavor = "s2s";
+
+ if (argv.length < 1) {
+ printArgOptions();
+ } else {
+ // J2SE does not support Xalan interpretive
+ // false -> true
+ boolean useXSLTC = true;
+ for (int i = 0; i < argv.length; i++) {
+ if ("-XSLTC".equalsIgnoreCase(argv[i])) {
+ useXSLTC = true;
+ }
+ }
+
+ TransformerFactory tfactory;
+ if (useXSLTC) {
+ String key = "javax.xml.transform.TransformerFactory";
+ String value = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
+ Properties props = System.getProperties();
+ props.put(key, value);
+ System.setProperties(props);
+ }
+
+ try {
+ tfactory = TransformerFactory.newInstance();
+ tfactory.setErrorListener(createDefaultErrorListener());
+ } catch (TransformerFactoryConfigurationError pfe) {
+ pfe.printStackTrace(dumpWriter);
+ // "XSL Process was not successful.");
+ msg = "XSL Process was not successful.";
+ diagnosticsWriter.println(msg);
+
+ tfactory = null; // shut up compiler
+
+ doExit(msg);
+ }
+
+ boolean formatOutput = false;
+ boolean useSourceLocation = false;
+ String inFileName = null;
+ String outFileName = null;
+ String dumpFileName = null;
+ String xslFileName = null;
+ String treedumpFileName = null;
+ String outputType = null;
+ String media = null;
+ List<String> params = new ArrayList<>();
+ boolean quietConflictWarnings = false;
+ URIResolver uriResolver = null;
+ EntityResolver entityResolver = null;
+ ContentHandler contentHandler = null;
+ int recursionLimit = -1;
+
+ for (int i = 0; i < argv.length; i++) {
+ if ("-XSLTC".equalsIgnoreCase(argv[i])) {
+ // The -XSLTC option has been processed.
+ } // J2SE does not support Xalan interpretive
+ else if ("-INDENT".equalsIgnoreCase(argv[i])) {
+ int indentAmount;
+
+ if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-')) {
+ indentAmount = Integer.parseInt(argv[++i]);
+ } else {
+ indentAmount = 0;
+ }
+
+ } else if ("-IN".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ inFileName = argv[++i];
+ } else {
+ System.err.println("Missing argument for -IN");
+ }
+ } else if ("-MEDIA".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length) {
+ media = argv[++i];
+ } else {
+ System.err.println("Missing argument for -MEDIA"); //"Missing argument for);
+ }
+ } else if ("-OUT".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ outFileName = argv[++i];
+ } else {
+ System.err.println("Missing argument for -OUT"); //"Missing argument for);
+ }
+ } else if ("-XSL".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ xslFileName = argv[++i];
+ } else {
+ System.err.println("Missing argument for -XSL"); //"Missing argument for);
+ }
+ } else if ("-FLAVOR".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length) {
+ flavor = argv[++i];
+ } else {
+ System.err.println("Missing argument for -FLAVOR"); //"Missing argument for);
+ }
+ } else if ("-PARAM".equalsIgnoreCase(argv[i])) {
+ if (i + 2 < argv.length) {
+ String name = argv[++i];
+
+ params.add(name);
+
+ String expression = argv[++i];
+
+ params.add(expression);
+ } else {
+ System.err.println("Missing argument for -PARAM"); //"Missing argument for);
+ }
+ } else if ("-E".equalsIgnoreCase(argv[i])) {
+
+ } else if ("-V".equalsIgnoreCase(argv[i])) {
+ diagnosticsWriter.println(">>>>>>> Java Version "
+ + System.getProperty("java.version") + ", "
+ + /* xmlProcessorLiaison.getParserDescription()+ */ "<<<<<<<");
+ } // J2SE does not support Xalan interpretive
+ /*
+ else if ("-QC".equalsIgnoreCase(argv[i]))
+ {
+ if (!useXSLTC)
+ quietConflictWarnings = true;
+ else
+ printInvalidXSLTCOption("-QC");
+ }
+ */ else if ("-Q".equalsIgnoreCase(argv[i])) {
+ setQuietMode = true;
+ } else if ("-DIAG".equalsIgnoreCase(argv[i])) {
+ doDiag = true;
+ } else if ("-XML".equalsIgnoreCase(argv[i])) {
+ outputType = "xml";
+ } else if ("-TEXT".equalsIgnoreCase(argv[i])) {
+ outputType = "text";
+ } else if ("-HTML".equalsIgnoreCase(argv[i])) {
+ outputType = "html";
+ } else if ("-EDUMP".equalsIgnoreCase(argv[i])) {
+ doStackDumpOnError = true;
+
+ if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-')) {
+ dumpFileName = argv[++i];
+ }
+ } else if ("-URIRESOLVER".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length) {
+ try {
+ Class<?> uriResolverClass = Class.forName(argv[++i]);
+ Constructor<?> ctor = uriResolverClass.getConstructor();
+ ctor.setAccessible(true);
+ uriResolver = (URIResolver) ctor.newInstance();
+
+ tfactory.setURIResolver(uriResolver);
+ } catch (Throwable cnfe) {
+ msg = "Class not found for option -URIResolver";
+ System.err.println(msg);
+ doExit(msg);
+ }
+ } else {
+ msg = "Missing argument for -URIResolver";
+ System.err.println(msg); //"Missing argument for);
+ doExit(msg);
+ }
+ } else if ("-ENTITYRESOLVER".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length) {
+ try {
+ Class<?> entityResolverClass = Class.forName(argv[++i]);
+ Constructor<?> ctor = entityResolverClass.getConstructor();
+ ctor.setAccessible(true);
+ entityResolver = (EntityResolver) ctor.newInstance();
+ } catch (Throwable cnfe) {
+ msg = "Class not found for option -EntityResolver";
+ System.err.println(msg);
+ doExit(msg);
+ }
+ } else {
+ // "Missing argument for);
+ msg = "Missing argument for -EntityResolver";
+ System.err.println(msg);
+ doExit(msg);
+ }
+ } else if ("-CONTENTHANDLER".equalsIgnoreCase(argv[i])) {
+ if (i + 1 < argv.length) {
+ try {
+ Class<?> contentHandlerClass = Class.forName(argv[++i]);
+ Constructor<?> ctor = contentHandlerClass.getConstructor();
+ ctor.setAccessible(true);
+ contentHandler = (ContentHandler) ctor.newInstance();
+ } catch (Throwable cnfe) {
+ msg = "Class not found for option -ContentHandler";
+ System.err.println(msg);
+ doExit(msg);
+ }
+ } else {
+ // "Missing argument for);
+ msg = "Missing argument for -ContentHandler";
+ System.err.println(msg);
+ doExit(msg);
+ }
+ } else if ("-XO".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ tfactory.setAttribute("generate-translet", "true");
+ tfactory.setAttribute("translet-name", argv[++i]);
+ } else {
+ tfactory.setAttribute("generate-translet", "true");
+ }
+ } else {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ i++;
+ }
+ printInvalidXalanOption("-XO");
+ }
+ } // Specify the destination directory for the translet classes.
+ else if ("-XD".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ tfactory.setAttribute("destination-directory", argv[++i]);
+ } else {
+ System.err.println("Missing argument for -XD"); //"Missing argument for);
+ }
+ } else {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ i++;
+ }
+
+ printInvalidXalanOption("-XD");
+ }
+ } // Specify the jar file name which the translet classes are packaged into.
+ else if ("-XJ".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ tfactory.setAttribute("generate-translet", "true");
+ tfactory.setAttribute("jar-name", argv[++i]);
+ } else {
+ System.err.println("Missing argument for -XJ"); //"Missing argument for);
+ }
+ } else {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ i++;
+ }
+
+ printInvalidXalanOption("-XJ");
+ }
+
+ } // Specify the package name prefix for the generated translet classes.
+ else if ("-XP".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ tfactory.setAttribute("package-name", argv[++i]);
+ } else {
+ System.err.println("Missing argument for -XP"); //"Missing argument for);
+ }
+ } else {
+ if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-') {
+ i++;
+ }
+
+ printInvalidXalanOption("-XP");
+ }
+
+ } // Enable template inlining.
+ else if ("-XN".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ tfactory.setAttribute("enable-inlining", "true");
+ } else {
+ printInvalidXalanOption("-XN");
+ }
+ } // Turns on additional debugging message output
+ else if ("-XX".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ tfactory.setAttribute("debug", "true");
+ } else {
+ printInvalidXalanOption("-XX");
+ }
+ } // Create the Transformer from the translet if the translet class is newer
+ // than the stylesheet.
+ else if ("-XT".equalsIgnoreCase(argv[i])) {
+ if (useXSLTC) {
+ tfactory.setAttribute("auto-translet", "true");
+ } else {
+ printInvalidXalanOption("-XT");
+ }
+ } else if ("-SECURE".equalsIgnoreCase(argv[i])) {
+ isSecureProcessing = true;
+ try {
+ tfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (TransformerConfigurationException e) {
+ }
+ } else {
+ System.err.println("Invalid argument: " + argv[i]); //"Invalid argument:);
+ }
+ }
+
+ // Print usage instructions if no xml and xsl file is specified in the command line
+ if (inFileName == null && xslFileName == null) {
+ msg = "Error: No stylesheet or input xml is specified. Run this command without any option for usage instructions.";
+ System.err.println(msg);
+ doExit(msg);
+ }
+
+ // Note that there are usage cases for calling us without a -IN arg
+ // The main XSL transformation occurs here!
+ try {
+ long start = System.currentTimeMillis();
+
+ if (null != dumpFileName) {
+ dumpWriter = new PrintWriter(new FileWriter(dumpFileName));
+ }
+
+ Templates stylesheet = null;
+
+ if (null != xslFileName) {
+ if (flavor.equals("d2d")) {
+
+ // Parse in the xml data into a DOM
+ DocumentBuilderFactory dfactory
+ = DocumentBuilderFactory.newInstance();
+
+ dfactory.setNamespaceAware(true);
+
+ if (isSecureProcessing) {
+ try {
+ dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (ParserConfigurationException pce) {
+ }
+ }
+
+ DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+ Node xslDOM = docBuilder.parse(new InputSource(xslFileName));
+
+ stylesheet = tfactory.newTemplates(new DOMSource(xslDOM,
+ xslFileName));
+ } else {
+ // System.out.println("Calling newTemplates: "+xslFileName);
+ stylesheet = tfactory.newTemplates(new StreamSource(xslFileName));
+ // System.out.println("Done calling newTemplates: "+xslFileName);
+ }
+ }
+
+ PrintWriter resultWriter;
+ StreamResult strResult;
+
+ if (null != outFileName) {
+ strResult = new StreamResult(new FileOutputStream(outFileName));
+ // One possible improvement might be to ensure this is
+ // a valid URI before setting the systemId, but that
+ // might have subtle changes that pre-existing users
+ // might notice; we can think about that later -sc r1.46
+ strResult.setSystemId(outFileName);
+ } else {
+ strResult = new StreamResult(System.out);
+ // We used to default to incremental mode in this case.
+ // We've since decided that since the -INCREMENTAL switch is
+ // available, that default is probably not necessary nor
+ // necessarily a good idea.
+ }
+
+ SAXTransformerFactory stf = (SAXTransformerFactory) tfactory;
+
+ // Did they pass in a stylesheet, or should we get it from the
+ // document?
+ if (null == stylesheet) {
+ Source source
+ = stf.getAssociatedStylesheet(new StreamSource(inFileName), media,
+ null, null);
+
+ if (null != source) {
+ stylesheet = tfactory.newTemplates(source);
+ } else {
+ if (null != media) {
+ throw new TransformerException("No stylesheet found in: "
+ + inFileName + ", media=" + media); //"No stylesheet found in: "
+ } // + inFileName + ", media="
+ // + media);
+ else {
+ throw new TransformerException("No xml-stylesheet PI found in: " + inFileName); //"No xml-stylesheet PI found in: "
+ } //+ inFileName);
+ }
+ }
+
+ if (null != stylesheet) {
+ Transformer transformer = flavor.equals("th") ? null : stylesheet.newTransformer();
+ transformer.setErrorListener(createDefaultErrorListener());
+
+ // Override the output format?
+ if (null != outputType) {
+ transformer.setOutputProperty(OutputKeys.METHOD, outputType);
+ }
+
+ int nParams = params.size();
+
+ for (int i = 0; i < nParams; i += 2) {
+ transformer.setParameter((String) params.get(i),
+ (String) params.get(i + 1));
+ }
+
+ if (uriResolver != null) {
+ transformer.setURIResolver(uriResolver);
+ }
+
+ if (null != inFileName) {
+ if (flavor.equals("d2d")) {
+
+ // Parse in the xml data into a DOM
+ DocumentBuilderFactory dfactory
+ = DocumentBuilderFactory.newInstance();
+
+ dfactory.setCoalescing(true);
+ dfactory.setNamespaceAware(true);
+
+ if (isSecureProcessing) {
+ try {
+ dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (ParserConfigurationException pce) {
+ }
+ }
+
+ DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+
+ if (entityResolver != null) {
+ docBuilder.setEntityResolver(entityResolver);
+ }
+
+ Node xmlDoc = docBuilder.parse(new InputSource(inFileName));
+ Document doc = docBuilder.newDocument();
+ org.w3c.dom.DocumentFragment outNode
+ = doc.createDocumentFragment();
+
+ transformer.transform(new DOMSource(xmlDoc, inFileName),
+ new DOMResult(outNode));
+
+ // Now serialize output to disk with identity transformer
+ Transformer serializer = stf.newTransformer();
+ serializer.setErrorListener(createDefaultErrorListener());
+
+ Properties serializationProps
+ = stylesheet.getOutputProperties();
+
+ serializer.setOutputProperties(serializationProps);
+
+ if (contentHandler != null) {
+ SAXResult result = new SAXResult(contentHandler);
+
+ serializer.transform(new DOMSource(outNode), result);
+ } else {
+ serializer.transform(new DOMSource(outNode), strResult);
+ }
+ } else if (flavor.equals("th")) {
+ for (int i = 0; i < 1; i++) // Loop for diagnosing bugs with inconsistent behavior
+ {
+ // System.out.println("Testing the TransformerHandler...");
+
+ XMLReader reader = null;
+
+ // Use JAXP1.1 ( if possible )
+ try {
+ javax.xml.parsers.SAXParserFactory factory
+ = javax.xml.parsers.SAXParserFactory.newInstance();
+
+ factory.setNamespaceAware(true);
+
+ if (isSecureProcessing) {
+ try {
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (org.xml.sax.SAXException se) {
+ }
+ }
+
+ javax.xml.parsers.SAXParser jaxpParser
+ = factory.newSAXParser();
+
+ reader = jaxpParser.getXMLReader();
+ } catch (javax.xml.parsers.ParserConfigurationException ex) {
+ throw new org.xml.sax.SAXException(ex);
+ } catch (javax.xml.parsers.FactoryConfigurationError ex1) {
+ throw new org.xml.sax.SAXException(ex1.toString());
+ } catch (NoSuchMethodError ex2) {
+ } catch (AbstractMethodError ame) {
+ }
+
+ if (null == reader) {
+ reader = XMLReaderFactory.createXMLReader();
+ }
+
+ TransformerHandler th = stf.newTransformerHandler(stylesheet);
+
+ reader.setContentHandler(th);
+ reader.setDTDHandler(th);
+
+ if (th instanceof org.xml.sax.ErrorHandler) {
+ reader.setErrorHandler((org.xml.sax.ErrorHandler) th);
+ }
+
+ try {
+ reader.setProperty(
+ "http://xml.org/sax/properties/lexical-handler", th);
+ } catch (org.xml.sax.SAXNotRecognizedException e) {
+ } catch (org.xml.sax.SAXNotSupportedException e) {
+ }
+ try {
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
+ true);
+ } catch (org.xml.sax.SAXException se) {
+ }
+
+ th.setResult(strResult);
+
+ reader.parse(new InputSource(inFileName));
+ }
+ } else {
+ if (entityResolver != null) {
+ XMLReader reader = null;
+
+ // Use JAXP1.1 ( if possible )
+ try {
+ javax.xml.parsers.SAXParserFactory factory
+ = javax.xml.parsers.SAXParserFactory.newInstance();
+
+ factory.setNamespaceAware(true);
+
+ if (isSecureProcessing) {
+ try {
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ } catch (org.xml.sax.SAXException se) {
+ }
+ }
+
+ javax.xml.parsers.SAXParser jaxpParser
+ = factory.newSAXParser();
+
+ reader = jaxpParser.getXMLReader();
+ } catch (javax.xml.parsers.ParserConfigurationException ex) {
+ throw new org.xml.sax.SAXException(ex);
+ } catch (javax.xml.parsers.FactoryConfigurationError ex1) {
+ throw new org.xml.sax.SAXException(ex1.toString());
+ } catch (NoSuchMethodError ex2) {
+ } catch (AbstractMethodError ame) {
+ }
+
+ if (null == reader) {
+ reader = XMLReaderFactory.createXMLReader();
+ }
+
+ reader.setEntityResolver(entityResolver);
+
+ if (contentHandler != null) {
+ SAXResult result = new SAXResult(contentHandler);
+
+ transformer.transform(
+ new SAXSource(reader, new InputSource(inFileName)),
+ result);
+ } else {
+ transformer.transform(
+ new SAXSource(reader, new InputSource(inFileName)),
+ strResult);
+ }
+ } else if (contentHandler != null) {
+ SAXResult result = new SAXResult(contentHandler);
+
+ transformer.transform(new StreamSource(inFileName), result);
+ } else {
+ // System.out.println("Starting transform");
+ transformer.transform(new StreamSource(inFileName),
+ strResult);
+ // System.out.println("Done with transform");
+ }
+ }
+ } else {
+ StringReader reader
+ = new StringReader("<?xml version=\"1.0\"?> <doc/>");
+
+ transformer.transform(new StreamSource(reader), strResult);
+ }
+ } else {
+ // "XSL Process was not successful.");
+ msg = "XSL Process was not successful.";
+ diagnosticsWriter.println(msg);
+ doExit(msg);
+ }
+
+ // close output streams
+ if (null != outFileName && strResult != null) {
+ java.io.OutputStream out = strResult.getOutputStream();
+ java.io.Writer writer = strResult.getWriter();
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (writer != null) {
+ writer.close();
+ }
+ } catch (java.io.IOException ie) {
+ }
+ }
+
+ long stop = System.currentTimeMillis();
+ long millisecondsDuration = stop - start;
+
+ if (doDiag) {
+ msg = " --------- Transform of " + inFileName + " via "
+ + xslFileName + " took " + millisecondsDuration + " ms";
+ diagnosticsWriter.println('\n');
+ diagnosticsWriter.println(msg);
+ }
+
+ } catch (Throwable throwable) {
+ doStackDumpOnError = true;
+
+ diagnosticsWriter.println();
+
+ if (doStackDumpOnError) {
+ throwable.printStackTrace(dumpWriter);
+ } else {
+ printLocation(diagnosticsWriter, throwable);
+ diagnosticsWriter.println("Unexpected exception: " + throwable);
+ }
+
+ // diagnosticsWriter.println(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUCCESSFUL, null)); //"XSL Process was not successful.");
+ if (null != dumpFileName) {
+ dumpWriter.close();
+ }
+
+ doExit(throwable.getMessage());
+ }
+
+ if (null != dumpFileName) {
+ dumpWriter.close();
+ }
+
+ if (null != diagnosticsWriter) {
+
+ // diagnosticsWriter.close();
+ }
+
+ // if(!setQuietMode)
+ // diagnosticsWriter.println(resbundle.getString("xsldone")); //"Xalan: done");
+ // else
+ // diagnosticsWriter.println(""); //"Xalan: done");
+ }
+ }
+
+ /**
+ * It is _much_ easier to debug under VJ++ if I can set a single breakpoint
+ * before this blows itself out of the water... (I keep checking this in, it
+ * keeps vanishing. Grr!)
+ *
+ */
+ static void doExit(String msg) {
+ throw new RuntimeException(msg);
+ }
+
+ /**
+ * Wait for a return key to continue
+ *
+ * @param resbundle The resource bundle
+ */
+ private static void waitForReturnKey() {
+ System.out.println("(press <return> to continue)");
+ try {
+ while (System.in.read() != '\n');
+ } catch (java.io.IOException e) {
+ }
+ }
+
+ /**
+ * Print a message if an option cannot be used with -XSLTC.
+ *
+ * @param option The option String
+ */
+ private static void printInvalidXSLTCOption(String option) {
+ System.err.println("The option " + option + " is not supported in XSLTC mode.");
+ }
+
+ /**
+ * Print a message if an option can only be used with -XSLTC.
+ *
+ * @param option The option String
+ */
+ private static void printInvalidXalanOption(String option) {
+ System.err.println("The option " + option + " can only be used with -XSLTC.");
+ }
+
+ static class DummyErrorListenerHandler implements ErrorHandler, ErrorListener {
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ System.err.println("WARNING: " + exception);
+ }
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+ @Override
+ public void warning(TransformerException exception) throws TransformerException {
+ System.err.println("WARNING: " + exception);
+ }
+ @Override
+ public void error(TransformerException exception) throws TransformerException {
+ throw exception;
+ }
+ @Override
+ public void fatalError(TransformerException exception) throws TransformerException {
+ throw exception;
+ }
+ }
+
+ static ErrorListener createDefaultErrorListener() {
+ try {
+ Class<?> errorHandler =
+ Class.forName("com.sun.org.apache.xml.internal.utils.DefaultErrorHandler");
+ Constructor<?> ctor = errorHandler.getConstructor();
+ return (ErrorListener) ctor.newInstance();
+ } catch (Throwable r) {
+ return new DummyErrorListenerHandler();
+ }
+ }
+
+ private static void printLocation(PrintWriter diagnosticsWriter, Throwable throwable) {
+ try {
+ Class<?> errorHandler =
+ Class.forName("com.sun.org.apache.xml.internal.utils.DefaultErrorHandler");
+ Method m = errorHandler.getMethod("printLocation", PrintWriter.class, Throwable.class);
+ m.invoke(null, diagnosticsWriter, throwable);
+ } catch (Throwable t) {
+ SourceLocator locator = null;
+ Throwable cause = throwable;
+
+ // Try to find the locator closest to the cause.
+ do {
+ if (cause instanceof TransformerException) {
+ SourceLocator causeLocator = ((TransformerException) cause).getLocator();
+ if (null != causeLocator) {
+ locator = causeLocator;
+ }
+ cause = ((TransformerException) cause).getCause();
+ } else if (cause instanceof SAXException) {
+ cause = ((SAXException) cause).getException();
+ } else {
+ cause = cause.getCause();
+ }
+ } while (null != cause);
+
+ if (null != locator) {
+ // m_pw.println("Parser fatal error: "+exception.getMessage());
+ String id = (null != locator.getPublicId())
+ ? locator.getPublicId()
+ : (null != locator.getSystemId())
+ ? locator.getSystemId() : "SystemId Unknown"; //"SystemId Unknown";
+
+ diagnosticsWriter.print(id + "; " + "line: " + locator.getLineNumber()
+ + "; column: " + locator.getColumnNumber() + "; ");
+ }
+ diagnosticsWriter.print("(" + throwable + ": unknown location)");
+ }
+ }
+
+}
--- a/jaxws/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/jaxws/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -321,3 +321,4 @@
285939df908721cdb2b18a119638114306b8dca7 jdk9-b73
6232472e51418757f7b2bf05332678ea78096e6b jdk9-b74
086bcd5e4a531a350c84668c8dc019461588ee3d jdk9-b75
+55bb88306dc57d07f2c854803465f6d9a7eb4aba jdk9-b76
--- a/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -321,9 +321,12 @@
String scheme = uri.getScheme();
// check installed providers
- for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+ for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
if (scheme.equalsIgnoreCase(provider.getScheme())) {
- return provider.newFileSystem(uri, env);
+ try {
+ return provider.newFileSystem(uri, env);
+ } catch (UnsupportedOperationException uoe) {
+ }
}
}
@@ -331,9 +334,12 @@
if (loader != null) {
ServiceLoader<FileSystemProvider> sl = ServiceLoader
.load(FileSystemProvider.class, loader);
- for (FileSystemProvider provider: sl) {
+ for (FileSystemProvider provider : sl) {
if (scheme.equalsIgnoreCase(provider.getScheme())) {
- return provider.newFileSystem(uri, env);
+ try {
+ return provider.newFileSystem(uri, env);
+ } catch (UnsupportedOperationException uoe) {
+ }
}
}
}
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Mon Aug 10 18:58:25 2015 -0700
@@ -1772,7 +1772,7 @@
*
* <tr><td valign="top">{@code 'n'}
* <td> the platform-specific line separator as returned by {@link
- * System#getProperty System.getProperty("line.separator")}.
+ * System#lineSeparator()}.
*
* </table>
*
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/GnomeFileTypeDetector.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/GnomeFileTypeDetector.java Mon Aug 10 18:58:25 2015 -0700
@@ -67,7 +67,7 @@
// GIO
private static native boolean initializeGio();
- private static native byte[] probeGio(long pathAddress);
+ private static synchronized native byte[] probeGio(long pathAddress);
static {
AccessController.doPrivileged(new PrivilegedAction<>() {
--- a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_convert.c Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_convert.c Mon Aug 10 18:58:25 2015 -0700
@@ -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.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@@ -474,6 +474,7 @@
jfieldID fieldID;
jclass jSsl3RandomDataClass;
jobject jRandomInfo, jRIClientRandom, jRIServerRandom, jVersion;
+ memset(&ckParam, 0, sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
/* get RandomInfo */
jSsl3MasterKeyDeriveParamsClass = (*env)->FindClass(env, CLASS_SSL3_MASTER_KEY_DERIVE_PARAMS);
@@ -527,6 +528,7 @@
CK_TLS_PRF_PARAMS ckParam;
jfieldID fieldID;
jobject jSeed, jLabel, jOutput;
+ memset(&ckParam, 0, sizeof(CK_TLS_PRF_PARAMS));
// TBD: what if jParam == NULL?!
@@ -592,6 +594,7 @@
jobject jRandomInfo, jRIClientRandom, jRIServerRandom;
jobject jReturnedKeyMaterial, jRMIvClient, jRMIvServer;
CK_ULONG ckTemp;
+ memset(&ckParam, 0, sizeof(CK_SSL3_KEY_MAT_PARAMS));
/* get ulMacSizeInBits */
jSsl3KeyMatParamsClass = (*env)->FindClass(env, CLASS_SSL3_KEY_MAT_PARAMS);
@@ -1355,6 +1358,7 @@
jlong jHashAlg, jMgf, jSource;
jobject jSourceData;
CK_BYTE_PTR ckpByte;
+ memset(&ckParam, 0, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
/* get hashAlg */
jRsaPkcsOaepParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_OAEP_PARAMS);
@@ -1404,6 +1408,7 @@
jlong jIteration;
jobject jInitVector, jPassword, jSalt;
CK_ULONG ckTemp;
+ memset(&ckParam, 0, sizeof(CK_PBE_PARAMS));
/* get pInitVector */
jPbeParamsClass = (*env)->FindClass(env, CLASS_PBE_PARAMS);
@@ -1522,6 +1527,7 @@
jfieldID fieldID;
jlong jSaltSource, jIteration, jPrf;
jobject jSaltSourceData, jPrfData;
+ memset(&ckParam, 0, sizeof(CK_PKCS5_PBKD2_PARAMS));
/* get saltSource */
jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
@@ -1734,6 +1740,7 @@
jfieldID fieldID;
jlong jKdf;
jobject jOtherInfo, jPublicData;
+ memset(&ckParam, 0, sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
/* get kdf */
jX942Dh1DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH1_DERIVE_PARAMS);
@@ -1779,6 +1786,7 @@
jfieldID fieldID;
jlong jKdf, jPrivateDataLen, jPrivateData;
jobject jOtherInfo, jPublicData, jPublicData2;
+ memset(&ckParam, 0, sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
/* get kdf */
jX942Dh2DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH2_DERIVE_PARAMS);
--- a/jdk/test/java/nio/file/FileSystem/Basic.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/test/java/nio/file/FileSystem/Basic.java Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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,17 +22,23 @@
*/
/* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 8132497
* @summary Unit test for java.nio.file.FileSystem
- * @library ..
+ * @library .. /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run main/othervm Basic
*/
+import java.io.File;
import java.nio.file.*;
-import java.nio.file.attribute.*;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import jdk.testlibrary.FileUtils;
/**
- * Simple santity checks for java.nio.file.FileSystem
+ * Simple sanity checks for java.nio.file.FileSystem
*/
public class Basic {
@@ -48,7 +54,25 @@
}
}
- public static void main(String[] args) throws IOException {
+ static void checkNoUOE() throws IOException, URISyntaxException {
+ String dir = System.getProperty("test.dir", ".");
+ String fileName = dir + File.separator + "foo.bar";
+ Path path = Paths.get(fileName);
+ Path file = Files.createFile(path);
+ try {
+ URI uri = new URI("jar", file.toUri().toString(), null);
+ System.out.println(uri);
+ FileSystem fs = FileSystems.newFileSystem(uri, new HashMap());
+ fs.close();
+ } catch (ProviderNotFoundException pnfe) {
+ System.out.println("Expected ProviderNotFoundException caught: "
+ + "\"" + pnfe.getMessage() + "\"");
+ } finally {
+ FileUtils.deleteFileWithRetry(path);
+ }
+ }
+
+ public static void main(String[] args) throws IOException, URISyntaxException {
FileSystem fs = FileSystems.getDefault();
// close should throw UOE
@@ -80,5 +104,9 @@
checkSupported(fs, "posix", "unix", "owner");
if (os.equals("Windows"))
checkSupported(fs, "owner", "dos", "acl", "user");
+
+ // sanity check non-throwing of UnsupportedOperationException by
+ // FileSystems.newFileSystem(URI, ..)
+ checkNoUOE();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+
+/* @test
+ * @summary Test probing content type simultaneously from multiple threads.
+ * @requires (os.family == "linux") | (os.family == "solaris")
+ * @build ParallelProbes SimpleFileTypeDetector
+ * @run main/othervm ParallelProbes 10
+ */
+public class ParallelProbes {
+
+ private static final int REPEATS = 1000;
+
+ private int numThreads = 0;
+ private ArrayList<Thread> threads;
+
+ public ParallelProbes(int numThreads) {
+ System.out.println("Using <" + numThreads + "> threads.");
+ this.numThreads = numThreads;
+ this.threads = new ArrayList<Thread>(numThreads);
+ }
+
+ private Path createTmpFile() throws IOException {
+ final Path p = Files.createTempFile("prefix", ".json");
+ Files.write(p, "{\"test\"}".getBytes());
+ System.out.println("Write test file <" + p + ">");
+ return p;
+ }
+
+ private Runnable createRunnable(final Path p) {
+ Runnable r = new Runnable() {
+ public void run() {
+ for (int i = 0; i < REPEATS; i++) {
+ try {
+ System.out.println(Thread.currentThread().getName()
+ + " -> " + Files.probeContentType(p));
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
+ }
+ }
+ }
+ };
+ return r;
+ }
+
+ public void start() throws IOException {
+ for (int i = 0; i < numThreads; i++) {
+ final Path p = createTmpFile();
+ Runnable r = createRunnable(p);
+ Thread thread = new Thread(r, "thread-" + i);
+ thread.start();
+ threads.add(thread);
+ }
+ }
+
+ public void join() {
+ for (Thread thread : threads) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ // ignore it and proceed to the next one
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ ParallelProbes probes =
+ new ParallelProbes(args.length < 1 ? 1 : Integer.parseInt(args[0]));
+ probes.start();
+ probes.join();
+ }
+}
--- a/jdk/test/java/util/TimeZone/CLDRDisplayNamesTest.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/test/java/util/TimeZone/CLDRDisplayNamesTest.java Mon Aug 10 18:58:25 2015 -0700
@@ -109,9 +109,6 @@
fmtROOT.parse("Thu Nov 13 04:35:51 AKST 2008");
fmtUS.parse("Thu Nov 13 04:35:51 AKST 2008");
fmtUK.parse("Thu Nov 13 04:35:51 GMT-09:00 2008");
- String dateString = new Date().toString();
- System.out.println("Date: "+dateString);
- System.out.println("Parsed Date: "+new Date(Date.parse(dateString)).toString());
} catch (ParseException pe) {
System.err.println(pe);
errors++;
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Thu Aug 06 13:00:45 2015 -0700
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Mon Aug 10 18:58:25 2015 -0700
@@ -35,6 +35,7 @@
* @test
* @bug 4486658 5031862
* @run main TimeoutLockLoops
+ * @key intermittent
* @summary Checks for responsiveness of locks to timeouts.
* Runs under the assumption that ITERS computations require more than
* TIMEOUT msecs to complete, which seems to be a safe assumption for
--- a/langtools/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -318,3 +318,4 @@
1fccc38cd6f56cb2173195e317ba2784b484c2d1 jdk9-b73
02681b7c4232ba5d43ccba794492db9502211ff0 jdk9-b74
827915d1e55eac4f2e138f9b8c79d154862c2284 jdk9-b75
+80ab772222fb6b85f8174bf97261178ee4026620 jdk9-b76
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Mon Aug 10 18:58:25 2015 -0700
@@ -27,7 +27,11 @@
import com.sun.tools.javac.code.Kinds.Kind;
import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.util.*;
@@ -35,8 +39,6 @@
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
/** A scope represents an area of visibility in a Java program. The
* Scope class is a container for symbols which provides
@@ -721,8 +723,8 @@
prependSubScope(currentFileScope);
}
- public Scope importByName(Types types, Scope origin, Name name, ImportFilter filter) {
- return appendScope(new FilterImportScope(types, origin, name, filter, true));
+ public Scope importByName(Types types, Scope origin, Name name, ImportFilter filter, JCImport imp, BiConsumer<JCImport, CompletionFailure> cfHandler) {
+ return appendScope(new FilterImportScope(types, origin, name, filter, imp, cfHandler));
}
public Scope importType(Scope delegate, Scope origin, Symbol sym) {
@@ -786,15 +788,16 @@
public void importAll(Types types, Scope origin,
ImportFilter filter,
- boolean staticImport) {
+ JCImport imp,
+ BiConsumer<JCImport, CompletionFailure> cfHandler) {
for (Scope existing : subScopes) {
Assert.check(existing instanceof FilterImportScope);
FilterImportScope fis = (FilterImportScope) existing;
if (fis.origin == origin && fis.filter == filter &&
- fis.staticImport == staticImport)
+ fis.imp.staticImport == imp.staticImport)
return ; //avoid entering the same scope twice
}
- prependSubScope(new FilterImportScope(types, origin, null, filter, staticImport));
+ prependSubScope(new FilterImportScope(types, origin, null, filter, imp, cfHandler));
}
public boolean isFilled() {
@@ -813,32 +816,40 @@
private final Scope origin;
private final Name filterName;
private final ImportFilter filter;
- private final boolean staticImport;
+ private final JCImport imp;
+ private final BiConsumer<JCImport, CompletionFailure> cfHandler;
public FilterImportScope(Types types,
Scope origin,
Name filterName,
ImportFilter filter,
- boolean staticImport) {
+ JCImport imp,
+ BiConsumer<JCImport, CompletionFailure> cfHandler) {
super(origin.owner);
this.types = types;
this.origin = origin;
this.filterName = filterName;
this.filter = filter;
- this.staticImport = staticImport;
+ this.imp = imp;
+ this.cfHandler = cfHandler;
}
@Override
public Iterable<Symbol> getSymbols(final Filter<Symbol> sf, final LookupKind lookupKind) {
if (filterName != null)
return getSymbolsByName(filterName, sf, lookupKind);
- SymbolImporter si = new SymbolImporter(staticImport) {
- @Override
- Iterable<Symbol> doLookup(TypeSymbol tsym) {
- return tsym.members().getSymbols(sf, lookupKind);
- }
- };
- return si.importFrom((TypeSymbol) origin.owner) :: iterator;
+ try {
+ SymbolImporter si = new SymbolImporter(imp.staticImport) {
+ @Override
+ Iterable<Symbol> doLookup(TypeSymbol tsym) {
+ return tsym.members().getSymbols(sf, lookupKind);
+ }
+ };
+ return si.importFrom((TypeSymbol) origin.owner) :: iterator;
+ } catch (CompletionFailure cf) {
+ cfHandler.accept(imp, cf);
+ return Collections.emptyList();
+ }
}
@Override
@@ -847,13 +858,18 @@
final LookupKind lookupKind) {
if (filterName != null && filterName != name)
return Collections.emptyList();
- SymbolImporter si = new SymbolImporter(staticImport) {
- @Override
- Iterable<Symbol> doLookup(TypeSymbol tsym) {
- return tsym.members().getSymbolsByName(name, sf, lookupKind);
- }
- };
- return si.importFrom((TypeSymbol) origin.owner) :: iterator;
+ try {
+ SymbolImporter si = new SymbolImporter(imp.staticImport) {
+ @Override
+ Iterable<Symbol> doLookup(TypeSymbol tsym) {
+ return tsym.members().getSymbolsByName(name, sf, lookupKind);
+ }
+ };
+ return si.importFrom((TypeSymbol) origin.owner) :: iterator;
+ } catch (CompletionFailure cf) {
+ cfHandler.accept(imp, cf);
+ return Collections.emptyList();
+ }
}
@Override
@@ -863,7 +879,7 @@
@Override
public boolean isStaticallyImported(Symbol byName) {
- return staticImport;
+ return imp.staticImport;
}
abstract class SymbolImporter {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Mon Aug 10 18:58:25 2015 -0700
@@ -27,6 +27,7 @@
import java.util.HashSet;
import java.util.Set;
+import java.util.function.BiConsumer;
import javax.tools.JavaFileObject;
@@ -284,6 +285,8 @@
Env<AttrContext> env;
ImportFilter staticImportFilter;
ImportFilter typeImportFilter;
+ BiConsumer<JCImport, CompletionFailure> cfHandler =
+ (imp, cf) -> chk.completionError(imp.pos(), cf);
@Override
protected void doRunPhase(Env<AttrContext> env) {
@@ -327,7 +330,7 @@
PackageSymbol javaLang = syms.enterPackage(names.java_lang);
if (javaLang.members().isEmpty() && !javaLang.exists())
throw new FatalError(diags.fragment("fatal.err.no.java.lang"));
- importAll(tree.pos, javaLang, env);
+ importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env);
// Process the package def and all import clauses.
if (tree.getPackage() != null)
@@ -378,13 +381,13 @@
// Import on demand.
chk.checkCanonical(imp.selected);
if (tree.staticImport)
- importStaticAll(tree.pos, p, env);
+ importStaticAll(tree, p, env);
else
- importAll(tree.pos, p, env);
+ importAll(tree, p, env);
} else {
// Named type import.
if (tree.staticImport) {
- importNamedStatic(tree.pos(), p, name, localEnv, tree);
+ importNamedStatic(tree, p, name, localEnv);
chk.checkCanonical(imp.selected);
} else {
TypeSymbol c = attribImportType(imp, localEnv).tsym;
@@ -411,51 +414,50 @@
}
/** Import all classes of a class or package on demand.
- * @param pos Position to be used for error reporting.
+ * @param imp The import that is being handled.
* @param tsym The class or package the members of which are imported.
* @param env The env in which the imported classes will be entered.
*/
- private void importAll(int pos,
+ private void importAll(JCImport imp,
final TypeSymbol tsym,
Env<AttrContext> env) {
- env.toplevel.starImportScope.importAll(types, tsym.members(), typeImportFilter, false);
+ env.toplevel.starImportScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler);
}
/** Import all static members of a class or package on demand.
- * @param pos Position to be used for error reporting.
+ * @param imp The import that is being handled.
* @param tsym The class or package the members of which are imported.
* @param env The env in which the imported classes will be entered.
*/
- private void importStaticAll(int pos,
+ private void importStaticAll(JCImport imp,
final TypeSymbol tsym,
Env<AttrContext> env) {
final StarImportScope toScope = env.toplevel.starImportScope;
final TypeSymbol origin = tsym;
- toScope.importAll(types, origin.members(), staticImportFilter, true);
+ toScope.importAll(types, origin.members(), staticImportFilter, imp, cfHandler);
}
/** Import statics types of a given name. Non-types are handled in Attr.
- * @param pos Position to be used for error reporting.
+ * @param imp The import that is being handled.
* @param tsym The class from which the name is imported.
* @param name The (simple) name being imported.
* @param env The environment containing the named import
* scope to add to.
*/
- private void importNamedStatic(final DiagnosticPosition pos,
+ private void importNamedStatic(final JCImport imp,
final TypeSymbol tsym,
final Name name,
- final Env<AttrContext> env,
- final JCImport imp) {
+ final Env<AttrContext> env) {
if (tsym.kind != TYP) {
- log.error(DiagnosticFlag.RECOVERABLE, pos, "static.imp.only.classes.and.interfaces");
+ log.error(DiagnosticFlag.RECOVERABLE, imp.pos(), "static.imp.only.classes.and.interfaces");
return;
}
final NamedImportScope toScope = env.toplevel.namedImportScope;
final Scope originMembers = tsym.members();
- imp.importScope = toScope.importByName(types, originMembers, name, staticImportFilter);
+ imp.importScope = toScope.importByName(types, originMembers, name, staticImportFilter, imp, cfHandler);
}
/** Import given class.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApiTypeParam.java Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApiTypeParam.java Mon Aug 10 18:58:25 2015 -0700
@@ -1,3 +1,28 @@
+/*
+ * 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.pubapi;
import java.io.Serializable;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/importscope/CompletionFailureDuringImport.java Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,86 @@
+/*
+ * 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 8131915
+ * @summary Verify that CompletionFailure thrown during listing of import content is handled properly.
+ * @library /tools/lib
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+public class CompletionFailureDuringImport {
+ public static void main(String... args) throws Exception {
+ new CompletionFailureDuringImport().run();
+ }
+
+ ToolBox tb = new ToolBox();
+
+ void run() throws Exception {
+ tb.new JavacTask()
+ .outdir(".")
+ .sources("package p; public class Super { public static final int I = 0; }",
+ "package p; public class Sub extends Super { }")
+ .run()
+ .writeAll();
+
+ Files.delete(Paths.get(".", "p", "Super.class"));
+
+ doTest("import static p.Sub.*;",
+ "",
+ "Test.java:1:1: compiler.err.cant.access: p.Super, (compiler.misc.class.file.not.found: p.Super)",
+ "1 error");
+ doTest("import static p.Sub.I;",
+ "",
+ "Test.java:1:1: compiler.err.cant.access: p.Super, (compiler.misc.class.file.not.found: p.Super)",
+ "1 error");
+ doTest("import static p.Sub.*;",
+ "int i = I;",
+ "Test.java:1:1: compiler.err.cant.access: p.Super, (compiler.misc.class.file.not.found: p.Super)",
+ "Test.java:1:52: compiler.err.cant.resolve.location: kindname.variable, I, , , (compiler.misc.location: kindname.class, Test, null)",
+ "2 errors");
+ doTest("import static p.Sub.I;",
+ "int i = I;",
+ "Test.java:1:1: compiler.err.cant.access: p.Super, (compiler.misc.class.file.not.found: p.Super)",
+ "Test.java:1:52: compiler.err.cant.resolve.location: kindname.variable, I, , , (compiler.misc.location: kindname.class, Test, null)",
+ "2 errors");
+ }
+
+ void doTest(String importText, String useText, String... expectedOutput) {
+ List<String> log = tb.new JavacTask()
+ .classpath(".")
+ .sources(importText + " public class Test { " + useText + " }")
+ .options("-XDrawDiagnostics")
+ .run(ToolBox.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+ if (!log.equals(Arrays.asList(expectedOutput))) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+}
--- a/langtools/test/tools/javac/scope/HashCollisionTest.java Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/test/tools/javac/scope/HashCollisionTest.java Mon Aug 10 18:58:25 2015 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7004029
+ * @bug 7004029 8131915
* @summary Ensure Scope impl can cope with hash collisions
* @library /tools/javac/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -37,6 +37,7 @@
import java.lang.reflect.*;
import java.io.*;
+import java.util.function.BiConsumer;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacTrees;
@@ -45,6 +46,8 @@
import com.sun.tools.javac.code.Scope.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.TreeMaker;
import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -57,6 +60,7 @@
// set up basic environment for test
Context context = new Context();
JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
+ make = TreeMaker.instance(context);
names = Names.instance(context); // Name.Table impls tied to an instance of Names
symtab = Symtab.instance(context);
trees = JavacTrees.instance(context);
@@ -127,12 +131,14 @@
return sym.kind == TYP;
}
};
- starImportScope.importAll(types, fromScope, typeFilter, false);
+ BiConsumer<JCImport, CompletionFailure> noCompletionFailure =
+ (imp, cf) -> { throw new IllegalStateException(); };
+ starImportScope.importAll(types, fromScope, typeFilter, make.Import(null, false), noCompletionFailure);
dump("imported p", starImportScope);
// 7. Insert the class from 3.
- starImportScope.importAll(types, cc.members_field, typeFilter, false);
+ starImportScope.importAll(types, cc.members_field, typeFilter, make.Import(null, false), noCompletionFailure);
dump("imported ce", starImportScope);
/*
@@ -199,6 +205,7 @@
int MAX_TRIES = 100; // max tries to find a hash clash before giving up.
int scopeHashMask;
+ TreeMaker make;
Names names;
Symtab symtab;
Trees trees;
--- a/langtools/test/tools/javac/scope/StarImportTest.java Thu Aug 06 13:00:45 2015 -0700
+++ b/langtools/test/tools/javac/scope/StarImportTest.java Mon Aug 10 18:58:25 2015 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7004029
+ * @bug 7004029 8131915
* @summary Basher for star-import scopes
* @modules jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.file
@@ -39,6 +39,7 @@
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -136,6 +137,7 @@
log ("setup");
context = new Context();
JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
+ make = TreeMaker.instance(context);
names = Names.instance(context); // Name.Table impls tied to an instance of Names
symtab = Symtab.instance(context);
types = Types.instance(context);
@@ -227,7 +229,7 @@
public boolean accepts(Scope origin, Symbol t) {
return t.kind == TYP;
}
- }, false);
+ }, make.Import(null, false), (i, cf) -> { throw new IllegalStateException(); });
for (Symbol sym : members.getSymbols()) {
starImportModel.enter(sym);
@@ -295,6 +297,7 @@
Context context;
Symtab symtab;
+ TreeMaker make;
Names names;
Types types;
int nextNameSerial;
--- a/make/Main.gmk Thu Aug 06 13:00:45 2015 -0700
+++ b/make/Main.gmk Mon Aug 10 18:58:25 2015 -0700
@@ -78,11 +78,14 @@
interim-rmic:
+($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CompileInterimRmic.gmk)
+interim-cldrconverter:
+ +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CopyInterimCLDRConverter.gmk)
+
buildtools-jdk:
+($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Tools.gmk java-tools)
ALL_TARGETS += buildtools-langtools interim-langtools interim-corba \
- interim-rmic buildtools-jdk
+ interim-rmic interim-cldrconverter buildtools-jdk
################################################################################
# Special targets for certain modules
@@ -345,7 +348,7 @@
interim-langtools: $(LANGTOOLS_GENSRC_TARGETS)
- buildtools-jdk: interim-langtools
+ buildtools-jdk: interim-langtools interim-cldrconverter
$(CORBA_GENSRC_TARGETS): interim-langtools
--- a/nashorn/.hgtags Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/.hgtags Mon Aug 10 18:58:25 2015 -0700
@@ -309,3 +309,4 @@
548f1eb2c3c89e024ef3805f48ceed9de503588f jdk9-b73
2e8bb16872d7b15dc0a4f8e45c6ad65f762c1b04 jdk9-b74
f884dff432a7ac349153f3d1ea1eb222f3764c6c jdk9-b75
+ab231613d7206431ba31917a02e7cedd70e88e70 jdk9-b76
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Aug 10 18:58:25 2015 -0700
@@ -1480,7 +1480,7 @@
}
@Override
void consumeStack() {
- dynamicCall(2 + argsCount, flags);
+ dynamicCall(2 + argsCount, flags, ident.getName());
}
}.emit();
}
@@ -1538,7 +1538,7 @@
@Override
void consumeStack() {
// Ordinary call
- dynamicCall(2 + argsCount, flags);
+ dynamicCall(2 + argsCount, flags, "eval");
method._goto(eval_done);
method.label(invoke_direct_eval);
@@ -1610,7 +1610,7 @@
}
@Override
void consumeStack() {
- dynamicCall(2 + argCount, flags);
+ dynamicCall(2 + argCount, flags, node.toString(false));
}
}.emit();
@@ -1635,9 +1635,7 @@
@Override
void consumeStack() {
- final int flags = getCallSiteFlags();
- //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
- dynamicCall(2 + argsCount, flags);
+ dynamicCall(2 + argsCount, getCallSiteFlags(), origCallee.getName());
}
}.emit();
return false;
@@ -1666,8 +1664,7 @@
}
@Override
void consumeStack() {
- final int flags = getCallSiteFlags();
- dynamicCall(2 + argsCount, flags);
+ dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
}
}.emit();
return false;
@@ -1687,7 +1684,7 @@
@Override
void consumeStack() {
final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
- dynamicCall(2 + argsCount, flags);
+ dynamicCall(2 + argsCount, flags, node.toString(false));
}
}.emit();
return false;
@@ -3707,10 +3704,11 @@
final CallNode callNode = (CallNode)unaryNode.getExpression();
final List<Expression> args = callNode.getArgs();
+ final Expression func = callNode.getFunction();
// Load function reference.
- loadExpressionAsObject(callNode.getFunction()); // must detect type error
-
- method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
+ loadExpressionAsObject(func); // must detect type error
+
+ method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
}
private void loadNOT(final UnaryNode unaryNode) {
@@ -4818,11 +4816,11 @@
return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
}
- MethodEmitter dynamicCall(final int argCount, final int flags) {
+ MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
if (isOptimistic) {
- return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
- }
- return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
+ return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
+ }
+ return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
}
int getOptimisticFlags(final int flags) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Mon Aug 10 18:58:25 2015 -0700
@@ -2132,10 +2132,25 @@
* @return the method emitter
*/
MethodEmitter dynamicNew(final int argCount, final int flags) {
+ return dynamicNew(argCount, flags, null);
+ }
+
+ /**
+ * Generate a dynamic new
+ *
+ * @param argCount number of arguments
+ * @param flags callsite flags
+ * @param msg additional message to be used when reporting error
+ *
+ * @return the method emitter
+ */
+ MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) {
assert !isOptimistic(flags);
debug("dynamic_new", "argcount=", argCount);
final String signature = getDynamicSignature(Type.OBJECT, argCount);
- method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
+ method.visitInvokeDynamicInsn(
+ msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new",
+ signature, LINKERBOOTSTRAP, flags);
pushType(Type.OBJECT); //TODO fix result type
return this;
}
@@ -2150,10 +2165,26 @@
* @return the method emitter
*/
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
+ return dynamicCall(returnType, argCount, flags, null);
+ }
+
+ /**
+ * Generate a dynamic call
+ *
+ * @param returnType return type
+ * @param argCount number of arguments
+ * @param flags callsite flags
+ * @param msg additional message to be used when reporting error
+ *
+ * @return the method emitter
+ */
+ MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) {
debug("dynamic_call", "args=", argCount, "returnType=", returnType);
final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
debug(" signature", signature);
- method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
+ method.visitInvokeDynamicInsn(
+ msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call",
+ signature, LINKERBOOTSTRAP, flags);
pushType(returnType);
return this;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SharedScopeCall.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SharedScopeCall.java Mon Aug 10 18:58:25 2015 -0700
@@ -169,7 +169,7 @@
slot += type.getSlots();
}
// Shared scope calls disabled in optimistic world. TODO is this right?
- method.dynamicCall(returnType, 2 + paramTypes.length, flags);
+ method.dynamicCall(returnType, 2 + paramTypes.length, flags, symbol.getName());
}
method._return(returnType);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java Mon Aug 10 18:58:25 2015 -0700
@@ -141,9 +141,17 @@
public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
@Override
- public String toString() {
+ public final String toString() {
+ return toString(true);
+ }
+
+ /*
+ * Return String representation of this Node.
+ * @param includeTypeInfo include type information or not
+ */
+ public final String toString(final boolean includeTypeInfo) {
final StringBuilder sb = new StringBuilder();
- toString(sb);
+ toString(sb, includeTypeInfo);
return sb.toString();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Mon Aug 10 18:58:25 2015 -0700
@@ -1859,7 +1859,7 @@
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
- return notAFunction();
+ return notAFunction(desc);
}
/**
@@ -1872,11 +1872,11 @@
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
- return notAFunction();
+ return notAFunction(desc);
}
- private GuardedInvocation notAFunction() {
- throw typeError("not.a.function", ScriptRuntime.safeToString(this));
+ private GuardedInvocation notAFunction(final CallSiteDescriptor desc) {
+ throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, this));
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Mon Aug 10 18:58:25 2015 -0700
@@ -96,8 +96,12 @@
switch (operator) {
case "new":
- case "call":
- throw lookupTypeError("cant.call.undefined", desc);
+ case "call": {
+ final String name = NashornCallSiteDescriptor.getFunctionDescription(desc);
+ final String msg = name != null? "not.a.function" : "cant.call.undefined";
+ throw typeError(msg, name);
+ }
+
case "callMethod":
throw lookupTypeError("cant.read.property.of.undefined", desc);
// NOTE: we support getElem and setItem as JavaScript doesn't distinguish items from properties. Nashorn itself
@@ -125,7 +129,8 @@
}
private static ECMAException lookupTypeError(final String msg, final CallSiteDescriptor desc) {
- return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
+ final String name = desc.getNameToken(2);
+ return typeError(msg, name != null && !name.isEmpty()? name : null);
}
private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Mon Aug 10 18:58:25 2015 -0700
@@ -27,6 +27,8 @@
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
@@ -92,7 +94,7 @@
if(BeansLinker.isDynamicMethod(self)) {
throw typeError("method.not.constructor", ScriptRuntime.safeToString(self));
}
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+ throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
case "call":
if(BeansLinker.isDynamicConstructor(self)) {
throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
@@ -100,10 +102,12 @@
if(BeansLinker.isDynamicMethod(self)) {
throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
}
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+ throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
case "callMethod":
+ throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
case "getMethod":
- throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
+ // evaluate to undefined, later on Undefined will take care of throwing TypeError
+ return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc);
case "getProp":
case "getElem":
if(NashornCallSiteDescriptor.isOptimistic(desc)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Mon Aug 10 18:58:25 2015 -0700
@@ -34,6 +34,7 @@
import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.ir.debug.NashornTextifier;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
* Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@@ -150,7 +151,7 @@
public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
final MethodType methodType, final int flags) {
final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name);
- assert tokenizedName.length == 2 || tokenizedName.length == 3;
+ assert tokenizedName.length >= 2;
assert "dyn".equals(tokenizedName[0]);
assert tokenizedName[1] != null;
// TODO: see if we can move mangling/unmangling into Dynalink
@@ -248,6 +249,54 @@
}
/**
+ * If this is a dyn:call or dyn:new, this returns function description from callsite.
+ * Caller has to make sure this is a dyn:call or dyn:new call site.
+ *
+ * @return function description if available (or null)
+ */
+ public String getFunctionDescription() {
+ assert getFirstOperator().equals("call") || getFirstOperator().equals("new");
+ return getNameTokenCount() > 2? getNameToken(2) : null;
+ }
+
+ /**
+ * If this is a dyn:call or dyn:new, this returns function description from callsite.
+ * Caller has to make sure this is a dyn:call or dyn:new call site.
+ *
+ * @param desc call site descriptor
+ * @return function description if available (or null)
+ */
+ public static String getFunctionDescription(final CallSiteDescriptor desc) {
+ return desc instanceof NashornCallSiteDescriptor ?
+ ((NashornCallSiteDescriptor)desc).getFunctionDescription() : null;
+ }
+
+
+ /**
+ * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+ *
+ * @param obj object on which dyn:call or dyn:new is used
+ * @return error message
+ */
+ public String getFunctionErrorMessage(final Object obj) {
+ final String funcDesc = getFunctionDescription();
+ return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
+ }
+
+ /**
+ * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+ *
+ * @param desc call site descriptor
+ * @param obj object on which dyn:call or dyn:new is used
+ * @return error message
+ */
+ public static String getFunctionErrorMessage(final CallSiteDescriptor desc, final Object obj) {
+ return desc instanceof NashornCallSiteDescriptor ?
+ ((NashornCallSiteDescriptor)desc).getFunctionErrorMessage(obj) :
+ ScriptRuntime.safeToString(obj);
+ }
+
+ /**
* Returns the Nashorn-specific flags for this call site descriptor.
* @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
* {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Aug 10 18:58:25 2015 -0700
@@ -78,6 +78,7 @@
type.error.not.a.regexp={0} is not a RegExp
type.error.not.a.string={0} is not a String
type.error.not.a.function={0} is not a function
+type.error.not.a.function.value={0}, which has value {1}, is not a function
type.error.not.a.constructor={0} is not a constructor function
type.error.not.a.file={0} is not a File
type.error.not.a.numeric.array={0} is not a numeric array
--- a/nashorn/test/script/basic/JDK-8026016.js.EXPECTED Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/JDK-8026016.js.EXPECTED Mon Aug 10 18:58:25 2015 -0700
@@ -1,182 +1,182 @@
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such method _,0
-no such method _,1
-no such method _,2
-no such method _,3
-no such method _,4
-no such method _,5
-no such method _,6
-no such method _,7
-no such method _,8
-no such method _,9
-no such method _,10
-no such method _,11
-no such method _,12
-no such method _,13
-no such method _,14
-no such method _,15
-no such method _,16
-no such method _,17
-no such method _,18
-no such method _,19
-no such method _,20
-no such method _,21
-no such method _,22
-no such method _,23
-no such method _,24
-no such method _,25
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such method _,0
+no such method _,1
+no such method _,2
+no such method _,3
+no such method _,4
+no such method _,5
+no such method _,6
+no such method _,7
+no such method _,8
+no such method _,9
+no such method _,10
+no such method _,11
+no such method _,12
+no such method _,13
+no such method _,14
+no such method _,15
+no such method _,16
+no such method _,17
+no such method _,18
+no such method _,19
+no such method _,20
+no such method _,21
+no such method _,22
+no such method _,23
+no such method _,24
+no such method _,25
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
--- a/nashorn/test/script/basic/JDK-8036743.js Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/JDK-8036743.js Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8073733.js Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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-8073733: TypeError messages with "call" and "new" could be improved
+ *
+ * @test
+ * @run
+ */
+
+var func = undefined;
+try {
+ func();
+} catch (e) {
+ print(e);
+}
+
+var obj = {};
+try {
+ obj.foo();
+} catch (e) {
+ print(e);
+}
+
+try {
+ new func();
+} catch (e) {
+ print(e);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8073733.js.EXPECTED Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,3 @@
+TypeError: func is not a function
+TypeError: obj.foo is not a function
+TypeError: func is not a function
--- a/nashorn/test/script/basic/JDK-8114838.js Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/JDK-8114838.js Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/nashorn/test/script/basic/JDK-8130853.js Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/JDK-8130853.js Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/nashorn/test/script/basic/JDK-8131039.js Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/JDK-8131039.js Mon Aug 10 18:58:25 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8133119.js Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,81 @@
+/*
+ * 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-8133119: Error message associated with TypeError for call and new should include stringified Node
+ *
+ * @test
+ * @run
+ */
+
+var obj = {}
+try {
+ obj.func();
+} catch (e) {
+ print(e);
+}
+
+var arr = [33];
+try {
+ arr[0].func();
+} catch (e) {
+ print(e);
+}
+
+try {
+ new obj.func();
+} catch (e) {
+ print(e);
+}
+
+try {
+ new arr[0].func();
+} catch (e) {
+ print(e);
+}
+
+obj.foo = {}
+try {
+ new obj.foo();
+} catch (e) {
+ print(e);
+}
+
+try {
+ obj.foo();
+} catch (e) {
+ print(e);
+}
+
+var v = new java.util.Vector();
+try {
+ v();
+} catch (e) {
+ print(e);
+}
+
+try {
+ new v();
+} catch (e) {
+ print(e);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8133119.js.EXPECTED Mon Aug 10 18:58:25 2015 -0700
@@ -0,0 +1,8 @@
+TypeError: obj.func is not a function
+TypeError: arr[0].func is not a function
+TypeError: obj.func is not a function
+TypeError: arr[0].func is not a function
+TypeError: obj.foo is not a function
+TypeError: obj.foo is not a function
+TypeError: v is not a function
+TypeError: v is not a function
--- a/nashorn/test/script/basic/NASHORN-75.js.EXPECTED Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/NASHORN-75.js.EXPECTED Mon Aug 10 18:58:25 2015 -0700
@@ -1,3 +1,3 @@
-TypeError: [RegExp /a|b/g] is not a function
-TypeError: [String hello] is not a function
-TypeError: [object Object] is not a function
+TypeError: RegExp("a|b", "g") is not a function
+TypeError: new String("hello") is not a function
+TypeError: new Object() is not a function
--- a/nashorn/test/script/basic/errors.js.EXPECTED Thu Aug 06 13:00:45 2015 -0700
+++ b/nashorn/test/script/basic/errors.js.EXPECTED Mon Aug 10 18:58:25 2015 -0700
@@ -1,31 +1,31 @@
-Error is a function
-EvalError is a function
-RangeError is a function
-ReferenceError is a function
-SyntaxError is a function
-TypeError is a function
-URIError is a function
-Error.arity 1
-EvalError.arity 1
-RangeError.arity 1
-ReferenceError.arity 1
-SyntaxError.arity 1
-TypeError.arity 1
-URIError.arity 1
-true
-my error
-Error
-thrown @ 49
-true
-ReferenceError
-"foo" is not defined
-true
-TypeError
-Cannot call undefined
-Error
-EvalError
-RangeError
-ReferenceError
-SyntaxError
-TypeError
-URIError
+Error is a function
+EvalError is a function
+RangeError is a function
+ReferenceError is a function
+SyntaxError is a function
+TypeError is a function
+URIError is a function
+Error.arity 1
+EvalError.arity 1
+RangeError.arity 1
+ReferenceError.arity 1
+SyntaxError.arity 1
+TypeError.arity 1
+URIError.arity 1
+true
+my error
+Error
+thrown @ 49
+true
+ReferenceError
+"foo" is not defined
+true
+TypeError
+Object.foo_method is not a function
+Error
+EvalError
+RangeError
+ReferenceError
+SyntaxError
+TypeError
+URIError
--- a/test/lib/sun/hotspot/WhiteBox.java Thu Aug 06 13:00:45 2015 -0700
+++ b/test/lib/sun/hotspot/WhiteBox.java Mon Aug 10 18:58:25 2015 -0700
@@ -182,6 +182,30 @@
Objects.requireNonNull(method);
return isMethodQueuedForCompilation0(method);
}
+ // Determine if the compiler corresponding to the compilation level 'compLevel'
+ // and to the compilation context 'compilation_context' provides an intrinsic
+ // for the method 'method'. An intrinsic is available for method 'method' if:
+ // - the intrinsic is enabled (by using the appropriate command-line flag) and
+ // - the platform on which the VM is running provides the instructions necessary
+ // for the compiler to generate the intrinsic code.
+ //
+ // The compilation context is related to using the DisableIntrinsic flag on a
+ // per-method level, see hotspot/src/share/vm/compiler/abstractCompiler.hpp
+ // for more details.
+ public boolean isIntrinsicAvailable(Executable method,
+ Executable compilationContext,
+ int compLevel) {
+ Objects.requireNonNull(method);
+ return isIntrinsicAvailable0(method, compilationContext, compLevel);
+ }
+ // If usage of the DisableIntrinsic flag is not expected (or the usage can be ignored),
+ // use the below method that does not require the compilation context as argument.
+ public boolean isIntrinsicAvailable(Executable method, int compLevel) {
+ return isIntrinsicAvailable(method, null, compLevel);
+ }
+ private native boolean isIntrinsicAvailable0(Executable method,
+ Executable compilationContext,
+ int compLevel);
public int deoptimizeMethod(Executable method) {
return deoptimizeMethod(method, false /*not osr*/);
}