Merge
This commit is contained in:
commit
0f76c8f754
@ -318,3 +318,4 @@ c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
|
||||
4c2cbaae528bce970dabbb5676005d379357f4b6 jdk9-b73
|
||||
57f3134853ecdd4a3ee2d4d26f22ba981d653d79 jdk9-b74
|
||||
8fd6eeb878606e39c908f12535f34ebbfd225a4a jdk9-b75
|
||||
d82072b699b880a1f647a5e2d7c0f86cec958941 jdk9-b76
|
||||
|
@ -318,3 +318,4 @@ f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72
|
||||
29096b78d93b01a2f8882509cd40755e3d6b8cd9 jdk9-b73
|
||||
622fe934e351e89107edf3c667d6b57f543f58f1 jdk9-b74
|
||||
960b56805abd8460598897481820bd6a75f979e7 jdk9-b75
|
||||
d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
|
||||
|
@ -478,3 +478,4 @@ c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72
|
||||
e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73
|
||||
fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74
|
||||
2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
|
||||
0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
|
||||
|
162
hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java
Normal file
162
hotspot/agent/src/share/classes/sun/jvm/hotspot/SAGetopt.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
359
hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java
Normal file
359
hotspot/agent/src/share/classes/sun/jvm/hotspot/SALauncher.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,21 @@ import sun.jvm.hotspot.debugger.cdbg.*;
|
||||
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 abstract class AARCH64ThreadContext implements ThreadContext {
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ import sun.jvm.hotspot.memory.MemRegion;
|
||||
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 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
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 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
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 class G1CollectedHeap extends CollectedHeap {
|
||||
}
|
||||
|
||||
public long used() {
|
||||
return allocator().getSummaryBytes();
|
||||
return summaryBytesUsedField.getValue(addr);
|
||||
}
|
||||
|
||||
public long n_regions() {
|
||||
@ -96,11 +97,6 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
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,
|
||||
|
@ -2167,8 +2167,12 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
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 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
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);
|
||||
}
|
||||
MacroAssembler _masm(cbuf);
|
||||
__ movw(as_Register(Matcher::_regEncode[dst_lo]),
|
||||
as_Register(Matcher::_regEncode[src_lo]));
|
||||
}
|
||||
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));
|
||||
} 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 { // 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 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]);
|
||||
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);
|
||||
__ 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]);
|
||||
} 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 { // 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);
|
||||
}
|
||||
} 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]);
|
||||
}
|
||||
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);
|
||||
}
|
||||
} 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 {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
} 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 {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
return 8;
|
||||
break;
|
||||
default:
|
||||
assert(false, "bad rc_class for spill");
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
assert(false," bad rc_class for spill ");
|
||||
Unimplemented();
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -2522,7 +2307,7 @@ void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
}
|
||||
|
||||
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
|
||||
return implementation(NULL, ra_, true, NULL);
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -1896,7 +1896,7 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
#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
|
||||
|
||||
|
@ -2009,6 +2009,14 @@ void MacroAssembler::addw(Register Rd, Register Rn, RegisterOrConstant increment
|
||||
}
|
||||
}
|
||||
|
||||
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::offsetted_address(Register r, Register r1,
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -464,10 +464,21 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
// 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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
} 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 @@ void VM_Version::get_processor_features() {
|
||||
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 @@ void VM_Version::get_processor_features() {
|
||||
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;
|
||||
|
@ -1550,6 +1550,13 @@ void os::print_dll_info(outputStream *st) {
|
||||
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 @@ void os::print_memory_info(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
}
|
||||
|
||||
|
@ -1600,24 +1600,6 @@ void* os::dll_lookup(void* handle, const char* name) {
|
||||
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 @@ int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *pa
|
||||
#endif
|
||||
}
|
||||
|
||||
void os::print_os_info_brief(outputStream* st) {
|
||||
st->print("Bsd");
|
||||
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) {
|
||||
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 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// 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 @@ void os::print_memory_info(outputStream* st) {
|
||||
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) {
|
||||
|
@ -2043,31 +2043,96 @@ void os::print_os_info(outputStream* st) {
|
||||
// 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.
|
||||
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");
|
||||
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) {
|
||||
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 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -236,6 +236,15 @@ void os::Posix::print_uname_info(outputStream* st) {
|
||||
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 @@ bool PosixSemaphore::trywait() {
|
||||
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) {
|
||||
|
@ -1971,6 +1971,26 @@ void os::Solaris::print_distro_info(outputStream* st) {
|
||||
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 @@ static bool check_addr0(outputStream* st) {
|
||||
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.
|
||||
}
|
||||
|
@ -1593,6 +1593,21 @@ int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *pa
|
||||
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_brief(outputStream* st) {
|
||||
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 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// 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);
|
||||
|
@ -99,6 +99,164 @@ BufferBlob* Compiler::init_buffer_blob() {
|
||||
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::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
||||
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);
|
||||
}
|
||||
|
@ -55,6 +55,18 @@ class Compiler: public AbstractCompiler {
|
||||
// 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();
|
||||
};
|
||||
|
@ -3372,231 +3372,85 @@ const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
|
||||
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 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
|
||||
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 @@ void GraphBuilder::pop_scope_for_jsr() {
|
||||
_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 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -339,6 +339,8 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||
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 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||
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);
|
||||
|
||||
|
@ -153,7 +153,19 @@ ValueType* as_ValueType(ciConstant value) {
|
||||
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;
|
||||
|
@ -809,6 +809,22 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found,
|
||||
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 @@ class BacktraceBuilder: public StackObj {
|
||||
|
||||
};
|
||||
|
||||
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* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
|
||||
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 @@ oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
|
||||
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);
|
||||
|
@ -276,6 +276,7 @@ class java_lang_Class : AllStatic {
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -86,7 +86,7 @@ bool VerificationType::is_reference_assignable_from(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -297,6 +297,26 @@ class VerificationType VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -324,6 +324,319 @@ vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest)
|
||||
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 =
|
||||
|
@ -1368,6 +1368,26 @@ public:
|
||||
|
||||
// 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
|
||||
|
@ -66,6 +66,58 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
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; }
|
||||
|
@ -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 @@ void CompileTask::mark_on_stack() {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ void CompileQueue::free_all() {
|
||||
* 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 @@ CompileTask* CompileQueue::get() {
|
||||
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;
|
||||
|
@ -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 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
||||
|
||||
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 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
||||
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,
|
||||
|
@ -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::non_clean_card_iterate_parallel_work(Space* sp, MemRegio
|
||||
}
|
||||
|
||||
void
|
||||
CardTableModRefBS::
|
||||
CardTableModRefBSForCTRS::
|
||||
process_stride(Space* sp,
|
||||
MemRegion used,
|
||||
jint stride, int n_strides,
|
||||
@ -170,7 +171,7 @@ process_stride(Space* sp,
|
||||
#endif
|
||||
|
||||
void
|
||||
CardTableModRefBS::
|
||||
CardTableModRefBSForCTRS::
|
||||
process_chunk_boundaries(Space* sp,
|
||||
DirtyCardToOopClosure* dcto_cl,
|
||||
MemRegion chunk_mr,
|
||||
@ -426,7 +427,7 @@ process_chunk_boundaries(Space* sp,
|
||||
#undef NOISY
|
||||
|
||||
void
|
||||
CardTableModRefBS::
|
||||
CardTableModRefBSForCTRS::
|
||||
get_LNC_array_for_space(Space* sp,
|
||||
jbyte**& lowest_non_clean,
|
||||
uintptr_t& lowest_non_clean_base_chunk_index,
|
||||
|
@ -403,14 +403,6 @@ void CMMarkStack::note_end_of_gc() {
|
||||
_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 @@ ConcurrentMark::claim_region(uint worker_id) {
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
public:
|
||||
VerifyNoCSetOops(const char* phase, int info = -1) :
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_phase(phase),
|
||||
_info(info)
|
||||
{ }
|
||||
|
||||
void do_object_work(oop obj) {
|
||||
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 @@ void ConcurrentMark::verify_no_cset_oops() {
|
||||
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 @@ void ConcurrentMark::verify_no_cset_oops() {
|
||||
|
||||
// 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) {
|
||||
|
@ -246,9 +246,10 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC {
|
||||
// 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 {
|
||||
|
@ -223,6 +223,15 @@ inline bool CMBitMap::parClear(HeapWord* addr) {
|
||||
|
||||
#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");
|
||||
|
@ -39,13 +39,8 @@ class G1Allocator : public CHeapObj<mtGC> {
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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();
|
||||
|
@ -632,7 +632,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first,
|
||||
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 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
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 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
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 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
|
||||
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 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||
_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 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||
_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 @@ jint G1CollectedHeap::initialize() {
|
||||
|
||||
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 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl,
|
||||
|
||||
// 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() const {
|
||||
}
|
||||
|
||||
size_t G1CollectedHeap::used_unlocked() const {
|
||||
return _allocator->used_unlocked();
|
||||
return _summary_bytes_used;
|
||||
}
|
||||
|
||||
class SumUsedClosure: public HeapRegionClosure {
|
||||
@ -3376,7 +3381,7 @@ void G1CollectedHeap::print_extended_on(outputStream* st) const {
|
||||
|
||||
// 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 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
_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 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
} 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 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
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 @@ void G1CollectedHeap::remove_self_forwarding_pointers() {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
_objs_with_preserved_marks.clear(true);
|
||||
_preserved_marks_of_objs.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);
|
||||
_evacuation_failed_info_array[queue_num].register_copy_failure(obj->size());
|
||||
|
||||
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!");
|
||||
// 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,15 +4366,8 @@ void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
|
||||
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:
|
||||
G1CollectedHeap* _g1h;
|
||||
@ -4597,9 +4506,6 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ void G1CollectedHeap::process_discovered_references() {
|
||||
|
||||
// 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 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
|
||||
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 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
|
||||
purge_code_root_memory();
|
||||
|
||||
finalize_for_evac_failure();
|
||||
|
||||
if (evacuation_failed()) {
|
||||
remove_self_forwarding_pointers();
|
||||
|
||||
@ -5745,7 +5636,7 @@ void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::decrement_summary_bytes(size_t bytes) {
|
||||
_allocator->decrease_used(bytes);
|
||||
decrease_used(bytes);
|
||||
}
|
||||
|
||||
class G1ParCleanupCTTask : public AbstractGangTask {
|
||||
@ -6395,6 +6286,21 @@ void G1CollectedHeap::tear_down_region_sets(bool free_list_only) {
|
||||
_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 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
|
||||
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 @@ void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region,
|
||||
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
|
||||
|
@ -251,6 +251,15 @@ private:
|
||||
// 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 @@ protected:
|
||||
// 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
|
||||
|
@ -111,7 +111,6 @@ protected:
|
||||
|
||||
enum G1Barrier {
|
||||
G1BarrierNone,
|
||||
G1BarrierEvac,
|
||||
G1BarrierKlass
|
||||
};
|
||||
|
||||
@ -148,8 +147,6 @@ typedef G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> G1ParScanAndMar
|
||||
// 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;
|
||||
|
@ -144,8 +144,6 @@ bool G1ParScanThreadState::verify_task(StarTask ref) const {
|
||||
#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 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
|
||||
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 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
|
||||
// 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 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,6 @@ class G1ParScanThreadState : public StackObj {
|
||||
uint _tenuring_threshold;
|
||||
G1ParScanClosure _scanner;
|
||||
|
||||
OopsInHeapRegionClosure* _evac_failure_cl;
|
||||
|
||||
int _hash_seed;
|
||||
uint _queue_num;
|
||||
|
||||
@ -114,12 +112,6 @@ class G1ParScanThreadState : public StackObj {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ class G1ParScanThreadState : public StackObj {
|
||||
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
|
||||
|
@ -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 " \
|
||||
|
@ -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
|
||||
|
@ -40,7 +40,6 @@ class CheckForUnmarkedOops : public OopClosure {
|
||||
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 @@ class CheckForUnmarkedOops : public OopClosure {
|
||||
// Don't overwrite the first missing card mark
|
||||
if (_unmarked_addr == NULL) {
|
||||
_unmarked_addr = (HeapWord*)p;
|
||||
_unmarked_card = _card_table->byte_for(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ void DefNewGeneration::collect(bool full,
|
||||
{
|
||||
// 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,
|
||||
|
@ -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 @@ CardTableModRefBS::CardTableModRefBS(
|
||||
_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 @@ void CardTableModRefBS::initialize() {
|
||||
!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 @@ CardTableModRefBS::~CardTableModRefBS() {
|
||||
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::write_ref_field_work(void* field, oop newVal, bool relea
|
||||
}
|
||||
|
||||
|
||||
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 @@ void CardTableModRefBS::print_on(outputStream* st) const {
|
||||
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));
|
||||
};
|
||||
|
@ -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 @@ class CardTableModRefBS: public ModRefBarrierSet {
|
||||
// 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 @@ class CardTableModRefBS: public ModRefBarrierSet {
|
||||
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 @@ class CardTableModRefBS: public ModRefBarrierSet {
|
||||
// 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 @@ struct BarrierSet::GetName<CardTableModRefBS> {
|
||||
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
|
||||
|
129
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp
Normal file
129
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
143
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp
Normal file
143
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp
Normal file
@ -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
|
||||
|
@ -240,7 +240,7 @@ void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
|
||||
// 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 @@ void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) {
|
||||
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 @@ void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) {
|
||||
!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;
|
||||
}
|
||||
|
@ -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 @@ class CardTableRS: public GenRemSet {
|
||||
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 @@ class CardTableRS: public GenRemSet {
|
||||
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 @@ public:
|
||||
// *** 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 @@ public:
|
||||
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); }
|
||||
|
@ -295,8 +295,9 @@ public:
|
||||
// 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.
|
||||
|
@ -259,20 +259,14 @@ inline typename TaskQueueSuper<N, F>::Age TaskQueueSuper<N, F>::Age::cmpxchg(con
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 @@ jint universe_init() {
|
||||
|
||||
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();
|
||||
|
@ -200,7 +200,6 @@ class oopDesc {
|
||||
|
||||
// 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);
|
||||
|
@ -284,11 +284,7 @@ inline oop oopDesc::obj_field(int offset) const {
|
||||
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);
|
||||
|
@ -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") \
|
||||
|
@ -79,7 +79,6 @@ bool C2Compiler::init_c2_runtime() {
|
||||
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::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -36,7 +36,6 @@ public:
|
||||
|
||||
// Name
|
||||
const char *name() { return "C2"; }
|
||||
|
||||
void initialize();
|
||||
|
||||
// Compilation entry point for methods
|
||||
@ -52,6 +51,26 @@ public:
|
||||
// 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();
|
||||
};
|
||||
|
@ -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 @@ class LibraryCallKit : public GraphKit {
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// -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.
|
||||
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:
|
||||
if (is_available) {
|
||||
assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
|
||||
assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
|
||||
break;
|
||||
return new LibraryIntrinsic(m, is_virtual,
|
||||
vmIntrinsics::predicates_needed(id),
|
||||
vmIntrinsics::does_virtual_dispatch(id),
|
||||
(vmIntrinsics::ID) id);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// -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);
|
||||
}
|
||||
|
||||
//----------------------register_library_intrinsics-----------------------
|
||||
@ -812,7 +523,6 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
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);
|
||||
|
@ -2824,7 +2824,7 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) {
|
||||
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;
|
||||
}
|
||||
|
@ -528,6 +528,24 @@ WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobje
|
||||
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 @@ static JNINativeMethod methods[] = {
|
||||
#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",
|
||||
|
@ -788,9 +788,11 @@ void Arguments::print_on(outputStream* st) {
|
||||
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 @@ void Arguments::print_on(outputStream* st) {
|
||||
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 @@ void Arguments::print_jvm_args_on(outputStream* st) {
|
||||
for (int i=0; i < _num_jvm_args; i++) {
|
||||
st->print("%s ", _jvm_args_array[i]);
|
||||
}
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,32 +1226,6 @@ void Arguments::set_tiered_flags() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ bool Arguments::check_vm_args_consistency() {
|
||||
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 @@ jint Arguments::adjust_after_os() {
|
||||
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;
|
||||
|
@ -445,9 +445,6 @@ class Arguments : AllStatic {
|
||||
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 @@ class Arguments : AllStatic {
|
||||
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 @@ class Arguments : AllStatic {
|
||||
|
||||
// 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); }
|
||||
|
@ -39,7 +39,9 @@ class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_int : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_intx : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_uint : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_uintx : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_uint64_t : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_size_t : public CommandLineFlagConstraint {
|
||||
|
||||
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 @@ class CommandLineFlagConstraint_double : public CommandLineFlagConstraint {
|
||||
|
||||
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_size_t(const char* /*name*/) { /* NOP */ }
|
||||
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 @@ void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_doub
|
||||
#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 @@ void CommandLineFlagConstraintList::init(void) {
|
||||
#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;
|
||||
}
|
||||
|
@ -49,13 +49,27 @@ typedef Flag::Error (*CommandLineFlagConstraintFunc_size_t)(bool verbose, size_t
|
||||
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 @@ public:
|
||||
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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
return Flag::SUCCESS;
|
||||
}
|
||||
|
@ -36,4 +36,6 @@
|
||||
|
||||
Flag::Error AliasLevelConstraintFunc(bool verbose, intx* value);
|
||||
|
||||
Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value);
|
||||
|
||||
#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSCOMPILER_HPP */
|
||||
|
@ -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 MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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 MaxHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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 MinMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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 MaxMetaspaceFreeRatioConstraintFunc(bool verbose, uintx* value) {
|
||||
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 InitialTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
|
||||
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 @@ Flag::Error MaxTenuringThresholdConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
#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 G1NewSizePercentConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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 @@ Flag::Error G1MaxNewSizePercentConstraintFunc(bool verbose, uintx* value) {
|
||||
#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 CMSOldPLABMinConstraintFunc(bool verbose, size_t* value) {
|
||||
}
|
||||
|
||||
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 CMSPrecleanDenominatorConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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 CMSPrecleanNumeratorConstraintFunc(bool verbose, uintx* value) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -365,3 +365,63 @@ void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool un
|
||||
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;
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
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
|
||||
|
@ -770,7 +770,7 @@ static Flag::Error get_status_error(Flag::Error status_range, Flag::Error status
|
||||
|
||||
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::Error CommandLineFlags::boolAtPut(const char* name, size_t len, bool* valu
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_int(const char* name, int* n
|
||||
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::Error CommandLineFlags::intAtPut(const char* name, size_t len, int* value,
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_uint(const char* name, uint*
|
||||
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::Error CommandLineFlags::uintAtPut(const char* name, size_t len, uint* valu
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx*
|
||||
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::Error CommandLineFlags::intxAtPut(const char* name, size_t len, intx* valu
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uint
|
||||
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::Error CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* va
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, u
|
||||
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::Error CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_size_t(const char* name, siz
|
||||
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::Error CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t*
|
||||
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 @@ static Flag::Error apply_constraint_and_check_range_double(const char* name, dou
|
||||
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::Error CommandLineFlags::doubleAtPut(const char* name, size_t len, double*
|
||||
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 CommandLineFlags::doubleAtPut(const char* name, size_t len, double*
|
||||
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 @@ void CommandLineFlags::printSetFlags(outputStream* out) {
|
||||
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() {
|
||||
|
@ -450,7 +450,6 @@ class SizeTFlagSetting {
|
||||
|
||||
|
||||
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 @@ public:
|
||||
// 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 @@ public:
|
||||
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 @@ public:
|
||||
\
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
\
|
||||
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 @@ public:
|
||||
"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 @@ public:
|
||||
"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 @@ public:
|
||||
/* 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 @@ public:
|
||||
" 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 @@ public:
|
||||
"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 @@ public:
|
||||
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 @@ public:
|
||||
\
|
||||
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 @@ public:
|
||||
// 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, \
|
||||
|
@ -83,7 +83,6 @@ Mutex* DirtyCardQ_FL_lock = NULL;
|
||||
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 @@ void mutex_init() {
|
||||
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);
|
||||
|
@ -87,7 +87,6 @@ extern Mutex* Shared_DirtyCardQ_lock; // Lock protecting dirty card
|
||||
// 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
|
||||
|
@ -843,6 +843,28 @@ void os::print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
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 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
|
||||
|
||||
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 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
|
||||
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
|
||||
|
@ -150,6 +150,11 @@ class os: AllStatic {
|
||||
|
||||
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 @@ class os: AllStatic {
|
||||
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);
|
||||
|
@ -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 @@ void JavaThread::metadata_do(void f(Metadata*)) {
|
||||
if (ct->env() != NULL) {
|
||||
ct->env()->metadata_do(f);
|
||||
}
|
||||
if (ct->task() != NULL) {
|
||||
ct->task()->metadata_do(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3319,8 +3324,15 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -148,8 +148,7 @@ void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, co
|
||||
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());
|
||||
|
@ -899,6 +899,11 @@ void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) {
|
||||
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
|
||||
|
@ -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 @@ void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {
|
||||
Unimplemented();
|
||||
|
||||
CreateStore(
|
||||
LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
|
||||
LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
|
||||
CreateIntToPtr(
|
||||
CreateAdd(
|
||||
LLVMValue::intptr_constant(
|
||||
|
@ -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;
|
||||
|
||||
|
@ -306,6 +306,30 @@ void VMError::print_stack_trace(outputStream* st, JavaThread* jt,
|
||||
#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 @@ void VMError::report(outputStream* st) {
|
||||
|
||||
// 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 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
STEP(15, "(printing type of error)")
|
||||
STEP(50, "(printing type of error)")
|
||||
|
||||
switch(_id) {
|
||||
case OOM_MALLOC_ERROR:
|
||||
@ -418,19 +442,7 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
// 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 @@ void VMError::report(outputStream* st) {
|
||||
break;
|
||||
}
|
||||
|
||||
STEP(20, "(printing exception/signal name)")
|
||||
STEP(60, "(printing exception/signal name)")
|
||||
|
||||
st->print_cr("#");
|
||||
st->print("# ");
|
||||
@ -470,14 +482,14 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
STEP(50, "(printing Java version string)")
|
||||
STEP(90, "(printing Java version string)")
|
||||
|
||||
// VM version
|
||||
st->print_cr("#");
|
||||
@ -498,15 +510,18 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
STEP(80, "(printing current thread)" )
|
||||
STEP(180, "(printing current thread)" )
|
||||
|
||||
// current thread
|
||||
if (_verbose) {
|
||||
@ -559,31 +604,20 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
STEP(170, "(printing all threads)" )
|
||||
STEP(290, "(printing all threads)" )
|
||||
|
||||
// all threads
|
||||
if (_verbose && _thread) {
|
||||
@ -685,7 +732,7 @@ void VMError::report(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
STEP(175, "(printing VM state)" )
|
||||
STEP(300, "(printing VM state)" )
|
||||
|
||||
if (_verbose) {
|
||||
// Safepoint state
|
||||
@ -707,7 +754,7 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
STEP(210, "(printing VM options)" )
|
||||
STEP(380, "(printing VM options)" )
|
||||
|
||||
if (_verbose) {
|
||||
// VM options
|
||||
@ -774,33 +821,33 @@ void VMError::report(outputStream* st) {
|
||||
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 @@ void VMError::report(outputStream* st) {
|
||||
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
|
||||
|
||||
|
@ -89,6 +89,9 @@ class VMError : public StackObj {
|
||||
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; }
|
||||
|
135
hotspot/test/compiler/arguments/CheckCICompilerCount.java
Normal file
135
hotspot/test/compiler/arguments/CheckCICompilerCount.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
126
hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java
Normal file
126
hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -67,7 +67,7 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
|
||||
compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
|
||||
}
|
||||
|
||||
if (!isIntrinsicSupported()) {
|
||||
if (!isIntrinsicAvailable()) {
|
||||
expectedIntrinsicCount = 0;
|
||||
}
|
||||
break;
|
||||
@ -114,7 +114,11 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
|
||||
}
|
||||
|
||||
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 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -28,47 +28,89 @@ public class MathIntrinsic {
|
||||
|
||||
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);
|
||||
}
|
||||
},
|
||||
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 {
|
||||
@ -92,36 +134,66 @@ public class MathIntrinsic {
|
||||
|
||||
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 @@ public class MathIntrinsic {
|
||||
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 {
|
||||
|
@ -94,29 +94,47 @@ public class TestLargePageUseForAuxMemory {
|
||||
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 @@ public class TestLargePageUseForAuxMemory {
|
||||
// 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");
|
||||
|
@ -48,7 +48,6 @@ public class ObjectAlignment {
|
||||
.shouldHaveExitValue(1);
|
||||
|
||||
testObjectAlignment(-1)
|
||||
.shouldContain("must be power of 2")
|
||||
.shouldContain("outside the allowed range")
|
||||
.shouldHaveExitValue(1);
|
||||
|
||||
@ -75,4 +74,4 @@ public class ObjectAlignment {
|
||||
"-version");
|
||||
return new OutputAnalyzer(pb.start());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ import sun.misc.Unsafe;
|
||||
public class CreateCoredumpOnCrash {
|
||||
private static class Crasher {
|
||||
public static void main(String[] args) {
|
||||
Utils.getUnsafe().getInt(0);
|
||||
Utils.getUnsafe().putInt(0L, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -55,7 +55,6 @@ public class Options {
|
||||
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 @@ public class Options {
|
||||
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
|
||||
|
55
hotspot/test/runtime/verifier/PrimIntArray.java
Normal file
55
hotspot/test/runtime/verifier/PrimIntArray.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
46
hotspot/test/runtime/verifier/primArray.jasm
Normal file
46
hotspot/test/runtime/verifier/primArray.jasm
Normal file
@ -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
|
46
hotspot/test/runtime/verifier/primArray49.jasm
Normal file
46
hotspot/test/runtime/verifier/primArray49.jasm
Normal file
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user