--- a/.hgtags Wed Aug 28 09:13:01 2019 -0700
+++ b/.hgtags Thu Aug 29 16:11:22 2019 +0530
@@ -583,3 +583,4 @@
18f189e69b29f8215a3500b875127ed4fb2d977a jdk-14+9
ececb6dae777e622abda42c705fd984a42f46b5a jdk-14+10
bf4c808a4488025a415f867e54c8b088417e08a0 jdk-14+11
+8570f22b9b6ac6bec673899b582150865696e425 jdk-14+12
--- a/doc/building.html Wed Aug 28 09:13:01 2019 -0700
+++ b/doc/building.html Thu Aug 29 16:11:22 2019 +0530
@@ -572,6 +572,7 @@
<li><code>CONF_CHECK</code></li>
<li><code>COMPARE_BUILD</code></li>
<li><code>JDK_FILTER</code></li>
+<li><code>SPEC_FILTER</code></li>
</ul>
<h2 id="running-tests">Running Tests</h2>
<p>Most of the JDK tests are using the <a href="http://openjdk.java.net/jtreg">JTReg</a> test framework. Make sure that your configuration knows where to find your installation of JTReg. If this is not picked up automatically, use the <code>--with-jtreg=<path to jtreg home></code> option to point to the JTReg framework. Note that this option should point to the JTReg home, i.e. the top directory, containing <code>lib/jtreg.jar</code> etc.</p>
--- a/doc/testing.html Wed Aug 28 09:13:01 2019 -0700
+++ b/doc/testing.html Thu Aug 29 16:11:22 2019 +0530
@@ -54,7 +54,7 @@
$ make test-jdk_lang JTREG="JOBS=8"
$ make test TEST=jdk_lang
$ make test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
-$ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
+$ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT_FACTOR=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make test TEST="jtreg:test/hotspot:hotspot_gc test/hotspot/jtreg/native_sanity/JniVersion.java"
$ make test TEST="micro:java.lang.reflect" MICRO="FORK=1;WARMUP_ITER=2"
$ make exploded-test TEST=tier2</code></pre>
@@ -103,9 +103,9 @@
<p>Additional work data is stored in <code>build/$BUILD/test-support/$TEST_ID</code>. For some frameworks, this directory might contain information that is useful in determining the cause of a failed test.</p>
<h2 id="test-suite-control">Test suite control</h2>
<p>It is possible to control various aspects of the test suites using make control variables.</p>
-<p>These variables use a keyword=value approach to allow multiple values to be set. So, for instance, <code>JTREG="JOBS=1;TIMEOUT=8"</code> will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to setting <code>JTREG_JOBS=1 JTREG_TIMEOUT=8</code>, but using the keyword format means that the <code>JTREG</code> variable is parsed and verified for correctness, so <code>JTREG="TMIEOUT=8"</code> would give an error, while <code>JTREG_TMIEOUT=8</code> would just pass unnoticed.</p>
+<p>These variables use a keyword=value approach to allow multiple values to be set. So, for instance, <code>JTREG="JOBS=1;TIMEOUT_FACTOR=8"</code> will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to setting <code>JTREG_JOBS=1 JTREG_TIMEOUT_FACTOR=8</code>, but using the keyword format means that the <code>JTREG</code> variable is parsed and verified for correctness, so <code>JTREG="TMIEOUT_FACTOR=8"</code> would give an error, while <code>JTREG_TMIEOUT_FACTOR=8</code> would just pass unnoticed.</p>
<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG="...;..."</code>. This will also make sure spaces are preserved, as in <code>JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"</code>.</p>
-<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
+<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT_FACTOR=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
<p>As far as possible, the names of the keywords have been standardized between test suites.</p>
<h3 id="general-keywords-test_opts">General keywords (TEST_OPTS)</h3>
<p>Some keywords are valid across different test suites. If you want to run tests from multiple test suites, or just don't want to care which test suite specific control variable to use, then you can use the general TEST_OPTS control variable.</p>
--- a/doc/testing.md Wed Aug 28 09:13:01 2019 -0700
+++ b/doc/testing.md Thu Aug 29 16:11:22 2019 +0530
@@ -23,7 +23,7 @@
$ make test-jdk_lang JTREG="JOBS=8"
$ make test TEST=jdk_lang
$ make test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
- $ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
+ $ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT_FACTOR=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make test TEST="jtreg:test/hotspot:hotspot_gc test/hotspot/jtreg/native_sanity/JniVersion.java"
$ make test TEST="micro:java.lang.reflect" MICRO="FORK=1;WARMUP_ITER=2"
$ make exploded-test TEST=tier2
@@ -180,11 +180,11 @@
variables.
These variables use a keyword=value approach to allow multiple values to be
-set. So, for instance, `JTREG="JOBS=1;TIMEOUT=8"` will set the JTReg
+set. So, for instance, `JTREG="JOBS=1;TIMEOUT_FACTOR=8"` will set the JTReg
concurrency level to 1 and the timeout factor to 8. This is equivalent to
-setting `JTREG_JOBS=1 JTREG_TIMEOUT=8`, but using the keyword format means that
+setting `JTREG_JOBS=1 JTREG_TIMEOUT_FACTOR=8`, but using the keyword format means that
the `JTREG` variable is parsed and verified for correctness, so
-`JTREG="TMIEOUT=8"` would give an error, while `JTREG_TMIEOUT=8` would just
+`JTREG="TMIEOUT_FACTOR=8"` would give an error, while `JTREG_TMIEOUT_FACTOR=8` would just
pass unnoticed.
To separate multiple keyword=value pairs, use `;` (semicolon). Since the shell
@@ -192,7 +192,7 @@
qoutes, e.g. `JTREG="...;..."`. This will also make sure spaces are preserved,
as in `JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
-(Other ways are possible, e.g. using backslash: `JTREG=JOBS=1\;TIMEOUT=8`.
+(Other ways are possible, e.g. using backslash: `JTREG=JOBS=1\;TIMEOUT_FACTOR=8`.
Also, as a special technique, the string `%20` will be replaced with space for
certain options, e.g. `JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
This can be useful if you have layers of scripts and have trouble getting
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java Thu Aug 29 16:11:22 2019 +0530
@@ -87,6 +87,7 @@
String CICI = "string" + args.length + "string" + args.length;
String CJ = "string" + System.currentTimeMillis();
String JC = System.currentTimeMillis() + "string";
+ String CD = "string" + (args.length/2.0);
String CJC = "string" + System.currentTimeMillis() + "string";
String CJCJ = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis();
String CJCJC = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis() + "string";
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeListNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeListNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -40,20 +40,21 @@
void document(PrintWriter writer) {
writer.println("<dt>" + name() + " Data");
+ writer.println("<dd>");
if (components.isEmpty()) {
- writer.println("<dd>(None)");
+ writer.println("(None)");
} else {
- writer.println("<dd><table><tr>");
- for (int i = maxStructIndent; i > 0; --i) {
- writer.print("<th style=\"width: 4%\">");
- }
- writer.println("<th style=\"width: 15%\"><th style=\"width: 65%\">");
- writer.println("");
+ writer.println("<table><tr>");
+ writer.println("<th class=\"bold\" style=\"width: 20%\" scope=\"col\">Type");
+ writer.println("<th class=\"bold\" style=\"width: 15%\" scope=\"col\">Name");
+ writer.println("<th class=\"bold\" style=\"width: 65%\" scope=\"col\">Description");
+ writer.println("</tr>");
for (Node node : components) {
node.document(writer);
}
writer.println("</table>");
}
+ writer.println("</dd>");
}
void genJavaClassBodyComponents(PrintWriter writer, int depth) {
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -40,11 +40,11 @@
abstract String javaRead();
void document(PrintWriter writer) {
- docRowStart(writer);
- writer.println("<td colspan=" +
- (maxStructIndent - structIndent) + ">");
- writer.println(docType() + "<td><i>" + name() +
- "</i><td>" + comment() + " ");
+ writer.println("<tr>");
+ writer.println("<td>" + indentElement(structIndent, docType()));
+ writer.println("<th scope=\"row\"><i>" + name() + "</i>");
+ writer.println("<td>" + comment() + " ");
+ writer.println("</tr>");
}
String javaType() {
--- a/make/jdk/src/classes/build/tools/jdwpgen/AltNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/AltNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -46,13 +46,15 @@
}
void document(PrintWriter writer) {
- docRowStart(writer);
- writer.println("<td colspan=" +
- (maxStructIndent - structIndent + 1) + ">");
- writer.println("Case " + nameNode.name + " - if <i>" +
- ((SelectNode)parent).typeNode.name +
- "</i> is " + nameNode.value() + ":");
+ writer.println("<tr>");
+ writer.println("<th colspan=\"2\" scope=\"row\">"
+ + indentElement(structIndent,
+ "Case " + nameNode.name
+ + " - if <i>" + ((SelectNode)parent).typeNode.name + "</i>" +
+ " is " + nameNode.value() + ":"));
writer.println("<td>" + comment() + " ");
+ writer.println("</tr>");
+
++structIndent;
super.document(writer);
--structIndent;
--- a/make/jdk/src/classes/build/tools/jdwpgen/ConstantNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/ConstantNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -54,10 +54,12 @@
}
void document(PrintWriter writer) {
-
//Add anchor to each constant with format <constant table name>_<constant name>
- writer.println("<tr><td>" + name + "<td>" + nameNode.value() +
- "<td>" + comment() + " ");
+ writer.println("<tr>"
+ + "<th scope=\"row\">" + name
+ + "<td class=\"centered\">" + nameNode.value()
+ + "<td>" + comment() + " "
+ + "</tr>");
}
public String getName(){
--- a/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -54,14 +54,15 @@
}
void document(PrintWriter writer) {
- writer.println("<h2 id=\"" + context.whereC + "\">" + name +
- " Constants</h2>");
+ writer.println("<h2 id=\"" + context.whereC + "\">" + name + " Constants</h2>");
writer.println(comment());
writer.println("<table><tr>");
- writer.println("<th style=\"width: 20%\"><th style=\"width: 5%\"><th style=\"width: 65%\">");
- ConstantNode n;
+ writer.println("<th class=\"bold\" style=\"width: 30%\" scope=\"col\">Name");
+ writer.println("<th class=\"centered bold\" style=\"width: 5%\" scope=\"col\">Value");
+ writer.println("<th class=\"bold\" style=\"width: 65%\" scope=\"col\">Description");
+ writer.println("</tr>");
for (Node node : components) {
- n = (ConstantNode)node;
+ ConstantNode n = (ConstantNode)node;
writer.println("<span id=\"" + name + "_" + n.name + "\"></span>");
n.document(writer);
}
--- a/make/jdk/src/classes/build/tools/jdwpgen/ErrorNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/ErrorNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -55,9 +55,10 @@
if (com == null || com.length() == 0) {
com = ConstantSetNode.getConstant("Error_" + name);
}
- writer.println("<tr><td>" + "<a href=\"#" + NAME_OF_ERROR_TABLE + "_" + name + "\">"
- + name + "</a></td>" +
- "<td>" + com + " </td></tr>");
+ writer.println("<tr>"
+ + "<th scope=\"row\">" + "<a href=\"#" + NAME_OF_ERROR_TABLE + "_" + name + "\">" + name + "</a>"
+ + "<td>" + com + " "
+ + "</tr>");
}
void genJavaComment(PrintWriter writer, int depth) {}
--- a/make/jdk/src/classes/build/tools/jdwpgen/ErrorSetNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/ErrorSetNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -38,17 +38,21 @@
}
void document(PrintWriter writer) {
-
- writer.println("<dt>" + "Error Data");
+ writer.println("<dt>Error Data</dt>");
+ writer.print("<dd>");
if (components.isEmpty()) {
- writer.println("<dd>(None)");
+ writer.println("(None)");
} else {
- writer.println("<dd><table>");
- for (Node node : components) {
- node.document(writer);
+ writer.println("<table><tr>");
+ writer.println("<th class=\"bold\" style=\"width: 20%\" scope=\"col\">Value");
+ writer.println("<th class=\"bold\" scope=\"col\">Description");
+ writer.println("</tr>");
+ for (Node node : components) {
+ node.document(writer);
+ }
+ writer.println("</table>");
}
- writer.println("</table>");
- }
+ writer.print("</dd>");
}
void genJavaComment(PrintWriter writer, int depth) {}
--- a/make/jdk/src/classes/build/tools/jdwpgen/Node.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/Node.java Thu Aug 29 16:11:22 2019 +0530
@@ -88,11 +88,10 @@
void documentIndex(PrintWriter writer) {
}
- void docRowStart(PrintWriter writer) {
- writer.println("<tr>");
- if (structIndent > 0) {
- writer.println("<td colspan=" + structIndent + ">");
- }
+ String indentElement(int depth, String content) {
+ return depth > 0
+ ? "<div class=\"indent" + depth + "\">" + content + "</div>"
+ : content;
}
String comment() {
--- a/make/jdk/src/classes/build/tools/jdwpgen/RepeatNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/RepeatNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -44,15 +44,17 @@
}
void document(PrintWriter writer) {
- docRowStart(writer);
- writer.println("<td colspan=" +
- (maxStructIndent - structIndent) + ">");
- writer.println("int<td><i>" + name + "</i><td>" +
- comment() + " ");
- docRowStart(writer);
- writer.println("<td colspan=" +
- (maxStructIndent - structIndent + 2) + ">");
- writer.println("Repeated <i>" + name + "</i> times:");
+ writer.println("<tr>");
+ writer.println("<td>" + indentElement(structIndent, "int"));
+ writer.println("<th scope=\"row\"><i>" + name() + "</i>");
+ writer.println("<td>" + comment() + " ");
+ writer.println("</tr>");
+
+ writer.println("<tr>");
+ writer.println("<th colspan=\"3\" scope=\"rowgroup\">"
+ + indentElement(structIndent, "Repeated <i>" + name() + "</i> times:"));
+ writer.println("</tr>");
+
++structIndent;
member.document(writer);
--structIndent;
--- a/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java Wed Aug 28 09:13:01 2019 -0700
+++ b/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java Thu Aug 29 16:11:22 2019 +0530
@@ -46,15 +46,21 @@
writer.println("<meta charset=\"utf-8\"/>");
writer.println("<title>" + comment() + "</title>");
writer.println("<style>");
- writer.println("body {background-color:white;}");
- writer.println("table {border: 1px solid grey; border-spacing:0px; border-collapse: separate; width: 90%;}");
- writer.println("td, th {padding: 3px; border: 1px solid black;}");
+ writer.println("body { background-color:white; }");
+ writer.println("table { border: 1px solid grey; border-spacing:0px; border-collapse: separate; width: 90%; }");
+ writer.println("td, th { padding: 3px; border: 1px solid black; font-weight: normal; text-align: left; }");
+ writer.println(".bold { font-weight: bold; }");
+ writer.println(".centered { text-align: center; }");
+ for (int i = 0; i < maxStructIndent; i++) {
+ // each level is 40px
+ writer.println(".indent" + i + " { padding-left: " + (i * 40) + "px; }");
+ }
writer.println("</style>");
writer.println("</head>");
writer.println("<body>");
- writer.println("<div class=\"centered\" role=\"banner\">");
+ writer.println("<header>");
writer.println("<h1 id=\"Protocol_Details\">Java Debug Wire Protocol Details</h1>");
- writer.println("</div>");
+ writer.println("</header>");
writer.println("<nav>");
writer.println("<ul>");
for (Node node : components) {
@@ -62,11 +68,11 @@
}
writer.println("</ul>");
writer.println("</nav>");
- writer.println("<div role=\"main\">");
+ writer.println("<main>");
for (Node node : components) {
node.document(writer);
}
- writer.println("</div>");
+ writer.println("</main>");
writer.println("</body></html>");
}
--- a/src/hotspot/cpu/aarch64/aarch64.ad Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Thu Aug 29 16:11:22 2019 +0530
@@ -3569,7 +3569,7 @@
// Store a non-null value into the box to avoid looking like a re-entrant
// lock. The fast-path monitor unlock code checks for
// markWord::monitor_value so use markWord::unused_mark which has the
- // relevant bit set, and also matches ObjectSynchronizer::slow_enter.
+ // relevant bit set, and also matches ObjectSynchronizer::enter.
__ mov(tmp, (address)markWord::unused_mark().value());
__ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -2607,8 +2607,8 @@
// - Successful Stack-lock: box->dhw == mark.
// box->dhw must contain the displaced mark word value
// - Failure -- icc.ZFlag == 0 and box->dhw is undefined.
-// The slow-path fast_enter() and slow_enter() operators
-// are responsible for setting box->dhw = NonZero (typically markWord::unused_mark()).
+// The slow-path enter() is responsible for setting
+// box->dhw = NonZero (typically markWord::unused_mark()).
// - Biased: box->dhw is undefined
//
// SPARC refworkload performance - specifically jetstream and scimark - are
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1620,8 +1620,8 @@
// See also: cmpFastLock and cmpFastUnlock.
//
// What follows is a specialized inline transliteration of the code
-// in slow_enter() and slow_exit(). If we're concerned about I$ bloat
-// another option would be to emit TrySlowEnter and TrySlowExit methods
+// in enter() and exit(). If we're concerned about I$ bloat another
+// option would be to emit TrySlowEnter and TrySlowExit methods
// at startup-time. These methods would accept arguments as
// (rax,=Obj, rbx=Self, rcx=box, rdx=Scratch) and return success-failure
// indications in the icc.ZFlag. Fast_Lock and Fast_Unlock would simply
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zBackingFile_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2015, 2019, 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/z/zArray.inline.hpp"
+#include "gc/z/zBackingFile_linux.hpp"
+#include "gc/z/zBackingPath_linux.hpp"
+#include "gc/z/zErrno.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zLargePages.inline.hpp"
+#include "gc/z/zSyscall_linux.hpp"
+#include "logging/log.hpp"
+#include "runtime/init.hpp"
+#include "runtime/os.hpp"
+#include "utilities/align.hpp"
+#include "utilities/debug.hpp"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+//
+// Support for building on older Linux systems
+//
+
+// memfd_create(2) flags
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
+#ifndef MFD_HUGETLB
+#define MFD_HUGETLB 0x0004U
+#endif
+
+// open(2) flags
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 02000000
+#endif
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000 | O_DIRECTORY)
+#endif
+
+// fallocate(2) flags
+#ifndef FALLOC_FL_KEEP_SIZE
+#define FALLOC_FL_KEEP_SIZE 0x01
+#endif
+#ifndef FALLOC_FL_PUNCH_HOLE
+#define FALLOC_FL_PUNCH_HOLE 0x02
+#endif
+
+// Filesystem types, see statfs(2)
+#ifndef TMPFS_MAGIC
+#define TMPFS_MAGIC 0x01021994
+#endif
+#ifndef HUGETLBFS_MAGIC
+#define HUGETLBFS_MAGIC 0x958458f6
+#endif
+
+// Filesystem names
+#define ZFILESYSTEM_TMPFS "tmpfs"
+#define ZFILESYSTEM_HUGETLBFS "hugetlbfs"
+
+// Sysfs file for transparent huge page on tmpfs
+#define ZFILENAME_SHMEM_ENABLED "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
+
+// Java heap filename
+#define ZFILENAME_HEAP "java_heap"
+
+// Preferred tmpfs mount points, ordered by priority
+static const char* z_preferred_tmpfs_mountpoints[] = {
+ "/dev/shm",
+ "/run/shm",
+ NULL
+};
+
+// Preferred hugetlbfs mount points, ordered by priority
+static const char* z_preferred_hugetlbfs_mountpoints[] = {
+ "/dev/hugepages",
+ "/hugepages",
+ NULL
+};
+
+static int z_fallocate_hugetlbfs_attempts = 3;
+static bool z_fallocate_supported = true;
+
+ZBackingFile::ZBackingFile() :
+ _fd(-1),
+ _size(0),
+ _filesystem(0),
+ _block_size(0),
+ _available(0),
+ _initialized(false) {
+
+ // Create backing file
+ _fd = create_fd(ZFILENAME_HEAP);
+ if (_fd == -1) {
+ return;
+ }
+
+ // Get filesystem statistics
+ struct statfs buf;
+ if (fstatfs(_fd, &buf) == -1) {
+ ZErrno err;
+ log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string());
+ return;
+ }
+
+ _filesystem = buf.f_type;
+ _block_size = buf.f_bsize;
+ _available = buf.f_bavail * _block_size;
+
+ // Make sure we're on a supported filesystem
+ if (!is_tmpfs() && !is_hugetlbfs()) {
+ log_error(gc)("Backing file must be located on a %s or a %s filesystem",
+ ZFILESYSTEM_TMPFS, ZFILESYSTEM_HUGETLBFS);
+ return;
+ }
+
+ // Make sure the filesystem type matches requested large page type
+ if (ZLargePages::is_transparent() && !is_tmpfs()) {
+ log_error(gc)("-XX:+UseTransparentHugePages can only be enable when using a %s filesystem",
+ ZFILESYSTEM_TMPFS);
+ return;
+ }
+
+ if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) {
+ log_error(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel",
+ ZFILESYSTEM_TMPFS);
+ return;
+ }
+
+ if (ZLargePages::is_explicit() && !is_hugetlbfs()) {
+ log_error(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled "
+ "when using a %s filesystem", ZFILESYSTEM_HUGETLBFS);
+ return;
+ }
+
+ if (!ZLargePages::is_explicit() && is_hugetlbfs()) {
+ log_error(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem",
+ ZFILESYSTEM_HUGETLBFS);
+ return;
+ }
+
+ const size_t expected_block_size = is_tmpfs() ? os::vm_page_size() : os::large_page_size();
+ if (expected_block_size != _block_size) {
+ log_error(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")",
+ is_tmpfs() ? ZFILESYSTEM_TMPFS : ZFILESYSTEM_HUGETLBFS, _block_size, expected_block_size);
+ return;
+ }
+
+ // Successfully initialized
+ _initialized = true;
+}
+
+int ZBackingFile::create_mem_fd(const char* name) const {
+ // Create file name
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "%s%s", name, ZLargePages::is_explicit() ? ".hugetlb" : "");
+
+ // Create file
+ const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0;
+ const int fd = ZSyscall::memfd_create(filename, MFD_CLOEXEC | extra_flags);
+ if (fd == -1) {
+ ZErrno err;
+ log_debug(gc, init)("Failed to create memfd file (%s)",
+ ((ZLargePages::is_explicit() && err == EINVAL) ? "Hugepages not supported" : err.to_string()));
+ return -1;
+ }
+
+ log_info(gc, init)("Heap backed by file: /memfd:%s", filename);
+
+ return fd;
+}
+
+int ZBackingFile::create_file_fd(const char* name) const {
+ const char* const filesystem = ZLargePages::is_explicit()
+ ? ZFILESYSTEM_HUGETLBFS
+ : ZFILESYSTEM_TMPFS;
+ const char** const preferred_mountpoints = ZLargePages::is_explicit()
+ ? z_preferred_hugetlbfs_mountpoints
+ : z_preferred_tmpfs_mountpoints;
+
+ // Find mountpoint
+ ZBackingPath path(filesystem, preferred_mountpoints);
+ if (path.get() == NULL) {
+ log_error(gc)("Use -XX:ZPath to specify the path to a %s filesystem", filesystem);
+ return -1;
+ }
+
+ // Try to create an anonymous file using the O_TMPFILE flag. Note that this
+ // flag requires kernel >= 3.11. If this fails we fall back to open/unlink.
+ const int fd_anon = os::open(path.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
+ if (fd_anon == -1) {
+ ZErrno err;
+ log_debug(gc, init)("Failed to create anonymous file in %s (%s)", path.get(),
+ (err == EINVAL ? "Not supported" : err.to_string()));
+ } else {
+ // Get inode number for anonymous file
+ struct stat stat_buf;
+ if (fstat(fd_anon, &stat_buf) == -1) {
+ ZErrno err;
+ log_error(gc)("Failed to determine inode number for anonymous file (%s)", err.to_string());
+ return -1;
+ }
+
+ log_info(gc, init)("Heap backed by file: %s/#" UINT64_FORMAT, path.get(), (uint64_t)stat_buf.st_ino);
+
+ return fd_anon;
+ }
+
+ log_debug(gc, init)("Falling back to open/unlink");
+
+ // Create file name
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "%s/%s.%d", path.get(), name, os::current_process_id());
+
+ // Create file
+ const int fd = os::open(filename, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
+ if (fd == -1) {
+ ZErrno err;
+ log_error(gc)("Failed to create file %s (%s)", filename, err.to_string());
+ return -1;
+ }
+
+ // Unlink file
+ if (unlink(filename) == -1) {
+ ZErrno err;
+ log_error(gc)("Failed to unlink file %s (%s)", filename, err.to_string());
+ return -1;
+ }
+
+ log_info(gc, init)("Heap backed by file: %s", filename);
+
+ return fd;
+}
+
+int ZBackingFile::create_fd(const char* name) const {
+ if (ZPath == NULL) {
+ // If the path is not explicitly specified, then we first try to create a memfd file
+ // instead of looking for a tmpfd/hugetlbfs mount point. Note that memfd_create() might
+ // not be supported at all (requires kernel >= 3.17), or it might not support large
+ // pages (requires kernel >= 4.14). If memfd_create() fails, then we try to create a
+ // file on an accessible tmpfs or hugetlbfs mount point.
+ const int fd = create_mem_fd(name);
+ if (fd != -1) {
+ return fd;
+ }
+
+ log_debug(gc, init)("Falling back to searching for an accessible mount point");
+ }
+
+ return create_file_fd(name);
+}
+
+bool ZBackingFile::is_initialized() const {
+ return _initialized;
+}
+
+int ZBackingFile::fd() const {
+ return _fd;
+}
+
+size_t ZBackingFile::size() const {
+ return _size;
+}
+
+size_t ZBackingFile::available() const {
+ return _available;
+}
+
+bool ZBackingFile::is_tmpfs() const {
+ return _filesystem == TMPFS_MAGIC;
+}
+
+bool ZBackingFile::is_hugetlbfs() const {
+ return _filesystem == HUGETLBFS_MAGIC;
+}
+
+bool ZBackingFile::tmpfs_supports_transparent_huge_pages() const {
+ // If the shmem_enabled file exists and is readable then we
+ // know the kernel supports transparent huge pages for tmpfs.
+ return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0;
+}
+
+ZErrno ZBackingFile::fallocate_compat_ftruncate(size_t size) const {
+ while (ftruncate(_fd, size) == -1) {
+ if (errno != EINTR) {
+ // Failed
+ return errno;
+ }
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate_compat_mmap(size_t offset, size_t length, bool touch) const {
+ // On hugetlbfs, mapping a file segment will fail immediately, without
+ // the need to touch the mapped pages first, if there aren't enough huge
+ // pages available to back the mapping.
+ void* const addr = mmap(0, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, offset);
+ if (addr == MAP_FAILED) {
+ // Failed
+ return errno;
+ }
+
+ // Once mapped, the huge pages are only reserved. We need to touch them
+ // to associate them with the file segment. Note that we can not punch
+ // hole in file segments which only have reserved pages.
+ if (touch) {
+ char* const start = (char*)addr;
+ char* const end = start + length;
+ os::pretouch_memory(start, end, _block_size);
+ }
+
+ // Unmap again. From now on, the huge pages that were mapped are allocated
+ // to this file. There's no risk in getting SIGBUS when touching them.
+ if (munmap(addr, length) == -1) {
+ // Failed
+ return errno;
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate_compat_pwrite(size_t offset, size_t length) const {
+ uint8_t data = 0;
+
+ // Allocate backing memory by writing to each block
+ for (size_t pos = offset; pos < offset + length; pos += _block_size) {
+ if (pwrite(_fd, &data, sizeof(data), pos) == -1) {
+ // Failed
+ return errno;
+ }
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate_fill_hole_compat(size_t offset, size_t length) {
+ // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs
+ // since Linux 4.3. When fallocate(2) is not supported we emulate it using
+ // ftruncate/pwrite (for tmpfs) or ftruncate/mmap/munmap (for hugetlbfs).
+
+ const size_t end = offset + length;
+ if (end > _size) {
+ // Increase file size
+ const ZErrno err = fallocate_compat_ftruncate(end);
+ if (err) {
+ // Failed
+ return err;
+ }
+ }
+
+ // Allocate backing memory
+ const ZErrno err = is_hugetlbfs() ? fallocate_compat_mmap(offset, length, false /* touch */)
+ : fallocate_compat_pwrite(offset, length);
+ if (err) {
+ if (end > _size) {
+ // Restore file size
+ fallocate_compat_ftruncate(_size);
+ }
+
+ // Failed
+ return err;
+ }
+
+ if (end > _size) {
+ // Record new file size
+ _size = end;
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate_fill_hole_syscall(size_t offset, size_t length) {
+ const int mode = 0; // Allocate
+ const int res = ZSyscall::fallocate(_fd, mode, offset, length);
+ if (res == -1) {
+ // Failed
+ return errno;
+ }
+
+ const size_t end = offset + length;
+ if (end > _size) {
+ // Record new file size
+ _size = end;
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate_fill_hole(size_t offset, size_t length) {
+ // Using compat mode is more efficient when allocating space on hugetlbfs.
+ // Note that allocating huge pages this way will only reserve them, and not
+ // associate them with segments of the file. We must guarantee that we at
+ // some point touch these segments, otherwise we can not punch hole in them.
+ if (z_fallocate_supported && !is_hugetlbfs()) {
+ const ZErrno err = fallocate_fill_hole_syscall(offset, length);
+ if (!err) {
+ // Success
+ return 0;
+ }
+
+ if (err != ENOSYS && err != EOPNOTSUPP) {
+ // Failed
+ return err;
+ }
+
+ // Not supported
+ log_debug(gc)("Falling back to fallocate() compatibility mode");
+ z_fallocate_supported = false;
+ }
+
+ return fallocate_fill_hole_compat(offset, length);
+}
+
+ZErrno ZBackingFile::fallocate_punch_hole(size_t offset, size_t length) {
+ if (is_hugetlbfs()) {
+ // We can only punch hole in pages that have been touched. Non-touched
+ // pages are only reserved, and not associated with any specific file
+ // segment. We don't know which pages have been previously touched, so
+ // we always touch them here to guarantee that we can punch hole.
+ const ZErrno err = fallocate_compat_mmap(offset, length, true /* touch */);
+ if (err) {
+ // Failed
+ return err;
+ }
+ }
+
+ const int mode = FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE;
+ if (ZSyscall::fallocate(_fd, mode, offset, length) == -1) {
+ // Failed
+ return errno;
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::split_and_fallocate(bool punch_hole, size_t offset, size_t length) {
+ // Try first half
+ const size_t offset0 = offset;
+ const size_t length0 = align_up(length / 2, _block_size);
+ const ZErrno err0 = fallocate(punch_hole, offset0, length0);
+ if (err0) {
+ return err0;
+ }
+
+ // Try second half
+ const size_t offset1 = offset0 + length0;
+ const size_t length1 = length - length0;
+ const ZErrno err1 = fallocate(punch_hole, offset1, length1);
+ if (err1) {
+ return err1;
+ }
+
+ // Success
+ return 0;
+}
+
+ZErrno ZBackingFile::fallocate(bool punch_hole, size_t offset, size_t length) {
+ assert(is_aligned(offset, _block_size), "Invalid offset");
+ assert(is_aligned(length, _block_size), "Invalid length");
+
+ const ZErrno err = punch_hole ? fallocate_punch_hole(offset, length) : fallocate_fill_hole(offset, length);
+ if (err == EINTR && length > _block_size) {
+ // Calling fallocate(2) with a large length can take a long time to
+ // complete. When running profilers, such as VTune, this syscall will
+ // be constantly interrupted by signals. Expanding the file in smaller
+ // steps avoids this problem.
+ return split_and_fallocate(punch_hole, offset, length);
+ }
+
+ return err;
+}
+
+bool ZBackingFile::commit_inner(size_t offset, size_t length) {
+ log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
+ offset / M, (offset + length) / M, length / M);
+
+retry:
+ const ZErrno err = fallocate(false /* punch_hole */, offset, length);
+ if (err) {
+ if (err == ENOSPC && !is_init_completed() && is_hugetlbfs() && z_fallocate_hugetlbfs_attempts-- > 0) {
+ // If we fail to allocate during initialization, due to lack of space on
+ // the hugetlbfs filesystem, then we wait and retry a few times before
+ // giving up. Otherwise there is a risk that running JVMs back-to-back
+ // will fail, since there is a delay between process termination and the
+ // huge pages owned by that process being returned to the huge page pool
+ // and made available for new allocations.
+ log_debug(gc, init)("Failed to commit memory (%s), retrying", err.to_string());
+
+ // Wait and retry in one second, in the hope that huge pages will be
+ // available by then.
+ sleep(1);
+ goto retry;
+ }
+
+ // Failed
+ log_error(gc)("Failed to commit memory (%s)", err.to_string());
+ return false;
+ }
+
+ // Success
+ return true;
+}
+
+size_t ZBackingFile::commit(size_t offset, size_t length) {
+ // Try to commit the whole region
+ if (commit_inner(offset, length)) {
+ // Success
+ return length;
+ }
+
+ // Failed, try to commit as much as possible
+ size_t start = offset;
+ size_t end = offset + length;
+
+ for (;;) {
+ length = align_down((end - start) / 2, ZGranuleSize);
+ if (length < ZGranuleSize) {
+ // Done, don't commit more
+ return start - offset;
+ }
+
+ if (commit_inner(start, length)) {
+ // Success, try commit more
+ start += length;
+ } else {
+ // Failed, try commit less
+ end -= length;
+ }
+ }
+}
+
+size_t ZBackingFile::uncommit(size_t offset, size_t length) {
+ log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
+ offset / M, (offset + length) / M, length / M);
+
+ const ZErrno err = fallocate(true /* punch_hole */, offset, length);
+ if (err) {
+ log_error(gc)("Failed to uncommit memory (%s)", err.to_string());
+ return 0;
+ }
+
+ return length;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zBackingFile_linux.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2019, 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 OS_LINUX_GC_Z_ZBACKINGFILE_LINUX_HPP
+#define OS_LINUX_GC_Z_ZBACKINGFILE_LINUX_HPP
+
+#include "memory/allocation.hpp"
+
+class ZErrno;
+
+class ZBackingFile {
+private:
+ int _fd;
+ size_t _size;
+ uint64_t _filesystem;
+ size_t _block_size;
+ size_t _available;
+ bool _initialized;
+
+ int create_mem_fd(const char* name) const;
+ int create_file_fd(const char* name) const;
+ int create_fd(const char* name) const;
+
+ bool is_tmpfs() const;
+ bool is_hugetlbfs() const;
+ bool tmpfs_supports_transparent_huge_pages() const;
+
+ ZErrno fallocate_compat_ftruncate(size_t size) const;
+ ZErrno fallocate_compat_mmap(size_t offset, size_t length, bool reserve_only) const;
+ ZErrno fallocate_compat_pwrite(size_t offset, size_t length) const;
+ ZErrno fallocate_fill_hole_compat(size_t offset, size_t length);
+ ZErrno fallocate_fill_hole_syscall(size_t offset, size_t length);
+ ZErrno fallocate_fill_hole(size_t offset, size_t length);
+ ZErrno fallocate_punch_hole(size_t offset, size_t length);
+ ZErrno split_and_fallocate(bool punch_hole, size_t offset, size_t length);
+ ZErrno fallocate(bool punch_hole, size_t offset, size_t length);
+
+ bool commit_inner(size_t offset, size_t length);
+
+public:
+ ZBackingFile();
+
+ bool is_initialized() const;
+
+ int fd() const;
+ size_t size() const;
+ size_t available() const;
+
+ size_t commit(size_t offset, size_t length);
+ size_t uncommit(size_t offset, size_t length);
+};
+
+#endif // OS_LINUX_GC_Z_ZBACKINGFILE_LINUX_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zBackingPath_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016, 2019, 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/z/zArray.inline.hpp"
+#include "gc/z/zBackingPath_linux.hpp"
+#include "gc/z/zErrno.hpp"
+#include "logging/log.hpp"
+
+#include <stdio.h>
+#include <unistd.h>
+
+// Mount information, see proc(5) for more details.
+#define PROC_SELF_MOUNTINFO "/proc/self/mountinfo"
+
+ZBackingPath::ZBackingPath(const char* filesystem, const char** preferred_mountpoints) {
+ if (ZPath != NULL) {
+ // Use specified path
+ _path = strdup(ZPath);
+ } else {
+ // Find suitable path
+ _path = find_mountpoint(filesystem, preferred_mountpoints);
+ }
+}
+
+ZBackingPath::~ZBackingPath() {
+ free(_path);
+ _path = NULL;
+}
+
+char* ZBackingPath::get_mountpoint(const char* line, const char* filesystem) const {
+ char* line_mountpoint = NULL;
+ char* line_filesystem = NULL;
+
+ // Parse line and return a newly allocated string containing the mount point if
+ // the line contains a matching filesystem and the mount point is accessible by
+ // the current user.
+ if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-]- %ms", &line_mountpoint, &line_filesystem) != 2 ||
+ strcmp(line_filesystem, filesystem) != 0 ||
+ access(line_mountpoint, R_OK|W_OK|X_OK) != 0) {
+ // Not a matching or accessible filesystem
+ free(line_mountpoint);
+ line_mountpoint = NULL;
+ }
+
+ free(line_filesystem);
+
+ return line_mountpoint;
+}
+
+void ZBackingPath::get_mountpoints(const char* filesystem, ZArray<char*>* mountpoints) const {
+ FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r");
+ if (fd == NULL) {
+ ZErrno err;
+ log_error(gc)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string());
+ return;
+ }
+
+ char* line = NULL;
+ size_t length = 0;
+
+ while (getline(&line, &length, fd) != -1) {
+ char* const mountpoint = get_mountpoint(line, filesystem);
+ if (mountpoint != NULL) {
+ mountpoints->add(mountpoint);
+ }
+ }
+
+ free(line);
+ fclose(fd);
+}
+
+void ZBackingPath::free_mountpoints(ZArray<char*>* mountpoints) const {
+ ZArrayIterator<char*> iter(mountpoints);
+ for (char* mountpoint; iter.next(&mountpoint);) {
+ free(mountpoint);
+ }
+ mountpoints->clear();
+}
+
+char* ZBackingPath::find_preferred_mountpoint(const char* filesystem,
+ ZArray<char*>* mountpoints,
+ const char** preferred_mountpoints) const {
+ // Find preferred mount point
+ ZArrayIterator<char*> iter1(mountpoints);
+ for (char* mountpoint; iter1.next(&mountpoint);) {
+ for (const char** preferred = preferred_mountpoints; *preferred != NULL; preferred++) {
+ if (!strcmp(mountpoint, *preferred)) {
+ // Preferred mount point found
+ return strdup(mountpoint);
+ }
+ }
+ }
+
+ // Preferred mount point not found
+ log_error(gc)("More than one %s filesystem found:", filesystem);
+ ZArrayIterator<char*> iter2(mountpoints);
+ for (char* mountpoint; iter2.next(&mountpoint);) {
+ log_error(gc)(" %s", mountpoint);
+ }
+
+ return NULL;
+}
+
+char* ZBackingPath::find_mountpoint(const char* filesystem, const char** preferred_mountpoints) const {
+ char* path = NULL;
+ ZArray<char*> mountpoints;
+
+ get_mountpoints(filesystem, &mountpoints);
+
+ if (mountpoints.size() == 0) {
+ // No mount point found
+ log_error(gc)("Failed to find an accessible %s filesystem", filesystem);
+ } else if (mountpoints.size() == 1) {
+ // One mount point found
+ path = strdup(mountpoints.at(0));
+ } else {
+ // More than one mount point found
+ path = find_preferred_mountpoint(filesystem, &mountpoints, preferred_mountpoints);
+ }
+
+ free_mountpoints(&mountpoints);
+
+ return path;
+}
+
+const char* ZBackingPath::get() const {
+ return _path;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zBackingPath_linux.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, 2019, 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 OS_LINUX_GC_Z_ZBACKINGPATH_LINUX_HPP
+#define OS_LINUX_GC_Z_ZBACKINGPATH_LINUX_HPP
+
+#include "gc/z/zArray.hpp"
+#include "memory/allocation.hpp"
+
+class ZBackingPath : public StackObj {
+private:
+ char* _path;
+
+ char* get_mountpoint(const char* line,
+ const char* filesystem) const;
+ void get_mountpoints(const char* filesystem,
+ ZArray<char*>* mountpoints) const;
+ void free_mountpoints(ZArray<char*>* mountpoints) const;
+ char* find_preferred_mountpoint(const char* filesystem,
+ ZArray<char*>* mountpoints,
+ const char** preferred_mountpoints) const;
+ char* find_mountpoint(const char* filesystem,
+ const char** preferred_mountpoints) const;
+
+public:
+ ZBackingPath(const char* filesystem, const char** preferred_mountpoints);
+ ~ZBackingPath();
+
+ const char* get() const;
+};
+
+#endif // OS_LINUX_GC_Z_ZBACKINGPATH_LINUX_HPP
--- a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -24,6 +24,7 @@
#include "gc/z/zErrno.hpp"
#include "gc/z/zCPU.hpp"
#include "gc/z/zNUMA.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2015, 2019, 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/z/zAddress.inline.hpp"
+#include "gc/z/zErrno.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zLargePages.inline.hpp"
+#include "gc/z/zMemory.hpp"
+#include "gc/z/zNUMA.hpp"
+#include "gc/z/zPhysicalMemory.inline.hpp"
+#include "gc/z/zPhysicalMemoryBacking_linux.hpp"
+#include "logging/log.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/init.hpp"
+#include "runtime/os.hpp"
+#include "utilities/align.hpp"
+#include "utilities/debug.hpp"
+
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+//
+// Support for building on older Linux systems
+//
+
+// madvise(2) flags
+#ifndef MADV_HUGEPAGE
+#define MADV_HUGEPAGE 14
+#endif
+
+// Proc file entry for max map mount
+#define ZFILENAME_PROC_MAX_MAP_COUNT "/proc/sys/vm/max_map_count"
+
+bool ZPhysicalMemoryBacking::is_initialized() const {
+ return _file.is_initialized();
+}
+
+void ZPhysicalMemoryBacking::warn_available_space(size_t max) const {
+ // Note that the available space on a tmpfs or a hugetlbfs filesystem
+ // will be zero if no size limit was specified when it was mounted.
+ const size_t available = _file.available();
+ if (available == 0) {
+ // No size limit set, skip check
+ log_info(gc, init)("Available space on backing filesystem: N/A");
+ return;
+ }
+
+ log_info(gc, init)("Available space on backing filesystem: " SIZE_FORMAT "M", available / M);
+
+ // Warn if the filesystem doesn't currently have enough space available to hold
+ // the max heap size. The max heap size will be capped if we later hit this limit
+ // when trying to expand the heap.
+ if (available < max) {
+ log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
+ log_warning(gc)("Not enough space available on the backing filesystem to hold the current max Java heap");
+ log_warning(gc)("size (" SIZE_FORMAT "M). Please adjust the size of the backing filesystem accordingly "
+ "(available", max / M);
+ log_warning(gc)("space is currently " SIZE_FORMAT "M). Continuing execution with the current filesystem "
+ "size could", available / M);
+ log_warning(gc)("lead to a premature OutOfMemoryError being thrown, due to failure to map memory.");
+ }
+}
+
+void ZPhysicalMemoryBacking::warn_max_map_count(size_t max) const {
+ const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT;
+ FILE* const file = fopen(filename, "r");
+ if (file == NULL) {
+ // Failed to open file, skip check
+ log_debug(gc, init)("Failed to open %s", filename);
+ return;
+ }
+
+ size_t actual_max_map_count = 0;
+ const int result = fscanf(file, SIZE_FORMAT, &actual_max_map_count);
+ fclose(file);
+ if (result != 1) {
+ // Failed to read file, skip check
+ log_debug(gc, init)("Failed to read %s", filename);
+ return;
+ }
+
+ // The required max map count is impossible to calculate exactly since subsystems
+ // other than ZGC are also creating memory mappings, and we have no control over that.
+ // However, ZGC tends to create the most mappings and dominate the total count.
+ // In the worst cases, ZGC will map each granule three times, i.e. once per heap view.
+ // We speculate that we need another 20% to allow for non-ZGC subsystems to map memory.
+ const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2;
+ if (actual_max_map_count < required_max_map_count) {
+ log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
+ log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given");
+ log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at",
+ max / M, filename);
+ log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution "
+ "with the current", required_max_map_count, actual_max_map_count);
+ log_warning(gc)("limit could lead to a fatal error, due to failure to map memory.");
+ }
+}
+
+void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
+ // Warn if available space is too low
+ warn_available_space(max);
+
+ // Warn if max map count is too low
+ warn_max_map_count(max);
+}
+
+bool ZPhysicalMemoryBacking::supports_uncommit() {
+ assert(!is_init_completed(), "Invalid state");
+ assert(_file.size() >= ZGranuleSize, "Invalid size");
+
+ // Test if uncommit is supported by uncommitting and then re-committing a granule
+ return commit(uncommit(ZGranuleSize)) == ZGranuleSize;
+}
+
+size_t ZPhysicalMemoryBacking::commit(size_t size) {
+ size_t committed = 0;
+
+ // Fill holes in the backing file
+ while (committed < size) {
+ size_t allocated = 0;
+ const size_t remaining = size - committed;
+ const uintptr_t start = _uncommitted.alloc_from_front_at_most(remaining, &allocated);
+ if (start == UINTPTR_MAX) {
+ // No holes to commit
+ break;
+ }
+
+ // Try commit hole
+ const size_t filled = _file.commit(start, allocated);
+ if (filled > 0) {
+ // Successful or partialy successful
+ _committed.free(start, filled);
+ committed += filled;
+ }
+ if (filled < allocated) {
+ // Failed or partialy failed
+ _uncommitted.free(start + filled, allocated - filled);
+ return committed;
+ }
+ }
+
+ // Expand backing file
+ if (committed < size) {
+ const size_t remaining = size - committed;
+ const uintptr_t start = _file.size();
+ const size_t expanded = _file.commit(start, remaining);
+ if (expanded > 0) {
+ // Successful or partialy successful
+ _committed.free(start, expanded);
+ committed += expanded;
+ }
+ }
+
+ return committed;
+}
+
+size_t ZPhysicalMemoryBacking::uncommit(size_t size) {
+ size_t uncommitted = 0;
+
+ // Punch holes in backing file
+ while (uncommitted < size) {
+ size_t allocated = 0;
+ const size_t remaining = size - uncommitted;
+ const uintptr_t start = _committed.alloc_from_back_at_most(remaining, &allocated);
+ assert(start != UINTPTR_MAX, "Allocation should never fail");
+
+ // Try punch hole
+ const size_t punched = _file.uncommit(start, allocated);
+ if (punched > 0) {
+ // Successful or partialy successful
+ _uncommitted.free(start, punched);
+ uncommitted += punched;
+ }
+ if (punched < allocated) {
+ // Failed or partialy failed
+ _committed.free(start + punched, allocated - punched);
+ return uncommitted;
+ }
+ }
+
+ return uncommitted;
+}
+
+ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) {
+ assert(is_aligned(size, ZGranuleSize), "Invalid size");
+
+ ZPhysicalMemory pmem;
+
+ // Allocate segments
+ for (size_t allocated = 0; allocated < size; allocated += ZGranuleSize) {
+ const uintptr_t start = _committed.alloc_from_front(ZGranuleSize);
+ assert(start != UINTPTR_MAX, "Allocation should never fail");
+ pmem.add_segment(ZPhysicalMemorySegment(start, ZGranuleSize));
+ }
+
+ return pmem;
+}
+
+void ZPhysicalMemoryBacking::free(const ZPhysicalMemory& pmem) {
+ const size_t nsegments = pmem.nsegments();
+
+ // Free segments
+ for (size_t i = 0; i < nsegments; i++) {
+ const ZPhysicalMemorySegment& segment = pmem.segment(i);
+ _committed.free(segment.start(), segment.size());
+ }
+}
+
+void ZPhysicalMemoryBacking::map_failed(ZErrno err) const {
+ if (err == ENOMEM) {
+ fatal("Failed to map memory. Please check the system limit on number of "
+ "memory mappings allowed per process (see %s)", ZFILENAME_PROC_MAX_MAP_COUNT);
+ } else {
+ fatal("Failed to map memory (%s)", err.to_string());
+ }
+}
+
+void ZPhysicalMemoryBacking::advise_view(uintptr_t addr, size_t size, int advice) const {
+ if (madvise((void*)addr, size, advice) == -1) {
+ ZErrno err;
+ log_error(gc)("Failed to advise on memory (advice %d, %s)", advice, err.to_string());
+ }
+}
+
+void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const {
+ const size_t page_size = ZLargePages::is_explicit() ? os::large_page_size() : os::vm_page_size();
+ os::pretouch_memory((void*)addr, (void*)(addr + size), page_size);
+}
+
+void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const {
+ const size_t nsegments = pmem.nsegments();
+ size_t size = 0;
+
+ // Map segments
+ for (size_t i = 0; i < nsegments; i++) {
+ const ZPhysicalMemorySegment& segment = pmem.segment(i);
+ const uintptr_t segment_addr = addr + size;
+ const void* const res = mmap((void*)segment_addr, segment.size(), PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, _file.fd(), segment.start());
+ if (res == MAP_FAILED) {
+ ZErrno err;
+ map_failed(err);
+ }
+
+ size += segment.size();
+ }
+
+ // Advise on use of transparent huge pages before touching it
+ if (ZLargePages::is_transparent()) {
+ advise_view(addr, size, MADV_HUGEPAGE);
+ }
+
+ // NUMA interleave memory before touching it
+ ZNUMA::memory_interleave(addr, size);
+
+ // Pre-touch memory
+ if (pretouch) {
+ pretouch_view(addr, size);
+ }
+}
+
+void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const {
+ // Note that we must keep the address space reservation intact and just detach
+ // the backing memory. For this reason we map a new anonymous, non-accessible
+ // and non-reserved page over the mapping instead of actually unmapping.
+ const void* const res = mmap((void*)addr, pmem.size(), PROT_NONE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+ if (res == MAP_FAILED) {
+ ZErrno err;
+ map_failed(err);
+ }
+}
+
+uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const {
+ // From an NMT point of view we treat the first heap view (marked0) as committed
+ return ZAddress::marked0(offset);
+}
+
+void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
+ if (ZVerifyViews) {
+ // Map good view
+ map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
+ } else {
+ // Map all views
+ map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
+ map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
+ map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);
+ }
+}
+
+void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
+ if (ZVerifyViews) {
+ // Unmap good view
+ unmap_view(pmem, ZAddress::good(offset));
+ } else {
+ // Unmap all views
+ unmap_view(pmem, ZAddress::marked0(offset));
+ unmap_view(pmem, ZAddress::marked1(offset));
+ unmap_view(pmem, ZAddress::remapped(offset));
+ }
+}
+
+void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
+ // Map good view
+ assert(ZVerifyViews, "Should be enabled");
+ map_view(pmem, ZAddress::good(offset), false /* pretouch */);
+}
+
+void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
+ // Unmap good view
+ assert(ZVerifyViews, "Should be enabled");
+ unmap_view(pmem, ZAddress::good(offset));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, 2019, 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 OS_LINUX_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_HPP
+#define OS_LINUX_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_HPP
+
+#include "gc/z/zBackingFile_linux.hpp"
+#include "gc/z/zMemory.hpp"
+
+class ZErrno;
+class ZPhysicalMemory;
+
+class ZPhysicalMemoryBacking {
+private:
+ ZBackingFile _file;
+ ZMemoryManager _committed;
+ ZMemoryManager _uncommitted;
+
+ void warn_available_space(size_t max) const;
+ void warn_max_map_count(size_t max) const;
+
+ void map_failed(ZErrno err) const;
+
+ void advise_view(uintptr_t addr, size_t size, int advice) const;
+ void pretouch_view(uintptr_t addr, size_t size) const;
+ void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const;
+ void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const;
+
+public:
+ bool is_initialized() const;
+
+ void warn_commit_limits(size_t max) const;
+ bool supports_uncommit();
+
+ size_t commit(size_t size);
+ size_t uncommit(size_t size);
+
+ ZPhysicalMemory alloc(size_t size);
+ void free(const ZPhysicalMemory& pmem);
+
+ uintptr_t nmt_address(uintptr_t offset) const;
+
+ void map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
+ void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
+
+ void debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
+ void debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
+};
+
+#endif // OS_LINUX_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zSyscall_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, 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/z/zSyscall_linux.hpp"
+#include OS_CPU_HEADER(gc/z/zSyscall)
+
+#include <unistd.h>
+
+int ZSyscall::memfd_create(const char *name, unsigned int flags) {
+ return syscall(SYS_memfd_create, name, flags);
+}
+
+int ZSyscall::fallocate(int fd, int mode, size_t offset, size_t length) {
+ return syscall(SYS_fallocate, fd, mode, offset, length);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, 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 OS_LINUX_GC_Z_ZSYSCALL_LINUX_HPP
+#define OS_LINUX_GC_Z_ZSYSCALL_LINUX_HPP
+
+#include "memory/allocation.hpp"
+
+class ZSyscall : public AllStatic {
+public:
+ static int memfd_create(const char *name, unsigned int flags);
+ static int fallocate(int fd, int mode, size_t offset, size_t length);
+};
+
+#endif // OS_LINUX_GC_Z_ZSYSCALL_LINUX_HPP
--- a/src/hotspot/os/linux/osContainer_linux.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/os/linux/osContainer_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -27,6 +27,7 @@
#include <errno.h>
#include "utilities/globalDefinitions.hpp"
#include "memory/allocation.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "logging/log.hpp"
#include "osContainer_linux.hpp"
@@ -673,4 +674,3 @@
return shares;
}
-
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zBackingFile_linux_aarch64.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,590 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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/z/zArray.inline.hpp"
-#include "gc/z/zBackingFile_linux_aarch64.hpp"
-#include "gc/z/zBackingPath_linux_aarch64.hpp"
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLargePages.inline.hpp"
-#include "logging/log.hpp"
-#include "runtime/init.hpp"
-#include "runtime/os.hpp"
-#include "utilities/align.hpp"
-#include "utilities/debug.hpp"
-
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//
-// Support for building on older Linux systems
-//
-
-// System calls
-#ifndef SYS_fallocate
-#define SYS_fallocate 47
-#endif
-#ifndef SYS_memfd_create
-#define SYS_memfd_create 279
-#endif
-
-// memfd_create(2) flags
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-#ifndef MFD_HUGETLB
-#define MFD_HUGETLB 0x0004U
-#endif
-
-// open(2) flags
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 02000000
-#endif
-#ifndef O_TMPFILE
-#define O_TMPFILE (020000000 | O_DIRECTORY)
-#endif
-
-// fallocate(2) flags
-#ifndef FALLOC_FL_KEEP_SIZE
-#define FALLOC_FL_KEEP_SIZE 0x01
-#endif
-#ifndef FALLOC_FL_PUNCH_HOLE
-#define FALLOC_FL_PUNCH_HOLE 0x02
-#endif
-
-// Filesystem types, see statfs(2)
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-
-// Filesystem names
-#define ZFILESYSTEM_TMPFS "tmpfs"
-#define ZFILESYSTEM_HUGETLBFS "hugetlbfs"
-
-// Sysfs file for transparent huge page on tmpfs
-#define ZFILENAME_SHMEM_ENABLED "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
-
-// Java heap filename
-#define ZFILENAME_HEAP "java_heap"
-
-// Preferred tmpfs mount points, ordered by priority
-static const char* z_preferred_tmpfs_mountpoints[] = {
- "/dev/shm",
- "/run/shm",
- NULL
-};
-
-// Preferred hugetlbfs mount points, ordered by priority
-static const char* z_preferred_hugetlbfs_mountpoints[] = {
- "/dev/hugepages",
- "/hugepages",
- NULL
-};
-
-static int z_fallocate_hugetlbfs_attempts = 3;
-static bool z_fallocate_supported = true;
-
-static int z_fallocate(int fd, int mode, size_t offset, size_t length) {
- return syscall(SYS_fallocate, fd, mode, offset, length);
-}
-
-static int z_memfd_create(const char *name, unsigned int flags) {
- return syscall(SYS_memfd_create, name, flags);
-}
-
-ZBackingFile::ZBackingFile() :
- _fd(-1),
- _size(0),
- _filesystem(0),
- _block_size(0),
- _available(0),
- _initialized(false) {
-
- // Create backing file
- _fd = create_fd(ZFILENAME_HEAP);
- if (_fd == -1) {
- return;
- }
-
- // Get filesystem statistics
- struct statfs buf;
- if (fstatfs(_fd, &buf) == -1) {
- ZErrno err;
- log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string());
- return;
- }
-
- _filesystem = buf.f_type;
- _block_size = buf.f_bsize;
- _available = buf.f_bavail * _block_size;
-
- // Make sure we're on a supported filesystem
- if (!is_tmpfs() && !is_hugetlbfs()) {
- log_error(gc)("Backing file must be located on a %s or a %s filesystem",
- ZFILESYSTEM_TMPFS, ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- // Make sure the filesystem type matches requested large page type
- if (ZLargePages::is_transparent() && !is_tmpfs()) {
- log_error(gc)("-XX:+UseTransparentHugePages can only be enable when using a %s filesystem",
- ZFILESYSTEM_TMPFS);
- return;
- }
-
- if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) {
- log_error(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel",
- ZFILESYSTEM_TMPFS);
- return;
- }
-
- if (ZLargePages::is_explicit() && !is_hugetlbfs()) {
- log_error(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled "
- "when using a %s filesystem", ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- if (!ZLargePages::is_explicit() && is_hugetlbfs()) {
- log_error(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem",
- ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- const size_t expected_block_size = is_tmpfs() ? os::vm_page_size() : os::large_page_size();
- if (expected_block_size != _block_size) {
- log_error(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")",
- is_tmpfs() ? ZFILESYSTEM_TMPFS : ZFILESYSTEM_HUGETLBFS, _block_size, expected_block_size);
- return;
- }
-
- // Successfully initialized
- _initialized = true;
-}
-
-int ZBackingFile::create_mem_fd(const char* name) const {
- // Create file name
- char filename[PATH_MAX];
- snprintf(filename, sizeof(filename), "%s%s", name, ZLargePages::is_explicit() ? ".hugetlb" : "");
-
- // Create file
- const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0;
- const int fd = z_memfd_create(filename, MFD_CLOEXEC | extra_flags);
- if (fd == -1) {
- ZErrno err;
- log_debug(gc, init)("Failed to create memfd file (%s)",
- ((ZLargePages::is_explicit() && err == EINVAL) ? "Hugepages not supported" : err.to_string()));
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: /memfd:%s", filename);
-
- return fd;
-}
-
-int ZBackingFile::create_file_fd(const char* name) const {
- const char* const filesystem = ZLargePages::is_explicit()
- ? ZFILESYSTEM_HUGETLBFS
- : ZFILESYSTEM_TMPFS;
- const char** const preferred_mountpoints = ZLargePages::is_explicit()
- ? z_preferred_hugetlbfs_mountpoints
- : z_preferred_tmpfs_mountpoints;
-
- // Find mountpoint
- ZBackingPath path(filesystem, preferred_mountpoints);
- if (path.get() == NULL) {
- log_error(gc)("Use -XX:ZPath to specify the path to a %s filesystem", filesystem);
- return -1;
- }
-
- // Try to create an anonymous file using the O_TMPFILE flag. Note that this
- // flag requires kernel >= 3.11. If this fails we fall back to open/unlink.
- const int fd_anon = os::open(path.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
- if (fd_anon == -1) {
- ZErrno err;
- log_debug(gc, init)("Failed to create anonymous file in %s (%s)", path.get(),
- (err == EINVAL ? "Not supported" : err.to_string()));
- } else {
- // Get inode number for anonymous file
- struct stat stat_buf;
- if (fstat(fd_anon, &stat_buf) == -1) {
- ZErrno err;
- log_error(gc)("Failed to determine inode number for anonymous file (%s)", err.to_string());
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: %s/#" UINT64_FORMAT, path.get(), (uint64_t)stat_buf.st_ino);
-
- return fd_anon;
- }
-
- log_debug(gc, init)("Falling back to open/unlink");
-
- // Create file name
- char filename[PATH_MAX];
- snprintf(filename, sizeof(filename), "%s/%s.%d", path.get(), name, os::current_process_id());
-
- // Create file
- const int fd = os::open(filename, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
- if (fd == -1) {
- ZErrno err;
- log_error(gc)("Failed to create file %s (%s)", filename, err.to_string());
- return -1;
- }
-
- // Unlink file
- if (unlink(filename) == -1) {
- ZErrno err;
- log_error(gc)("Failed to unlink file %s (%s)", filename, err.to_string());
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: %s", filename);
-
- return fd;
-}
-
-int ZBackingFile::create_fd(const char* name) const {
- if (ZPath == NULL) {
- // If the path is not explicitly specified, then we first try to create a memfd file
- // instead of looking for a tmpfd/hugetlbfs mount point. Note that memfd_create() might
- // not be supported at all (requires kernel >= 3.17), or it might not support large
- // pages (requires kernel >= 4.14). If memfd_create() fails, then we try to create a
- // file on an accessible tmpfs or hugetlbfs mount point.
- const int fd = create_mem_fd(name);
- if (fd != -1) {
- return fd;
- }
-
- log_debug(gc, init)("Falling back to searching for an accessible mount point");
- }
-
- return create_file_fd(name);
-}
-
-bool ZBackingFile::is_initialized() const {
- return _initialized;
-}
-
-int ZBackingFile::fd() const {
- return _fd;
-}
-
-size_t ZBackingFile::size() const {
- return _size;
-}
-
-size_t ZBackingFile::available() const {
- return _available;
-}
-
-bool ZBackingFile::is_tmpfs() const {
- return _filesystem == TMPFS_MAGIC;
-}
-
-bool ZBackingFile::is_hugetlbfs() const {
- return _filesystem == HUGETLBFS_MAGIC;
-}
-
-bool ZBackingFile::tmpfs_supports_transparent_huge_pages() const {
- // If the shmem_enabled file exists and is readable then we
- // know the kernel supports transparent huge pages for tmpfs.
- return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_ftruncate(size_t size) const {
- while (ftruncate(_fd, size) == -1) {
- if (errno != EINTR) {
- // Failed
- return errno;
- }
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_mmap(size_t offset, size_t length, bool touch) const {
- // On hugetlbfs, mapping a file segment will fail immediately, without
- // the need to touch the mapped pages first, if there aren't enough huge
- // pages available to back the mapping.
- void* const addr = mmap(0, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, offset);
- if (addr == MAP_FAILED) {
- // Failed
- return errno;
- }
-
- // Once mapped, the huge pages are only reserved. We need to touch them
- // to associate them with the file segment. Note that we can not punch
- // hole in file segments which only have reserved pages.
- if (touch) {
- char* const start = (char*)addr;
- char* const end = start + length;
- os::pretouch_memory(start, end, _block_size);
- }
-
- // Unmap again. From now on, the huge pages that were mapped are allocated
- // to this file. There's no risk in getting SIGBUS when touching them.
- if (munmap(addr, length) == -1) {
- // Failed
- return errno;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_pwrite(size_t offset, size_t length) const {
- uint8_t data = 0;
-
- // Allocate backing memory by writing to each block
- for (size_t pos = offset; pos < offset + length; pos += _block_size) {
- if (pwrite(_fd, &data, sizeof(data), pos) == -1) {
- // Failed
- return errno;
- }
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole_compat(size_t offset, size_t length) {
- // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs
- // since Linux 4.3. When fallocate(2) is not supported we emulate it using
- // ftruncate/pwrite (for tmpfs) or ftruncate/mmap/munmap (for hugetlbfs).
-
- const size_t end = offset + length;
- if (end > _size) {
- // Increase file size
- const ZErrno err = fallocate_compat_ftruncate(end);
- if (err) {
- // Failed
- return err;
- }
- }
-
- // Allocate backing memory
- const ZErrno err = is_hugetlbfs() ? fallocate_compat_mmap(offset, length, false /* touch */)
- : fallocate_compat_pwrite(offset, length);
- if (err) {
- if (end > _size) {
- // Restore file size
- fallocate_compat_ftruncate(_size);
- }
-
- // Failed
- return err;
- }
-
- if (end > _size) {
- // Record new file size
- _size = end;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole_syscall(size_t offset, size_t length) {
- const int mode = 0; // Allocate
- const int res = z_fallocate(_fd, mode, offset, length);
- if (res == -1) {
- // Failed
- return errno;
- }
-
- const size_t end = offset + length;
- if (end > _size) {
- // Record new file size
- _size = end;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole(size_t offset, size_t length) {
- // Using compat mode is more efficient when allocating space on hugetlbfs.
- // Note that allocating huge pages this way will only reserve them, and not
- // associate them with segments of the file. We must guarantee that we at
- // some point touch these segments, otherwise we can not punch hole in them.
- if (z_fallocate_supported && !is_hugetlbfs()) {
- const ZErrno err = fallocate_fill_hole_syscall(offset, length);
- if (!err) {
- // Success
- return 0;
- }
-
- if (err != ENOSYS && err != EOPNOTSUPP) {
- // Failed
- return err;
- }
-
- // Not supported
- log_debug(gc)("Falling back to fallocate() compatibility mode");
- z_fallocate_supported = false;
- }
-
- return fallocate_fill_hole_compat(offset, length);
-}
-
-ZErrno ZBackingFile::fallocate_punch_hole(size_t offset, size_t length) {
- if (is_hugetlbfs()) {
- // We can only punch hole in pages that have been touched. Non-touched
- // pages are only reserved, and not associated with any specific file
- // segment. We don't know which pages have been previously touched, so
- // we always touch them here to guarantee that we can punch hole.
- const ZErrno err = fallocate_compat_mmap(offset, length, true /* touch */);
- if (err) {
- // Failed
- return err;
- }
- }
-
- const int mode = FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE;
- if (z_fallocate(_fd, mode, offset, length) == -1) {
- // Failed
- return errno;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::split_and_fallocate(bool punch_hole, size_t offset, size_t length) {
- // Try first half
- const size_t offset0 = offset;
- const size_t length0 = align_up(length / 2, _block_size);
- const ZErrno err0 = fallocate(punch_hole, offset0, length0);
- if (err0) {
- return err0;
- }
-
- // Try second half
- const size_t offset1 = offset0 + length0;
- const size_t length1 = length - length0;
- const ZErrno err1 = fallocate(punch_hole, offset1, length1);
- if (err1) {
- return err1;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate(bool punch_hole, size_t offset, size_t length) {
- assert(is_aligned(offset, _block_size), "Invalid offset");
- assert(is_aligned(length, _block_size), "Invalid length");
-
- const ZErrno err = punch_hole ? fallocate_punch_hole(offset, length) : fallocate_fill_hole(offset, length);
- if (err == EINTR && length > _block_size) {
- // Calling fallocate(2) with a large length can take a long time to
- // complete. When running profilers, such as VTune, this syscall will
- // be constantly interrupted by signals. Expanding the file in smaller
- // steps avoids this problem.
- return split_and_fallocate(punch_hole, offset, length);
- }
-
- return err;
-}
-
-bool ZBackingFile::commit_inner(size_t offset, size_t length) {
- log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
- offset / M, (offset + length) / M, length / M);
-
-retry:
- const ZErrno err = fallocate(false /* punch_hole */, offset, length);
- if (err) {
- if (err == ENOSPC && !is_init_completed() && is_hugetlbfs() && z_fallocate_hugetlbfs_attempts-- > 0) {
- // If we fail to allocate during initialization, due to lack of space on
- // the hugetlbfs filesystem, then we wait and retry a few times before
- // giving up. Otherwise there is a risk that running JVMs back-to-back
- // will fail, since there is a delay between process termination and the
- // huge pages owned by that process being returned to the huge page pool
- // and made available for new allocations.
- log_debug(gc, init)("Failed to commit memory (%s), retrying", err.to_string());
-
- // Wait and retry in one second, in the hope that huge pages will be
- // available by then.
- sleep(1);
- goto retry;
- }
-
- // Failed
- log_error(gc)("Failed to commit memory (%s)", err.to_string());
- return false;
- }
-
- // Success
- return true;
-}
-
-size_t ZBackingFile::commit(size_t offset, size_t length) {
- // Try to commit the whole region
- if (commit_inner(offset, length)) {
- // Success
- return length;
- }
-
- // Failed, try to commit as much as possible
- size_t start = offset;
- size_t end = offset + length;
-
- for (;;) {
- length = align_down((end - start) / 2, ZGranuleSize);
- if (length < ZGranuleSize) {
- // Done, don't commit more
- return start - offset;
- }
-
- if (commit_inner(start, length)) {
- // Success, try commit more
- start += length;
- } else {
- // Failed, try commit less
- end -= length;
- }
- }
-}
-
-size_t ZBackingFile::uncommit(size_t offset, size_t length) {
- log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
- offset / M, (offset + length) / M, length / M);
-
- const ZErrno err = fallocate(true /* punch_hole */, offset, length);
- if (err) {
- log_error(gc)("Failed to uncommit memory (%s)", err.to_string());
- return 0;
- }
-
- return length;
-}
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zBackingFile_linux_aarch64.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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 OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGFILE_LINUX_AARCH64_HPP
-#define OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGFILE_LINUX_AARCH64_HPP
-
-#include "memory/allocation.hpp"
-
-class ZErrno;
-
-class ZBackingFile {
-private:
- int _fd;
- size_t _size;
- uint64_t _filesystem;
- size_t _block_size;
- size_t _available;
- bool _initialized;
-
- int create_mem_fd(const char* name) const;
- int create_file_fd(const char* name) const;
- int create_fd(const char* name) const;
-
- bool is_tmpfs() const;
- bool is_hugetlbfs() const;
- bool tmpfs_supports_transparent_huge_pages() const;
-
- ZErrno fallocate_compat_ftruncate(size_t size) const;
- ZErrno fallocate_compat_mmap(size_t offset, size_t length, bool reserve_only) const;
- ZErrno fallocate_compat_pwrite(size_t offset, size_t length) const;
- ZErrno fallocate_fill_hole_compat(size_t offset, size_t length);
- ZErrno fallocate_fill_hole_syscall(size_t offset, size_t length);
- ZErrno fallocate_fill_hole(size_t offset, size_t length);
- ZErrno fallocate_punch_hole(size_t offset, size_t length);
- ZErrno split_and_fallocate(bool punch_hole, size_t offset, size_t length);
- ZErrno fallocate(bool punch_hole, size_t offset, size_t length);
-
- bool commit_inner(size_t offset, size_t length);
-
-public:
- ZBackingFile();
-
- bool is_initialized() const;
-
- int fd() const;
- size_t size() const;
- size_t available() const;
-
- size_t commit(size_t offset, size_t length);
- size_t uncommit(size_t offset, size_t length);
-};
-
-#endif // OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGFILE_LINUX_AARCH64_HPP
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zBackingPath_linux_aarch64.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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/z/zArray.inline.hpp"
-#include "zBackingPath_linux_aarch64.hpp"
-#include "gc/z/zErrno.hpp"
-#include "logging/log.hpp"
-
-#include <stdio.h>
-#include <unistd.h>
-
-// Mount information, see proc(5) for more details.
-#define PROC_SELF_MOUNTINFO "/proc/self/mountinfo"
-
-ZBackingPath::ZBackingPath(const char* filesystem, const char** preferred_mountpoints) {
- if (ZPath != NULL) {
- // Use specified path
- _path = strdup(ZPath);
- } else {
- // Find suitable path
- _path = find_mountpoint(filesystem, preferred_mountpoints);
- }
-}
-
-ZBackingPath::~ZBackingPath() {
- free(_path);
- _path = NULL;
-}
-
-char* ZBackingPath::get_mountpoint(const char* line, const char* filesystem) const {
- char* line_mountpoint = NULL;
- char* line_filesystem = NULL;
-
- // Parse line and return a newly allocated string containing the mount point if
- // the line contains a matching filesystem and the mount point is accessible by
- // the current user.
- if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-]- %ms", &line_mountpoint, &line_filesystem) != 2 ||
- strcmp(line_filesystem, filesystem) != 0 ||
- access(line_mountpoint, R_OK|W_OK|X_OK) != 0) {
- // Not a matching or accessible filesystem
- free(line_mountpoint);
- line_mountpoint = NULL;
- }
-
- free(line_filesystem);
-
- return line_mountpoint;
-}
-
-void ZBackingPath::get_mountpoints(const char* filesystem, ZArray<char*>* mountpoints) const {
- FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r");
- if (fd == NULL) {
- ZErrno err;
- log_error(gc)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string());
- return;
- }
-
- char* line = NULL;
- size_t length = 0;
-
- while (getline(&line, &length, fd) != -1) {
- char* const mountpoint = get_mountpoint(line, filesystem);
- if (mountpoint != NULL) {
- mountpoints->add(mountpoint);
- }
- }
-
- free(line);
- fclose(fd);
-}
-
-void ZBackingPath::free_mountpoints(ZArray<char*>* mountpoints) const {
- ZArrayIterator<char*> iter(mountpoints);
- for (char* mountpoint; iter.next(&mountpoint);) {
- free(mountpoint);
- }
- mountpoints->clear();
-}
-
-char* ZBackingPath::find_preferred_mountpoint(const char* filesystem,
- ZArray<char*>* mountpoints,
- const char** preferred_mountpoints) const {
- // Find preferred mount point
- ZArrayIterator<char*> iter1(mountpoints);
- for (char* mountpoint; iter1.next(&mountpoint);) {
- for (const char** preferred = preferred_mountpoints; *preferred != NULL; preferred++) {
- if (!strcmp(mountpoint, *preferred)) {
- // Preferred mount point found
- return strdup(mountpoint);
- }
- }
- }
-
- // Preferred mount point not found
- log_error(gc)("More than one %s filesystem found:", filesystem);
- ZArrayIterator<char*> iter2(mountpoints);
- for (char* mountpoint; iter2.next(&mountpoint);) {
- log_error(gc)(" %s", mountpoint);
- }
-
- return NULL;
-}
-
-char* ZBackingPath::find_mountpoint(const char* filesystem, const char** preferred_mountpoints) const {
- char* path = NULL;
- ZArray<char*> mountpoints;
-
- get_mountpoints(filesystem, &mountpoints);
-
- if (mountpoints.size() == 0) {
- // No mount point found
- log_error(gc)("Failed to find an accessible %s filesystem", filesystem);
- } else if (mountpoints.size() == 1) {
- // One mount point found
- path = strdup(mountpoints.at(0));
- } else {
- // More than one mount point found
- path = find_preferred_mountpoint(filesystem, &mountpoints, preferred_mountpoints);
- }
-
- free_mountpoints(&mountpoints);
-
- return path;
-}
-
-const char* ZBackingPath::get() const {
- return _path;
-}
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zBackingPath_linux_aarch64.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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 OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGPATH_LINUX_AARCH64_HPP
-#define OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGPATH_LINUX_AARCH64_HPP
-
-#include "gc/z/zArray.hpp"
-#include "memory/allocation.hpp"
-
-class ZBackingPath : public StackObj {
-private:
- char* _path;
-
- char* get_mountpoint(const char* line,
- const char* filesystem) const;
- void get_mountpoints(const char* filesystem,
- ZArray<char*>* mountpoints) const;
- void free_mountpoints(ZArray<char*>* mountpoints) const;
- char* find_preferred_mountpoint(const char* filesystem,
- ZArray<char*>* mountpoints,
- const char** preferred_mountpoints) const;
- char* find_mountpoint(const char* filesystem,
- const char** preferred_mountpoints) const;
-
-public:
- ZBackingPath(const char* filesystem, const char** preferred_mountpoints);
- ~ZBackingPath();
-
- const char* get() const;
-};
-
-#endif // OS_CPU_LINUX_AARCH64_GC_Z_ZBACKINGPATH_LINUX_AARCH64_HPP
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zPhysicalMemoryBacking_linux_aarch64.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,333 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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/z/zAddress.inline.hpp"
-#include "gc/z/zBackingFile_linux_aarch64.hpp"
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLargePages.inline.hpp"
-#include "gc/z/zMemory.hpp"
-#include "gc/z/zNUMA.hpp"
-#include "gc/z/zPhysicalMemory.inline.hpp"
-#include "gc/z/zPhysicalMemoryBacking_linux_aarch64.hpp"
-#include "logging/log.hpp"
-#include "runtime/init.hpp"
-#include "runtime/os.hpp"
-#include "utilities/align.hpp"
-#include "utilities/debug.hpp"
-
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-//
-// Support for building on older Linux systems
-//
-
-// madvise(2) flags
-#ifndef MADV_HUGEPAGE
-#define MADV_HUGEPAGE 14
-#endif
-
-// Proc file entry for max map mount
-#define ZFILENAME_PROC_MAX_MAP_COUNT "/proc/sys/vm/max_map_count"
-
-bool ZPhysicalMemoryBacking::is_initialized() const {
- return _file.is_initialized();
-}
-
-void ZPhysicalMemoryBacking::warn_available_space(size_t max) const {
- // Note that the available space on a tmpfs or a hugetlbfs filesystem
- // will be zero if no size limit was specified when it was mounted.
- const size_t available = _file.available();
- if (available == 0) {
- // No size limit set, skip check
- log_info(gc, init)("Available space on backing filesystem: N/A");
- return;
- }
-
- log_info(gc, init)("Available space on backing filesystem: " SIZE_FORMAT "M", available / M);
-
- // Warn if the filesystem doesn't currently have enough space available to hold
- // the max heap size. The max heap size will be capped if we later hit this limit
- // when trying to expand the heap.
- if (available < max) {
- log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
- log_warning(gc)("Not enough space available on the backing filesystem to hold the current max Java heap");
- log_warning(gc)("size (" SIZE_FORMAT "M). Please adjust the size of the backing filesystem accordingly "
- "(available", max / M);
- log_warning(gc)("space is currently " SIZE_FORMAT "M). Continuing execution with the current filesystem "
- "size could", available / M);
- log_warning(gc)("lead to a premature OutOfMemoryError being thrown, due to failure to map memory.");
- }
-}
-
-void ZPhysicalMemoryBacking::warn_max_map_count(size_t max) const {
- const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT;
- FILE* const file = fopen(filename, "r");
- if (file == NULL) {
- // Failed to open file, skip check
- log_debug(gc, init)("Failed to open %s", filename);
- return;
- }
-
- size_t actual_max_map_count = 0;
- const int result = fscanf(file, SIZE_FORMAT, &actual_max_map_count);
- fclose(file);
- if (result != 1) {
- // Failed to read file, skip check
- log_debug(gc, init)("Failed to read %s", filename);
- return;
- }
-
- // The required max map count is impossible to calculate exactly since subsystems
- // other than ZGC are also creating memory mappings, and we have no control over that.
- // However, ZGC tends to create the most mappings and dominate the total count.
- // In the worst cases, ZGC will map each granule three times, i.e. once per heap view.
- // We speculate that we need another 20% to allow for non-ZGC subsystems to map memory.
- const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2;
- if (actual_max_map_count < required_max_map_count) {
- log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
- log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given");
- log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at",
- max / M, filename);
- log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution "
- "with the current", required_max_map_count, actual_max_map_count);
- log_warning(gc)("limit could lead to a fatal error, due to failure to map memory.");
- }
-}
-
-void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
- // Warn if available space is too low
- warn_available_space(max);
-
- // Warn if max map count is too low
- warn_max_map_count(max);
-}
-
-bool ZPhysicalMemoryBacking::supports_uncommit() {
- assert(!is_init_completed(), "Invalid state");
- assert(_file.size() >= ZGranuleSize, "Invalid size");
-
- // Test if uncommit is supported by uncommitting and then re-committing a granule
- return commit(uncommit(ZGranuleSize)) == ZGranuleSize;
-}
-
-size_t ZPhysicalMemoryBacking::commit(size_t size) {
- size_t committed = 0;
-
- // Fill holes in the backing file
- while (committed < size) {
- size_t allocated = 0;
- const size_t remaining = size - committed;
- const uintptr_t start = _uncommitted.alloc_from_front_at_most(remaining, &allocated);
- if (start == UINTPTR_MAX) {
- // No holes to commit
- break;
- }
-
- // Try commit hole
- const size_t filled = _file.commit(start, allocated);
- if (filled > 0) {
- // Successful or partialy successful
- _committed.free(start, filled);
- committed += filled;
- }
- if (filled < allocated) {
- // Failed or partialy failed
- _uncommitted.free(start + filled, allocated - filled);
- return committed;
- }
- }
-
- // Expand backing file
- if (committed < size) {
- const size_t remaining = size - committed;
- const uintptr_t start = _file.size();
- const size_t expanded = _file.commit(start, remaining);
- if (expanded > 0) {
- // Successful or partialy successful
- _committed.free(start, expanded);
- committed += expanded;
- }
- }
-
- return committed;
-}
-
-size_t ZPhysicalMemoryBacking::uncommit(size_t size) {
- size_t uncommitted = 0;
-
- // Punch holes in backing file
- while (uncommitted < size) {
- size_t allocated = 0;
- const size_t remaining = size - uncommitted;
- const uintptr_t start = _committed.alloc_from_back_at_most(remaining, &allocated);
- assert(start != UINTPTR_MAX, "Allocation should never fail");
-
- // Try punch hole
- const size_t punched = _file.uncommit(start, allocated);
- if (punched > 0) {
- // Successful or partialy successful
- _uncommitted.free(start, punched);
- uncommitted += punched;
- }
- if (punched < allocated) {
- // Failed or partialy failed
- _committed.free(start + punched, allocated - punched);
- return uncommitted;
- }
- }
-
- return uncommitted;
-}
-
-ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) {
- assert(is_aligned(size, ZGranuleSize), "Invalid size");
-
- ZPhysicalMemory pmem;
-
- // Allocate segments
- for (size_t allocated = 0; allocated < size; allocated += ZGranuleSize) {
- const uintptr_t start = _committed.alloc_from_front(ZGranuleSize);
- assert(start != UINTPTR_MAX, "Allocation should never fail");
- pmem.add_segment(ZPhysicalMemorySegment(start, ZGranuleSize));
- }
-
- return pmem;
-}
-
-void ZPhysicalMemoryBacking::free(const ZPhysicalMemory& pmem) {
- const size_t nsegments = pmem.nsegments();
-
- // Free segments
- for (size_t i = 0; i < nsegments; i++) {
- const ZPhysicalMemorySegment& segment = pmem.segment(i);
- _committed.free(segment.start(), segment.size());
- }
-}
-
-void ZPhysicalMemoryBacking::map_failed(ZErrno err) const {
- if (err == ENOMEM) {
- fatal("Failed to map memory. Please check the system limit on number of "
- "memory mappings allowed per process (see %s)", ZFILENAME_PROC_MAX_MAP_COUNT);
- } else {
- fatal("Failed to map memory (%s)", err.to_string());
- }
-}
-
-void ZPhysicalMemoryBacking::advise_view(uintptr_t addr, size_t size, int advice) const {
- if (madvise((void*)addr, size, advice) == -1) {
- ZErrno err;
- log_error(gc)("Failed to advise on memory (advice %d, %s)", advice, err.to_string());
- }
-}
-
-void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const {
- const size_t page_size = ZLargePages::is_explicit() ? os::large_page_size() : os::vm_page_size();
- os::pretouch_memory((void*)addr, (void*)(addr + size), page_size);
-}
-
-void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const {
- const size_t nsegments = pmem.nsegments();
- size_t size = 0;
-
- // Map segments
- for (size_t i = 0; i < nsegments; i++) {
- const ZPhysicalMemorySegment& segment = pmem.segment(i);
- const uintptr_t segment_addr = addr + size;
- const void* const res = mmap((void*)segment_addr, segment.size(), PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, _file.fd(), segment.start());
- if (res == MAP_FAILED) {
- ZErrno err;
- map_failed(err);
- }
-
- size += segment.size();
- }
-
- // Advise on use of transparent huge pages before touching it
- if (ZLargePages::is_transparent()) {
- advise_view(addr, size, MADV_HUGEPAGE);
- }
-
- // NUMA interleave memory before touching it
- ZNUMA::memory_interleave(addr, size);
-
- // Pre-touch memory
- if (pretouch) {
- pretouch_view(addr, size);
- }
-}
-
-void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const {
- // Note that we must keep the address space reservation intact and just detach
- // the backing memory. For this reason we map a new anonymous, non-accessible
- // and non-reserved page over the mapping instead of actually unmapping.
- const void* const res = mmap((void*)addr, pmem.size(), PROT_NONE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
- if (res == MAP_FAILED) {
- ZErrno err;
- map_failed(err);
- }
-}
-
-uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const {
- // From an NMT point of view we treat the first heap view (marked0) as committed
- return ZAddress::marked0(offset);
-}
-
-void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- if (ZVerifyViews) {
- // Map good view
- map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
- } else {
- // Map all views
- map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
- map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
- map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);
- }
-}
-
-void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- if (ZVerifyViews) {
- // Unmap good view
- unmap_view(pmem, ZAddress::good(offset));
- } else {
- // Unmap all views
- unmap_view(pmem, ZAddress::marked0(offset));
- unmap_view(pmem, ZAddress::marked1(offset));
- unmap_view(pmem, ZAddress::remapped(offset));
- }
-}
-
-void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- // Map good view
- assert(ZVerifyViews, "Should be enabled");
- map_view(pmem, ZAddress::good(offset), false /* pretouch */);
-}
-
-void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- // Unmap good view
- assert(ZVerifyViews, "Should be enabled");
- unmap_view(pmem, ZAddress::good(offset));
-}
--- a/src/hotspot/os_cpu/linux_aarch64/gc/z/zPhysicalMemoryBacking_linux_aarch64.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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 OS_CPU_LINUX_AARCH64_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_AARCH64_HPP
-#define OS_CPU_LINUX_AARCH64_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_AARCH64_HPP
-
-#include "gc/z/zBackingFile_linux_aarch64.hpp"
-#include "gc/z/zMemory.hpp"
-
-class ZErrno;
-class ZPhysicalMemory;
-
-class ZPhysicalMemoryBacking {
-private:
- ZBackingFile _file;
- ZMemoryManager _committed;
- ZMemoryManager _uncommitted;
-
- void warn_available_space(size_t max) const;
- void warn_max_map_count(size_t max) const;
-
- void map_failed(ZErrno err) const;
-
- void advise_view(uintptr_t addr, size_t size, int advice) const;
- void pretouch_view(uintptr_t addr, size_t size) const;
- void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const;
- void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const;
-
-public:
- bool is_initialized() const;
-
- void warn_commit_limits(size_t max) const;
- bool supports_uncommit();
-
- size_t commit(size_t size);
- size_t uncommit(size_t size);
-
- ZPhysicalMemory alloc(size_t size);
- void free(const ZPhysicalMemory& pmem);
-
- uintptr_t nmt_address(uintptr_t offset) const;
-
- void map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
- void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
-
- void debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
- void debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
-};
-
-#endif // OS_CPU_LINUX_AARCH64_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_AARCH64_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/linux_aarch64/gc/z/zSyscall_linux_aarch64.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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 OS_CPU_LINUX_AARCH64_GC_Z_ZSYSCALL_LINUX_AARCH64_HPP
+#define OS_CPU_LINUX_AARCH64_GC_Z_ZSYSCALL_LINUX_AARCH64_HPP
+
+#include <sys/syscall.h>
+
+//
+// Support for building on older Linux systems
+//
+
+#ifndef SYS_memfd_create
+#define SYS_memfd_create 279
+#endif
+#ifndef SYS_fallocate
+#define SYS_fallocate 47
+#endif
+
+#endif // OS_CPU_LINUX_AARCH64_GC_Z_ZSYSCALL_LINUX_AARCH64_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,590 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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/z/zArray.inline.hpp"
-#include "gc/z/zBackingFile_linux_x86.hpp"
-#include "gc/z/zBackingPath_linux_x86.hpp"
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLargePages.inline.hpp"
-#include "logging/log.hpp"
-#include "runtime/init.hpp"
-#include "runtime/os.hpp"
-#include "utilities/align.hpp"
-#include "utilities/debug.hpp"
-
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//
-// Support for building on older Linux systems
-//
-
-// System calls
-#ifndef SYS_fallocate
-#define SYS_fallocate 285
-#endif
-#ifndef SYS_memfd_create
-#define SYS_memfd_create 319
-#endif
-
-// memfd_create(2) flags
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-#ifndef MFD_HUGETLB
-#define MFD_HUGETLB 0x0004U
-#endif
-
-// open(2) flags
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 02000000
-#endif
-#ifndef O_TMPFILE
-#define O_TMPFILE (020000000 | O_DIRECTORY)
-#endif
-
-// fallocate(2) flags
-#ifndef FALLOC_FL_KEEP_SIZE
-#define FALLOC_FL_KEEP_SIZE 0x01
-#endif
-#ifndef FALLOC_FL_PUNCH_HOLE
-#define FALLOC_FL_PUNCH_HOLE 0x02
-#endif
-
-// Filesystem types, see statfs(2)
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-
-// Filesystem names
-#define ZFILESYSTEM_TMPFS "tmpfs"
-#define ZFILESYSTEM_HUGETLBFS "hugetlbfs"
-
-// Sysfs file for transparent huge page on tmpfs
-#define ZFILENAME_SHMEM_ENABLED "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
-
-// Java heap filename
-#define ZFILENAME_HEAP "java_heap"
-
-// Preferred tmpfs mount points, ordered by priority
-static const char* z_preferred_tmpfs_mountpoints[] = {
- "/dev/shm",
- "/run/shm",
- NULL
-};
-
-// Preferred hugetlbfs mount points, ordered by priority
-static const char* z_preferred_hugetlbfs_mountpoints[] = {
- "/dev/hugepages",
- "/hugepages",
- NULL
-};
-
-static int z_fallocate_hugetlbfs_attempts = 3;
-static bool z_fallocate_supported = true;
-
-static int z_fallocate(int fd, int mode, size_t offset, size_t length) {
- return syscall(SYS_fallocate, fd, mode, offset, length);
-}
-
-static int z_memfd_create(const char *name, unsigned int flags) {
- return syscall(SYS_memfd_create, name, flags);
-}
-
-ZBackingFile::ZBackingFile() :
- _fd(-1),
- _size(0),
- _filesystem(0),
- _block_size(0),
- _available(0),
- _initialized(false) {
-
- // Create backing file
- _fd = create_fd(ZFILENAME_HEAP);
- if (_fd == -1) {
- return;
- }
-
- // Get filesystem statistics
- struct statfs buf;
- if (fstatfs(_fd, &buf) == -1) {
- ZErrno err;
- log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string());
- return;
- }
-
- _filesystem = buf.f_type;
- _block_size = buf.f_bsize;
- _available = buf.f_bavail * _block_size;
-
- // Make sure we're on a supported filesystem
- if (!is_tmpfs() && !is_hugetlbfs()) {
- log_error(gc)("Backing file must be located on a %s or a %s filesystem",
- ZFILESYSTEM_TMPFS, ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- // Make sure the filesystem type matches requested large page type
- if (ZLargePages::is_transparent() && !is_tmpfs()) {
- log_error(gc)("-XX:+UseTransparentHugePages can only be enable when using a %s filesystem",
- ZFILESYSTEM_TMPFS);
- return;
- }
-
- if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) {
- log_error(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel",
- ZFILESYSTEM_TMPFS);
- return;
- }
-
- if (ZLargePages::is_explicit() && !is_hugetlbfs()) {
- log_error(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled "
- "when using a %s filesystem", ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- if (!ZLargePages::is_explicit() && is_hugetlbfs()) {
- log_error(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem",
- ZFILESYSTEM_HUGETLBFS);
- return;
- }
-
- const size_t expected_block_size = is_tmpfs() ? os::vm_page_size() : os::large_page_size();
- if (expected_block_size != _block_size) {
- log_error(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")",
- is_tmpfs() ? ZFILESYSTEM_TMPFS : ZFILESYSTEM_HUGETLBFS, _block_size, expected_block_size);
- return;
- }
-
- // Successfully initialized
- _initialized = true;
-}
-
-int ZBackingFile::create_mem_fd(const char* name) const {
- // Create file name
- char filename[PATH_MAX];
- snprintf(filename, sizeof(filename), "%s%s", name, ZLargePages::is_explicit() ? ".hugetlb" : "");
-
- // Create file
- const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0;
- const int fd = z_memfd_create(filename, MFD_CLOEXEC | extra_flags);
- if (fd == -1) {
- ZErrno err;
- log_debug(gc, init)("Failed to create memfd file (%s)",
- ((ZLargePages::is_explicit() && err == EINVAL) ? "Hugepages not supported" : err.to_string()));
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: /memfd:%s", filename);
-
- return fd;
-}
-
-int ZBackingFile::create_file_fd(const char* name) const {
- const char* const filesystem = ZLargePages::is_explicit()
- ? ZFILESYSTEM_HUGETLBFS
- : ZFILESYSTEM_TMPFS;
- const char** const preferred_mountpoints = ZLargePages::is_explicit()
- ? z_preferred_hugetlbfs_mountpoints
- : z_preferred_tmpfs_mountpoints;
-
- // Find mountpoint
- ZBackingPath path(filesystem, preferred_mountpoints);
- if (path.get() == NULL) {
- log_error(gc)("Use -XX:ZPath to specify the path to a %s filesystem", filesystem);
- return -1;
- }
-
- // Try to create an anonymous file using the O_TMPFILE flag. Note that this
- // flag requires kernel >= 3.11. If this fails we fall back to open/unlink.
- const int fd_anon = os::open(path.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
- if (fd_anon == -1) {
- ZErrno err;
- log_debug(gc, init)("Failed to create anonymous file in %s (%s)", path.get(),
- (err == EINVAL ? "Not supported" : err.to_string()));
- } else {
- // Get inode number for anonymous file
- struct stat stat_buf;
- if (fstat(fd_anon, &stat_buf) == -1) {
- ZErrno err;
- log_error(gc)("Failed to determine inode number for anonymous file (%s)", err.to_string());
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: %s/#" UINT64_FORMAT, path.get(), (uint64_t)stat_buf.st_ino);
-
- return fd_anon;
- }
-
- log_debug(gc, init)("Falling back to open/unlink");
-
- // Create file name
- char filename[PATH_MAX];
- snprintf(filename, sizeof(filename), "%s/%s.%d", path.get(), name, os::current_process_id());
-
- // Create file
- const int fd = os::open(filename, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR);
- if (fd == -1) {
- ZErrno err;
- log_error(gc)("Failed to create file %s (%s)", filename, err.to_string());
- return -1;
- }
-
- // Unlink file
- if (unlink(filename) == -1) {
- ZErrno err;
- log_error(gc)("Failed to unlink file %s (%s)", filename, err.to_string());
- return -1;
- }
-
- log_info(gc, init)("Heap backed by file: %s", filename);
-
- return fd;
-}
-
-int ZBackingFile::create_fd(const char* name) const {
- if (ZPath == NULL) {
- // If the path is not explicitly specified, then we first try to create a memfd file
- // instead of looking for a tmpfd/hugetlbfs mount point. Note that memfd_create() might
- // not be supported at all (requires kernel >= 3.17), or it might not support large
- // pages (requires kernel >= 4.14). If memfd_create() fails, then we try to create a
- // file on an accessible tmpfs or hugetlbfs mount point.
- const int fd = create_mem_fd(name);
- if (fd != -1) {
- return fd;
- }
-
- log_debug(gc, init)("Falling back to searching for an accessible mount point");
- }
-
- return create_file_fd(name);
-}
-
-bool ZBackingFile::is_initialized() const {
- return _initialized;
-}
-
-int ZBackingFile::fd() const {
- return _fd;
-}
-
-size_t ZBackingFile::size() const {
- return _size;
-}
-
-size_t ZBackingFile::available() const {
- return _available;
-}
-
-bool ZBackingFile::is_tmpfs() const {
- return _filesystem == TMPFS_MAGIC;
-}
-
-bool ZBackingFile::is_hugetlbfs() const {
- return _filesystem == HUGETLBFS_MAGIC;
-}
-
-bool ZBackingFile::tmpfs_supports_transparent_huge_pages() const {
- // If the shmem_enabled file exists and is readable then we
- // know the kernel supports transparent huge pages for tmpfs.
- return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_ftruncate(size_t size) const {
- while (ftruncate(_fd, size) == -1) {
- if (errno != EINTR) {
- // Failed
- return errno;
- }
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_mmap(size_t offset, size_t length, bool touch) const {
- // On hugetlbfs, mapping a file segment will fail immediately, without
- // the need to touch the mapped pages first, if there aren't enough huge
- // pages available to back the mapping.
- void* const addr = mmap(0, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, offset);
- if (addr == MAP_FAILED) {
- // Failed
- return errno;
- }
-
- // Once mapped, the huge pages are only reserved. We need to touch them
- // to associate them with the file segment. Note that we can not punch
- // hole in file segments which only have reserved pages.
- if (touch) {
- char* const start = (char*)addr;
- char* const end = start + length;
- os::pretouch_memory(start, end, _block_size);
- }
-
- // Unmap again. From now on, the huge pages that were mapped are allocated
- // to this file. There's no risk in getting SIGBUS when touching them.
- if (munmap(addr, length) == -1) {
- // Failed
- return errno;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_compat_pwrite(size_t offset, size_t length) const {
- uint8_t data = 0;
-
- // Allocate backing memory by writing to each block
- for (size_t pos = offset; pos < offset + length; pos += _block_size) {
- if (pwrite(_fd, &data, sizeof(data), pos) == -1) {
- // Failed
- return errno;
- }
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole_compat(size_t offset, size_t length) {
- // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs
- // since Linux 4.3. When fallocate(2) is not supported we emulate it using
- // ftruncate/pwrite (for tmpfs) or ftruncate/mmap/munmap (for hugetlbfs).
-
- const size_t end = offset + length;
- if (end > _size) {
- // Increase file size
- const ZErrno err = fallocate_compat_ftruncate(end);
- if (err) {
- // Failed
- return err;
- }
- }
-
- // Allocate backing memory
- const ZErrno err = is_hugetlbfs() ? fallocate_compat_mmap(offset, length, false /* touch */)
- : fallocate_compat_pwrite(offset, length);
- if (err) {
- if (end > _size) {
- // Restore file size
- fallocate_compat_ftruncate(_size);
- }
-
- // Failed
- return err;
- }
-
- if (end > _size) {
- // Record new file size
- _size = end;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole_syscall(size_t offset, size_t length) {
- const int mode = 0; // Allocate
- const int res = z_fallocate(_fd, mode, offset, length);
- if (res == -1) {
- // Failed
- return errno;
- }
-
- const size_t end = offset + length;
- if (end > _size) {
- // Record new file size
- _size = end;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate_fill_hole(size_t offset, size_t length) {
- // Using compat mode is more efficient when allocating space on hugetlbfs.
- // Note that allocating huge pages this way will only reserve them, and not
- // associate them with segments of the file. We must guarantee that we at
- // some point touch these segments, otherwise we can not punch hole in them.
- if (z_fallocate_supported && !is_hugetlbfs()) {
- const ZErrno err = fallocate_fill_hole_syscall(offset, length);
- if (!err) {
- // Success
- return 0;
- }
-
- if (err != ENOSYS && err != EOPNOTSUPP) {
- // Failed
- return err;
- }
-
- // Not supported
- log_debug(gc)("Falling back to fallocate() compatibility mode");
- z_fallocate_supported = false;
- }
-
- return fallocate_fill_hole_compat(offset, length);
-}
-
-ZErrno ZBackingFile::fallocate_punch_hole(size_t offset, size_t length) {
- if (is_hugetlbfs()) {
- // We can only punch hole in pages that have been touched. Non-touched
- // pages are only reserved, and not associated with any specific file
- // segment. We don't know which pages have been previously touched, so
- // we always touch them here to guarantee that we can punch hole.
- const ZErrno err = fallocate_compat_mmap(offset, length, true /* touch */);
- if (err) {
- // Failed
- return err;
- }
- }
-
- const int mode = FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE;
- if (z_fallocate(_fd, mode, offset, length) == -1) {
- // Failed
- return errno;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::split_and_fallocate(bool punch_hole, size_t offset, size_t length) {
- // Try first half
- const size_t offset0 = offset;
- const size_t length0 = align_up(length / 2, _block_size);
- const ZErrno err0 = fallocate(punch_hole, offset0, length0);
- if (err0) {
- return err0;
- }
-
- // Try second half
- const size_t offset1 = offset0 + length0;
- const size_t length1 = length - length0;
- const ZErrno err1 = fallocate(punch_hole, offset1, length1);
- if (err1) {
- return err1;
- }
-
- // Success
- return 0;
-}
-
-ZErrno ZBackingFile::fallocate(bool punch_hole, size_t offset, size_t length) {
- assert(is_aligned(offset, _block_size), "Invalid offset");
- assert(is_aligned(length, _block_size), "Invalid length");
-
- const ZErrno err = punch_hole ? fallocate_punch_hole(offset, length) : fallocate_fill_hole(offset, length);
- if (err == EINTR && length > _block_size) {
- // Calling fallocate(2) with a large length can take a long time to
- // complete. When running profilers, such as VTune, this syscall will
- // be constantly interrupted by signals. Expanding the file in smaller
- // steps avoids this problem.
- return split_and_fallocate(punch_hole, offset, length);
- }
-
- return err;
-}
-
-bool ZBackingFile::commit_inner(size_t offset, size_t length) {
- log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
- offset / M, (offset + length) / M, length / M);
-
-retry:
- const ZErrno err = fallocate(false /* punch_hole */, offset, length);
- if (err) {
- if (err == ENOSPC && !is_init_completed() && is_hugetlbfs() && z_fallocate_hugetlbfs_attempts-- > 0) {
- // If we fail to allocate during initialization, due to lack of space on
- // the hugetlbfs filesystem, then we wait and retry a few times before
- // giving up. Otherwise there is a risk that running JVMs back-to-back
- // will fail, since there is a delay between process termination and the
- // huge pages owned by that process being returned to the huge page pool
- // and made available for new allocations.
- log_debug(gc, init)("Failed to commit memory (%s), retrying", err.to_string());
-
- // Wait and retry in one second, in the hope that huge pages will be
- // available by then.
- sleep(1);
- goto retry;
- }
-
- // Failed
- log_error(gc)("Failed to commit memory (%s)", err.to_string());
- return false;
- }
-
- // Success
- return true;
-}
-
-size_t ZBackingFile::commit(size_t offset, size_t length) {
- // Try to commit the whole region
- if (commit_inner(offset, length)) {
- // Success
- return length;
- }
-
- // Failed, try to commit as much as possible
- size_t start = offset;
- size_t end = offset + length;
-
- for (;;) {
- length = align_down((end - start) / 2, ZGranuleSize);
- if (length < ZGranuleSize) {
- // Done, don't commit more
- return start - offset;
- }
-
- if (commit_inner(start, length)) {
- // Success, try commit more
- start += length;
- } else {
- // Failed, try commit less
- end -= length;
- }
- }
-}
-
-size_t ZBackingFile::uncommit(size_t offset, size_t length) {
- log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
- offset / M, (offset + length) / M, length / M);
-
- const ZErrno err = fallocate(true /* punch_hole */, offset, length);
- if (err) {
- log_error(gc)("Failed to uncommit memory (%s)", err.to_string());
- return 0;
- }
-
- return length;
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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 OS_CPU_LINUX_X86_GC_Z_ZBACKINGFILE_LINUX_X86_HPP
-#define OS_CPU_LINUX_X86_GC_Z_ZBACKINGFILE_LINUX_X86_HPP
-
-#include "memory/allocation.hpp"
-
-class ZErrno;
-
-class ZBackingFile {
-private:
- int _fd;
- size_t _size;
- uint64_t _filesystem;
- size_t _block_size;
- size_t _available;
- bool _initialized;
-
- int create_mem_fd(const char* name) const;
- int create_file_fd(const char* name) const;
- int create_fd(const char* name) const;
-
- bool is_tmpfs() const;
- bool is_hugetlbfs() const;
- bool tmpfs_supports_transparent_huge_pages() const;
-
- ZErrno fallocate_compat_ftruncate(size_t size) const;
- ZErrno fallocate_compat_mmap(size_t offset, size_t length, bool reserve_only) const;
- ZErrno fallocate_compat_pwrite(size_t offset, size_t length) const;
- ZErrno fallocate_fill_hole_compat(size_t offset, size_t length);
- ZErrno fallocate_fill_hole_syscall(size_t offset, size_t length);
- ZErrno fallocate_fill_hole(size_t offset, size_t length);
- ZErrno fallocate_punch_hole(size_t offset, size_t length);
- ZErrno split_and_fallocate(bool punch_hole, size_t offset, size_t length);
- ZErrno fallocate(bool punch_hole, size_t offset, size_t length);
-
- bool commit_inner(size_t offset, size_t length);
-
-public:
- ZBackingFile();
-
- bool is_initialized() const;
-
- int fd() const;
- size_t size() const;
- size_t available() const;
-
- size_t commit(size_t offset, size_t length);
- size_t uncommit(size_t offset, size_t length);
-};
-
-#endif // OS_CPU_LINUX_X86_GC_Z_ZBACKINGFILE_LINUX_X86_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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/z/zArray.inline.hpp"
-#include "gc/z/zBackingPath_linux_x86.hpp"
-#include "gc/z/zErrno.hpp"
-#include "logging/log.hpp"
-
-#include <stdio.h>
-#include <unistd.h>
-
-// Mount information, see proc(5) for more details.
-#define PROC_SELF_MOUNTINFO "/proc/self/mountinfo"
-
-ZBackingPath::ZBackingPath(const char* filesystem, const char** preferred_mountpoints) {
- if (ZPath != NULL) {
- // Use specified path
- _path = strdup(ZPath);
- } else {
- // Find suitable path
- _path = find_mountpoint(filesystem, preferred_mountpoints);
- }
-}
-
-ZBackingPath::~ZBackingPath() {
- free(_path);
- _path = NULL;
-}
-
-char* ZBackingPath::get_mountpoint(const char* line, const char* filesystem) const {
- char* line_mountpoint = NULL;
- char* line_filesystem = NULL;
-
- // Parse line and return a newly allocated string containing the mount point if
- // the line contains a matching filesystem and the mount point is accessible by
- // the current user.
- if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-]- %ms", &line_mountpoint, &line_filesystem) != 2 ||
- strcmp(line_filesystem, filesystem) != 0 ||
- access(line_mountpoint, R_OK|W_OK|X_OK) != 0) {
- // Not a matching or accessible filesystem
- free(line_mountpoint);
- line_mountpoint = NULL;
- }
-
- free(line_filesystem);
-
- return line_mountpoint;
-}
-
-void ZBackingPath::get_mountpoints(const char* filesystem, ZArray<char*>* mountpoints) const {
- FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r");
- if (fd == NULL) {
- ZErrno err;
- log_error(gc)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string());
- return;
- }
-
- char* line = NULL;
- size_t length = 0;
-
- while (getline(&line, &length, fd) != -1) {
- char* const mountpoint = get_mountpoint(line, filesystem);
- if (mountpoint != NULL) {
- mountpoints->add(mountpoint);
- }
- }
-
- free(line);
- fclose(fd);
-}
-
-void ZBackingPath::free_mountpoints(ZArray<char*>* mountpoints) const {
- ZArrayIterator<char*> iter(mountpoints);
- for (char* mountpoint; iter.next(&mountpoint);) {
- free(mountpoint);
- }
- mountpoints->clear();
-}
-
-char* ZBackingPath::find_preferred_mountpoint(const char* filesystem,
- ZArray<char*>* mountpoints,
- const char** preferred_mountpoints) const {
- // Find preferred mount point
- ZArrayIterator<char*> iter1(mountpoints);
- for (char* mountpoint; iter1.next(&mountpoint);) {
- for (const char** preferred = preferred_mountpoints; *preferred != NULL; preferred++) {
- if (!strcmp(mountpoint, *preferred)) {
- // Preferred mount point found
- return strdup(mountpoint);
- }
- }
- }
-
- // Preferred mount point not found
- log_error(gc)("More than one %s filesystem found:", filesystem);
- ZArrayIterator<char*> iter2(mountpoints);
- for (char* mountpoint; iter2.next(&mountpoint);) {
- log_error(gc)(" %s", mountpoint);
- }
-
- return NULL;
-}
-
-char* ZBackingPath::find_mountpoint(const char* filesystem, const char** preferred_mountpoints) const {
- char* path = NULL;
- ZArray<char*> mountpoints;
-
- get_mountpoints(filesystem, &mountpoints);
-
- if (mountpoints.size() == 0) {
- // No mount point found
- log_error(gc)("Failed to find an accessible %s filesystem", filesystem);
- } else if (mountpoints.size() == 1) {
- // One mount point found
- path = strdup(mountpoints.at(0));
- } else {
- // More than one mount point found
- path = find_preferred_mountpoint(filesystem, &mountpoints, preferred_mountpoints);
- }
-
- free_mountpoints(&mountpoints);
-
- return path;
-}
-
-const char* ZBackingPath::get() const {
- return _path;
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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 OS_CPU_LINUX_X86_GC_Z_ZBACKINGPATH_LINUX_X86_HPP
-#define OS_CPU_LINUX_X86_GC_Z_ZBACKINGPATH_LINUX_X86_HPP
-
-#include "gc/z/zArray.hpp"
-#include "memory/allocation.hpp"
-
-class ZBackingPath : public StackObj {
-private:
- char* _path;
-
- char* get_mountpoint(const char* line,
- const char* filesystem) const;
- void get_mountpoints(const char* filesystem,
- ZArray<char*>* mountpoints) const;
- void free_mountpoints(ZArray<char*>* mountpoints) const;
- char* find_preferred_mountpoint(const char* filesystem,
- ZArray<char*>* mountpoints,
- const char** preferred_mountpoints) const;
- char* find_mountpoint(const char* filesystem,
- const char** preferred_mountpoints) const;
-
-public:
- ZBackingPath(const char* filesystem, const char** preferred_mountpoints);
- ~ZBackingPath();
-
- const char* get() const;
-};
-
-#endif // OS_CPU_LINUX_X86_GC_Z_ZBACKINGPATH_LINUX_X86_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,333 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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/z/zAddress.inline.hpp"
-#include "gc/z/zBackingFile_linux_x86.hpp"
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLargePages.inline.hpp"
-#include "gc/z/zMemory.hpp"
-#include "gc/z/zNUMA.hpp"
-#include "gc/z/zPhysicalMemory.inline.hpp"
-#include "gc/z/zPhysicalMemoryBacking_linux_x86.hpp"
-#include "logging/log.hpp"
-#include "runtime/init.hpp"
-#include "runtime/os.hpp"
-#include "utilities/align.hpp"
-#include "utilities/debug.hpp"
-
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-//
-// Support for building on older Linux systems
-//
-
-// madvise(2) flags
-#ifndef MADV_HUGEPAGE
-#define MADV_HUGEPAGE 14
-#endif
-
-// Proc file entry for max map mount
-#define ZFILENAME_PROC_MAX_MAP_COUNT "/proc/sys/vm/max_map_count"
-
-bool ZPhysicalMemoryBacking::is_initialized() const {
- return _file.is_initialized();
-}
-
-void ZPhysicalMemoryBacking::warn_available_space(size_t max) const {
- // Note that the available space on a tmpfs or a hugetlbfs filesystem
- // will be zero if no size limit was specified when it was mounted.
- const size_t available = _file.available();
- if (available == 0) {
- // No size limit set, skip check
- log_info(gc, init)("Available space on backing filesystem: N/A");
- return;
- }
-
- log_info(gc, init)("Available space on backing filesystem: " SIZE_FORMAT "M", available / M);
-
- // Warn if the filesystem doesn't currently have enough space available to hold
- // the max heap size. The max heap size will be capped if we later hit this limit
- // when trying to expand the heap.
- if (available < max) {
- log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
- log_warning(gc)("Not enough space available on the backing filesystem to hold the current max Java heap");
- log_warning(gc)("size (" SIZE_FORMAT "M). Please adjust the size of the backing filesystem accordingly "
- "(available", max / M);
- log_warning(gc)("space is currently " SIZE_FORMAT "M). Continuing execution with the current filesystem "
- "size could", available / M);
- log_warning(gc)("lead to a premature OutOfMemoryError being thrown, due to failure to map memory.");
- }
-}
-
-void ZPhysicalMemoryBacking::warn_max_map_count(size_t max) const {
- const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT;
- FILE* const file = fopen(filename, "r");
- if (file == NULL) {
- // Failed to open file, skip check
- log_debug(gc, init)("Failed to open %s", filename);
- return;
- }
-
- size_t actual_max_map_count = 0;
- const int result = fscanf(file, SIZE_FORMAT, &actual_max_map_count);
- fclose(file);
- if (result != 1) {
- // Failed to read file, skip check
- log_debug(gc, init)("Failed to read %s", filename);
- return;
- }
-
- // The required max map count is impossible to calculate exactly since subsystems
- // other than ZGC are also creating memory mappings, and we have no control over that.
- // However, ZGC tends to create the most mappings and dominate the total count.
- // In the worst cases, ZGC will map each granule three times, i.e. once per heap view.
- // We speculate that we need another 20% to allow for non-ZGC subsystems to map memory.
- const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2;
- if (actual_max_map_count < required_max_map_count) {
- log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****");
- log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given");
- log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at",
- max / M, filename);
- log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution "
- "with the current", required_max_map_count, actual_max_map_count);
- log_warning(gc)("limit could lead to a fatal error, due to failure to map memory.");
- }
-}
-
-void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
- // Warn if available space is too low
- warn_available_space(max);
-
- // Warn if max map count is too low
- warn_max_map_count(max);
-}
-
-bool ZPhysicalMemoryBacking::supports_uncommit() {
- assert(!is_init_completed(), "Invalid state");
- assert(_file.size() >= ZGranuleSize, "Invalid size");
-
- // Test if uncommit is supported by uncommitting and then re-committing a granule
- return commit(uncommit(ZGranuleSize)) == ZGranuleSize;
-}
-
-size_t ZPhysicalMemoryBacking::commit(size_t size) {
- size_t committed = 0;
-
- // Fill holes in the backing file
- while (committed < size) {
- size_t allocated = 0;
- const size_t remaining = size - committed;
- const uintptr_t start = _uncommitted.alloc_from_front_at_most(remaining, &allocated);
- if (start == UINTPTR_MAX) {
- // No holes to commit
- break;
- }
-
- // Try commit hole
- const size_t filled = _file.commit(start, allocated);
- if (filled > 0) {
- // Successful or partialy successful
- _committed.free(start, filled);
- committed += filled;
- }
- if (filled < allocated) {
- // Failed or partialy failed
- _uncommitted.free(start + filled, allocated - filled);
- return committed;
- }
- }
-
- // Expand backing file
- if (committed < size) {
- const size_t remaining = size - committed;
- const uintptr_t start = _file.size();
- const size_t expanded = _file.commit(start, remaining);
- if (expanded > 0) {
- // Successful or partialy successful
- _committed.free(start, expanded);
- committed += expanded;
- }
- }
-
- return committed;
-}
-
-size_t ZPhysicalMemoryBacking::uncommit(size_t size) {
- size_t uncommitted = 0;
-
- // Punch holes in backing file
- while (uncommitted < size) {
- size_t allocated = 0;
- const size_t remaining = size - uncommitted;
- const uintptr_t start = _committed.alloc_from_back_at_most(remaining, &allocated);
- assert(start != UINTPTR_MAX, "Allocation should never fail");
-
- // Try punch hole
- const size_t punched = _file.uncommit(start, allocated);
- if (punched > 0) {
- // Successful or partialy successful
- _uncommitted.free(start, punched);
- uncommitted += punched;
- }
- if (punched < allocated) {
- // Failed or partialy failed
- _committed.free(start + punched, allocated - punched);
- return uncommitted;
- }
- }
-
- return uncommitted;
-}
-
-ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) {
- assert(is_aligned(size, ZGranuleSize), "Invalid size");
-
- ZPhysicalMemory pmem;
-
- // Allocate segments
- for (size_t allocated = 0; allocated < size; allocated += ZGranuleSize) {
- const uintptr_t start = _committed.alloc_from_front(ZGranuleSize);
- assert(start != UINTPTR_MAX, "Allocation should never fail");
- pmem.add_segment(ZPhysicalMemorySegment(start, ZGranuleSize));
- }
-
- return pmem;
-}
-
-void ZPhysicalMemoryBacking::free(const ZPhysicalMemory& pmem) {
- const size_t nsegments = pmem.nsegments();
-
- // Free segments
- for (size_t i = 0; i < nsegments; i++) {
- const ZPhysicalMemorySegment& segment = pmem.segment(i);
- _committed.free(segment.start(), segment.size());
- }
-}
-
-void ZPhysicalMemoryBacking::map_failed(ZErrno err) const {
- if (err == ENOMEM) {
- fatal("Failed to map memory. Please check the system limit on number of "
- "memory mappings allowed per process (see %s)", ZFILENAME_PROC_MAX_MAP_COUNT);
- } else {
- fatal("Failed to map memory (%s)", err.to_string());
- }
-}
-
-void ZPhysicalMemoryBacking::advise_view(uintptr_t addr, size_t size, int advice) const {
- if (madvise((void*)addr, size, advice) == -1) {
- ZErrno err;
- log_error(gc)("Failed to advise on memory (advice %d, %s)", advice, err.to_string());
- }
-}
-
-void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const {
- const size_t page_size = ZLargePages::is_explicit() ? os::large_page_size() : os::vm_page_size();
- os::pretouch_memory((void*)addr, (void*)(addr + size), page_size);
-}
-
-void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const {
- const size_t nsegments = pmem.nsegments();
- size_t size = 0;
-
- // Map segments
- for (size_t i = 0; i < nsegments; i++) {
- const ZPhysicalMemorySegment& segment = pmem.segment(i);
- const uintptr_t segment_addr = addr + size;
- const void* const res = mmap((void*)segment_addr, segment.size(), PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, _file.fd(), segment.start());
- if (res == MAP_FAILED) {
- ZErrno err;
- map_failed(err);
- }
-
- size += segment.size();
- }
-
- // Advise on use of transparent huge pages before touching it
- if (ZLargePages::is_transparent()) {
- advise_view(addr, size, MADV_HUGEPAGE);
- }
-
- // NUMA interleave memory before touching it
- ZNUMA::memory_interleave(addr, size);
-
- // Pre-touch memory
- if (pretouch) {
- pretouch_view(addr, size);
- }
-}
-
-void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const {
- // Note that we must keep the address space reservation intact and just detach
- // the backing memory. For this reason we map a new anonymous, non-accessible
- // and non-reserved page over the mapping instead of actually unmapping.
- const void* const res = mmap((void*)addr, pmem.size(), PROT_NONE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
- if (res == MAP_FAILED) {
- ZErrno err;
- map_failed(err);
- }
-}
-
-uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const {
- // From an NMT point of view we treat the first heap view (marked0) as committed
- return ZAddress::marked0(offset);
-}
-
-void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- if (ZVerifyViews) {
- // Map good view
- map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
- } else {
- // Map all views
- map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
- map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
- map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);
- }
-}
-
-void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- if (ZVerifyViews) {
- // Unmap good view
- unmap_view(pmem, ZAddress::good(offset));
- } else {
- // Unmap all views
- unmap_view(pmem, ZAddress::marked0(offset));
- unmap_view(pmem, ZAddress::marked1(offset));
- unmap_view(pmem, ZAddress::remapped(offset));
- }
-}
-
-void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- // Map good view
- assert(ZVerifyViews, "Should be enabled");
- map_view(pmem, ZAddress::good(offset), false /* pretouch */);
-}
-
-void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
- // Unmap good view
- assert(ZVerifyViews, "Should be enabled");
- unmap_view(pmem, ZAddress::good(offset));
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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 OS_CPU_LINUX_X86_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_X86_HPP
-#define OS_CPU_LINUX_X86_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_X86_HPP
-
-#include "gc/z/zBackingFile_linux_x86.hpp"
-#include "gc/z/zMemory.hpp"
-
-class ZErrno;
-class ZPhysicalMemory;
-
-class ZPhysicalMemoryBacking {
-private:
- ZBackingFile _file;
- ZMemoryManager _committed;
- ZMemoryManager _uncommitted;
-
- void warn_available_space(size_t max) const;
- void warn_max_map_count(size_t max) const;
-
- void map_failed(ZErrno err) const;
-
- void advise_view(uintptr_t addr, size_t size, int advice) const;
- void pretouch_view(uintptr_t addr, size_t size) const;
- void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const;
- void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const;
-
-public:
- bool is_initialized() const;
-
- void warn_commit_limits(size_t max) const;
- bool supports_uncommit();
-
- size_t commit(size_t size);
- size_t uncommit(size_t size);
-
- ZPhysicalMemory alloc(size_t size);
- void free(const ZPhysicalMemory& pmem);
-
- uintptr_t nmt_address(uintptr_t offset) const;
-
- void map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
- void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
-
- void debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const;
- void debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
-};
-
-#endif // OS_CPU_LINUX_X86_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zSyscall_linux_x86.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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 OS_CPU_LINUX_X86_GC_Z_ZSYSCALL_LINUX_X86_HPP
+#define OS_CPU_LINUX_X86_GC_Z_ZSYSCALL_LINUX_X86_HPP
+
+#include <sys/syscall.h>
+
+//
+// Support for building on older Linux systems
+//
+
+#ifndef SYS_memfd_create
+#define SYS_memfd_create 319
+#endif
+#ifndef SYS_fallocate
+#define SYS_fallocate 285
+#endif
+
+#endif // OS_CPU_LINUX_X86_GC_Z_ZSYSCALL_LINUX_X86_HPP
--- a/src/hotspot/share/c1/c1_Runtime1.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -705,19 +705,11 @@
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(thread, obj);
- if (UseBiasedLocking) {
- // Retry fast entry if bias is revoked to avoid unnecessary inflation
- ObjectSynchronizer::fast_enter(h_obj, lock->lock(), true, CHECK);
- } else {
- if (UseFastLocking) {
- // When using fast locking, the compiled code has already tried the fast case
- assert(obj == lock->obj(), "must match");
- ObjectSynchronizer::slow_enter(h_obj, lock->lock(), THREAD);
- } else {
- lock->set_obj(obj);
- ObjectSynchronizer::fast_enter(h_obj, lock->lock(), false, THREAD);
- }
+ if (!UseFastLocking) {
+ lock->set_obj(obj);
}
+ assert(obj == lock->obj(), "must match");
+ ObjectSynchronizer::enter(h_obj, lock->lock(), THREAD);
JRT_END
@@ -730,12 +722,7 @@
oop obj = lock->obj();
assert(oopDesc::is_oop(obj), "must be NULL or an object");
- if (UseFastLocking) {
- // When using fast locking, the compiled code has already tried the fast case
- ObjectSynchronizer::slow_exit(obj, lock->lock(), THREAD);
- } else {
- ObjectSynchronizer::fast_exit(obj, lock->lock(), THREAD);
- }
+ ObjectSynchronizer::exit(obj, lock->lock(), THREAD);
JRT_END
// Cf. OptoRuntime::deoptimize_caller_frame
--- a/src/hotspot/share/classfile/classLoader.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/classfile/classLoader.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -69,12 +69,10 @@
#include "runtime/vm_version.hpp"
#include "services/management.hpp"
#include "services/threadService.hpp"
+#include "utilities/classpathStream.hpp"
#include "utilities/events.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_CDS
-#include "classfile/sharedPathsMiscInfo.hpp"
-#endif
// Entry points in zip.dll for loading zip/jar file entries
@@ -146,7 +144,6 @@
ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
ClassPathEntry* ClassLoader::_module_path_entries = NULL;
ClassPathEntry* ClassLoader::_last_module_path_entry = NULL;
-SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
#endif
// helper routines
@@ -168,41 +165,6 @@
return (const char*)version_string;
}
-class ClasspathStream : public StackObj {
- const char* _class_path;
- int _len;
- int _start;
- int _end;
-
-public:
- ClasspathStream(const char* class_path) {
- _class_path = class_path;
- _len = (int)strlen(class_path);
- _start = 0;
- _end = 0;
- }
-
- bool has_next() {
- return _start < _len;
- }
-
- const char* get_next() {
- while (_class_path[_end] != '\0' && _class_path[_end] != os::path_separator()[0]) {
- _end++;
- }
- int path_len = _end - _start;
- char* path = NEW_RESOURCE_ARRAY(char, path_len + 1);
- strncpy(path, &_class_path[_start], path_len);
- path[path_len] = '\0';
-
- while (_class_path[_end] == os::path_separator()[0]) {
- _end++;
- }
- _start = _end;
- return path;
- }
-};
-
bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
size_t str_len = strlen(str);
size_t str_to_find_len = strlen(str_to_find);
@@ -284,13 +246,12 @@
return pkgEntryTable->lookup_only(pkg_symbol);
}
-ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
- char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
- strcpy(copy, dir);
- _dir = copy;
+const char* ClassPathEntry::copy_path(const char* path) {
+ char* copy = NEW_C_HEAP_ARRAY(char, strlen(path)+1, mtClass);
+ strcpy(copy, path);
+ return copy;
}
-
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
// construct full path name
assert((_dir != NULL) && (name != NULL), "sanity");
@@ -330,9 +291,7 @@
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name,
bool is_boot_append, bool from_class_path_attr) : ClassPathEntry() {
_zip = zip;
- char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
- strcpy(copy, zip_name);
- _zip_name = copy;
+ _zip_name = copy_path(zip_name);
_from_class_path_attr = from_class_path_attr;
}
@@ -417,8 +376,7 @@
assert(_singleton == NULL, "VM supports only one jimage");
DEBUG_ONLY(_singleton = this);
size_t len = strlen(name) + 1;
- _name = NEW_C_HEAP_ARRAY(const char, len, mtClass);
- strncpy((char *)_name, name, len);
+ _name = copy_path(name);
}
ClassPathImageEntry::~ClassPathImageEntry() {
@@ -571,30 +529,10 @@
} else {
trace_class_path("bootstrap loader class path=", sys_class_path);
}
-#if INCLUDE_CDS
- if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
- _shared_paths_misc_info->add_boot_classpath(sys_class_path);
- }
-#endif
setup_boot_search_path(sys_class_path);
}
#if INCLUDE_CDS
-int ClassLoader::get_shared_paths_misc_info_size() {
- return _shared_paths_misc_info->get_used_bytes();
-}
-
-void* ClassLoader::get_shared_paths_misc_info() {
- return _shared_paths_misc_info->buffer();
-}
-
-bool ClassLoader::check_shared_paths_misc_info(void *buf, int size, bool is_static) {
- SharedPathsMiscInfo* checker = new SharedPathsMiscInfo((char*)buf, size);
- bool result = checker->check(is_static);
- delete checker;
- return result;
-}
-
void ClassLoader::setup_app_search_path(const char *class_path) {
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
@@ -977,11 +915,6 @@
}
return true;
} else {
-#if INCLUDE_CDS
- if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
- _shared_paths_misc_info->add_nonexist_path(path);
- }
-#endif
return false;
}
}
@@ -1601,12 +1534,6 @@
load_zip_library();
// lookup jimage library entry points
load_jimage_library();
-#if INCLUDE_CDS
- // initialize search path
- if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
- _shared_paths_misc_info = new SharedPathsMiscInfo();
- }
-#endif
setup_bootstrap_search_path();
}
@@ -1614,7 +1541,6 @@
void ClassLoader::initialize_shared_path() {
if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
ClassLoaderExt::setup_search_paths();
- _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}
}
--- a/src/hotspot/share/classfile/classLoader.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/classfile/classLoader.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -47,17 +47,19 @@
class ClassPathEntry : public CHeapObj<mtClass> {
private:
ClassPathEntry* volatile _next;
+protected:
+ const char* copy_path(const char*path);
public:
ClassPathEntry* next() const;
virtual ~ClassPathEntry() {}
void set_next(ClassPathEntry* next);
- virtual bool is_modules_image() const = 0;
- virtual bool is_jar_file() const = 0;
+ virtual bool is_modules_image() const { return false; }
+ virtual bool is_jar_file() const { return false; }
// Is this entry created from the "Class-path" attribute from a JAR Manifest?
- virtual bool from_class_path_attr() const = 0;
+ virtual bool from_class_path_attr() const { return false; }
virtual const char* name() const = 0;
- virtual JImageFile* jimage() const = 0;
- virtual void close_jimage() = 0;
+ virtual JImageFile* jimage() const { return NULL; }
+ virtual void close_jimage() {}
// Constructor
ClassPathEntry() : _next(NULL) {}
// Attempt to locate file_name through this class path entry.
@@ -73,18 +75,14 @@
private:
const char* _dir; // Name of directory
public:
- bool is_modules_image() const { return false; }
- bool is_jar_file() const { return false; }
- bool from_class_path_attr() const { return false; }
const char* name() const { return _dir; }
- JImageFile* jimage() const { return NULL; }
- void close_jimage() {}
- ClassPathDirEntry(const char* dir);
+ ClassPathDirEntry(const char* dir) {
+ _dir = copy_path(dir);
+ }
virtual ~ClassPathDirEntry() {}
ClassFileStream* open_stream(const char* name, TRAPS);
};
-
// Type definitions for zip file and zip file entry
typedef void* jzfile;
typedef struct {
@@ -104,12 +102,9 @@
const char* _zip_name; // Name of zip archive
bool _from_class_path_attr; // From the "Class-path" attribute of a jar file
public:
- bool is_modules_image() const { return false; }
bool is_jar_file() const { return true; }
bool from_class_path_attr() const { return _from_class_path_attr; }
const char* name() const { return _zip_name; }
- JImageFile* jimage() const { return NULL; }
- void close_jimage() {}
ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr);
virtual ~ClassPathZipEntry();
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
@@ -126,8 +121,6 @@
DEBUG_ONLY(static ClassPathImageEntry* _singleton;)
public:
bool is_modules_image() const;
- bool is_jar_file() const { return false; }
- bool from_class_path_attr() const { return false; }
bool is_open() const { return _jimage != NULL; }
const char* name() const { return _name == NULL ? "" : _name; }
JImageFile* jimage() const { return _jimage; }
@@ -156,8 +149,6 @@
void add_to_list(ClassPathEntry* new_entry);
};
-class SharedPathsMiscInfo;
-
class ClassLoader: AllStatic {
public:
enum ClassLoaderType {
@@ -230,8 +221,6 @@
static ClassPathEntry* _last_append_entry;
// Info used by CDS
- CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
-
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;)
CDS_ONLY(static ClassPathEntry* _module_path_entries;)
@@ -416,10 +405,6 @@
}
return num_entries;
}
- static void finalize_shared_paths_misc_info();
- static int get_shared_paths_misc_info_size();
- static void* get_shared_paths_misc_info();
- static bool check_shared_paths_misc_info(void* info, int size, bool is_static);
static void exit_with_path_failure(const char* error, const char* message);
static char* skip_uri_protocol(char* source);
static void record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS);
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -30,7 +30,6 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/modules.hpp"
-#include "classfile/sharedPathsMiscInfo.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.inline.hpp"
@@ -74,7 +73,6 @@
trace_class_path("app loader class path (skipped)=", app_class_path);
} else {
trace_class_path("app loader class path=", app_class_path);
- shared_paths_misc_info()->add_app_classpath(app_class_path);
ClassLoader::setup_app_search_path(app_class_path);
}
}
@@ -212,8 +210,12 @@
char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1);
int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
assert((size_t)n == libname_len, "Unexpected number of characters in string");
- trace_class_path("library = ", libname);
- ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */);
+ if (ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */)) {
+ trace_class_path("library = ", libname);
+ } else {
+ trace_class_path("library (non-existent) = ", libname);
+ FileMapInfo::record_non_existent_class_path_entry(libname);
+ }
}
file_start = file_end;
@@ -222,7 +224,6 @@
}
void ClassLoaderExt::setup_search_paths() {
- shared_paths_misc_info()->record_app_offset();
ClassLoaderExt::setup_app_search_path();
}
@@ -248,12 +249,6 @@
result->set_class_loader_type(classloader_type);
}
-void ClassLoaderExt::finalize_shared_paths_misc_info() {
- if (!_has_app_classes) {
- shared_paths_misc_info()->pop_app();
- }
-}
-
// Load the class of the given name from the location given by path. The path is specified by
// the "source:" in the class list file (see classListParser.cpp), and can be a directory or
// a JAR file.
--- a/src/hotspot/share/classfile/classLoaderExt.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -47,9 +47,6 @@
static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size);
static void setup_app_search_path(); // Only when -Xshare:dump
static void process_module_table(ModuleEntryTable* met, TRAPS);
- static SharedPathsMiscInfo* shared_paths_misc_info() {
- return (SharedPathsMiscInfo*)_shared_paths_misc_info;
- }
// index of first app JAR in shared classpath entry table
static jshort _app_class_paths_start_index;
// index of first modular JAR in shared modulepath entry table
@@ -84,8 +81,6 @@
return read_manifest(entry, manifest_size, false, THREAD);
}
- static void finalize_shared_paths_misc_info();
-
static jshort app_class_paths_start_index() { return _app_class_paths_start_index; }
static jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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 "classfile/classLoader.hpp"
-#include "classfile/sharedPathsMiscInfo.hpp"
-#include "logging/log.hpp"
-#include "logging/logStream.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/filemap.hpp"
-#include "memory/metaspaceShared.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/os.inline.hpp"
-#include "utilities/ostream.hpp"
-
-SharedPathsMiscInfo::SharedPathsMiscInfo() {
- _app_offset = 0;
- _buf_size = INITIAL_BUF_SIZE;
- _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass);
- _allocated = true;
-}
-
-SharedPathsMiscInfo::~SharedPathsMiscInfo() {
- if (_allocated) {
- FREE_C_HEAP_ARRAY(char, _buf_start);
- }
-}
-
-void SharedPathsMiscInfo::add_path(const char* path, int type) {
- log_info(class, path)("type=%s ", type_name(type));
- ClassLoader::trace_class_path("add misc shared path ", path);
- write(path, strlen(path) + 1);
- write_jint(jint(type));
-}
-
-void SharedPathsMiscInfo::ensure_size(size_t needed_bytes) {
- assert(_allocated, "cannot modify buffer during validation.");
- int used = get_used_bytes();
- int target = used + int(needed_bytes);
- if (target > _buf_size) {
- _buf_size = _buf_size * 2 + (int)needed_bytes;
- _buf_start = REALLOC_C_HEAP_ARRAY(char, _buf_start, _buf_size, mtClass);
- _cur_ptr = _buf_start + used;
- _end_ptr = _buf_start + _buf_size;
- }
-}
-
-void SharedPathsMiscInfo::write(const void* ptr, size_t size) {
- ensure_size(size);
- memcpy(_cur_ptr, ptr, size);
- _cur_ptr += size;
-}
-
-bool SharedPathsMiscInfo::read(void* ptr, size_t size) {
- if (_cur_ptr + size <= _end_ptr) {
- memcpy(ptr, _cur_ptr, size);
- _cur_ptr += size;
- return true;
- }
- return false;
-}
-
-bool SharedPathsMiscInfo::fail(const char* msg, const char* name) {
- ClassLoader::trace_class_path(msg, name);
- MetaspaceShared::set_archive_loading_failed();
- return false;
-}
-
-void SharedPathsMiscInfo::print_path(outputStream* out, int type, const char* path) {
- switch (type) {
- case BOOT_PATH:
- out->print("Expecting BOOT path=%s", path);
- break;
- case NON_EXIST:
- out->print("Expecting that %s does not exist", path);
- break;
- case APP_PATH:
- ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
- break;
- default:
- ShouldNotReachHere();
- }
-}
-
-bool SharedPathsMiscInfo::check(bool is_static) {
- // The whole buffer must be 0 terminated so that we can use strlen and strcmp
- // without fear.
- _end_ptr -= sizeof(jint);
- if (_cur_ptr >= _end_ptr) {
- return fail("Truncated archive file header");
- }
- if (*_end_ptr != 0) {
- return fail("Corrupted archive file header");
- }
-
- jshort cur_index = 0;
- FileMapHeader* header = is_static ? FileMapInfo::current_info()->header() :
- FileMapInfo::dynamic_info()->header();
- jshort max_cp_index = header->max_used_path_index();
- jshort module_paths_start_index = header->app_module_paths_start_index();
- while (_cur_ptr < _end_ptr) {
- jint type;
- const char* path = _cur_ptr;
- _cur_ptr += strlen(path) + 1;
-
- if (!read_jint(&type)) {
- return fail("Corrupted archive file header");
- }
- LogTarget(Info, class, path) lt;
- if (lt.is_enabled()) {
- lt.print("type=%s ", type_name(type));
- LogStream ls(lt);
- print_path(&ls, type, path);
- ls.cr();
- }
- // skip checking the class path(s) which was not referenced during CDS dump
- if ((cur_index <= max_cp_index) || (cur_index >= module_paths_start_index)) {
- if (!check(type, path, is_static)) {
- if (!PrintSharedArchiveAndExit) {
- return false;
- }
- } else {
- ClassLoader::trace_class_path("ok");
- }
- } else {
- ClassLoader::trace_class_path("skipped check");
- }
- cur_index++;
- }
-
- return true;
-}
-
-bool SharedPathsMiscInfo::check(jint type, const char* path, bool is_static) {
- assert(UseSharedSpaces, "runtime only");
- switch (type) {
- case BOOT_PATH:
- break;
- case NON_EXIST:
- {
- struct stat st;
- if (os::stat(path, &st) == 0) {
- // The file actually exists
- // But we want it to not exist -> fail
- return fail("File must not exist");
- }
- }
- break;
- case APP_PATH:
- break;
- default:
- return fail("Corrupted archive file header");
- }
-
- return true;
-}
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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_CLASSFILE_SHAREDPATHSMISCINFO_HPP
-#define SHARE_CLASSFILE_SHAREDPATHSMISCINFO_HPP
-
-#include "classfile/classLoader.hpp"
-#include "runtime/os.hpp"
-
-class outputStream;
-// During dumping time, when processing class paths, we build up the dump-time
-// classpath. The JAR files that exist are stored in the list ClassLoader::_first_append_entry.
-// However, we need to store other "misc" information for run-time checking, such as
-//
-// + The values of Arguments::get_sysclasspath() used during dumping.
-//
-// + The class path elements specified during dumping but did not exist --
-// these elements must also be specified at run time, and they also must not
-// exist at run time.
-//
-// These misc items are stored in a linear buffer in SharedPathsMiscInfo.
-// The storage format is stream oriented to minimize its size.
-//
-// When writing the information to the archive file, SharedPathsMiscInfo is stored in
-// the archive file header. At run-time, this information is used only during initialization
-// (accessed using read() instead of mmap()), and is deallocated afterwards to save space.
-//
-// The SharedPathsMiscInfo class is used for both creating the the information (during
-// dumping time) and validation (at run time). Different constructors are used in the
-// two situations. See below.
-
-class SharedPathsMiscInfo : public CHeapObj<mtClass> {
-private:
- int _app_offset;
-protected:
- char* _buf_start;
- char* _cur_ptr;
- char* _end_ptr;
- int _buf_size;
- bool _allocated; // was _buf_start allocated by me?
- void ensure_size(size_t needed_bytes);
- void add_path(const char* path, int type);
-
- void write(const void* ptr, size_t size);
- bool read(void* ptr, size_t size);
-
-protected:
- static bool fail(const char* msg, const char* name = NULL);
- bool check(jint type, const char* path, bool is_static);
-
-public:
- enum {
- INITIAL_BUF_SIZE = 128
- };
- // This constructor is used when creating the misc information (during dump)
- SharedPathsMiscInfo();
- // This constructor is used when validating the misc info (during run time)
- SharedPathsMiscInfo(char *buff, int size) {
- _app_offset = 0;
- _cur_ptr = _buf_start = buff;
- _end_ptr = _buf_start + size;
- _buf_size = size;
- _allocated = false;
- }
- ~SharedPathsMiscInfo();
-
- int get_used_bytes() {
- return _cur_ptr - _buf_start;
- }
- void* buffer() {
- return _buf_start;
- }
-
- // writing --
-
- // The path must not exist at run-time
- void add_nonexist_path(const char* path) {
- add_path(path, NON_EXIST);
- }
-
- // The path must exist, and must contain exactly <num_entries> files/dirs
- void add_boot_classpath(const char* path) {
- add_path(path, BOOT_PATH);
- }
-
- void add_app_classpath(const char* path) {
- add_path(path, APP_PATH);
- }
- void record_app_offset() {
- _app_offset = get_used_bytes();
- }
- void pop_app() {
- _cur_ptr = _buf_start + _app_offset;
- write_jint(0);
- }
-
- int write_jint(jint num) {
- write(&num, sizeof(num));
- return 0;
- }
- void write_time(time_t t) {
- write(&t, sizeof(t));
- }
- void write_long(long l) {
- write(&l, sizeof(l));
- }
-
- bool dump_to_file(int fd) {
- int n = get_used_bytes();
- return (os::write(fd, _buf_start, n) == (size_t)n);
- }
-
- // reading --
-
-private:
- enum {
- BOOT_PATH = 1,
- APP_PATH = 2,
- NON_EXIST = 3
- };
-
- const char* type_name(int type) {
- switch (type) {
- case BOOT_PATH: return "BOOT";
- case APP_PATH: return "APP";
- case NON_EXIST: return "NON_EXIST";
- default: ShouldNotReachHere(); return "?";
- }
- }
-
- void print_path(outputStream* os, int type, const char* path);
-
- bool read_jint(jint *ptr) {
- return read(ptr, sizeof(jint));
- }
- bool read_long(long *ptr) {
- return read(ptr, sizeof(long));
- }
- bool read_time(time_t *ptr) {
- return read(ptr, sizeof(time_t));
- }
-
-public:
- bool check(bool is_static);
-};
-
-#endif // SHARE_CLASSFILE_SHAREDPATHSMISCINFO_HPP
--- a/src/hotspot/share/code/vmreg.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/code/vmreg.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -26,6 +26,7 @@
#define SHARE_CODE_VMREG_HPP
#include "asm/register.hpp"
+#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
--- a/src/hotspot/share/gc/cms/allocationStats.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/cms/allocationStats.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -27,6 +27,7 @@
#include "gc/shared/gcUtil.hpp"
#include "logging/log.hpp"
+#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -26,6 +26,7 @@
#include "gc/epsilon/epsilonMemoryPool.hpp"
#include "gc/epsilon/epsilonThreadLocalData.hpp"
#include "gc/shared/gcArguments.hpp"
+#include "gc/shared/locationPrinter.inline.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
@@ -305,6 +306,10 @@
MetaspaceUtils::print_on(st);
}
+bool EpsilonHeap::print_location(outputStream* st, void* addr) const {
+ return BlockLocationPrinter<EpsilonHeap>::print_location(st, addr);
+}
+
void EpsilonHeap::print_tracing_info() const {
print_heap_info(used());
print_metaspace_info();
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -114,8 +114,8 @@
virtual void unpin_object(JavaThread* thread, oop obj) { }
// No support for block parsing.
- virtual HeapWord* block_start(const void* addr) const { return NULL; }
- virtual bool block_is_obj(const HeapWord* addr) const { return false; }
+ HeapWord* block_start(const void* addr) const { return NULL; }
+ bool block_is_obj(const HeapWord* addr) const { return false; }
// No GC threads
virtual void print_gc_threads_on(outputStream* st) const {}
@@ -138,6 +138,7 @@
virtual void print_on(outputStream* st) const;
virtual void print_tracing_info() const;
+ virtual bool print_location(outputStream* st, void* addr) const;
private:
void print_heap_info(size_t used) const;
--- a/src/hotspot/share/gc/g1/g1Analytics.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Analytics.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/g1Predictions.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
#include "utilities/numberSeq.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1BufferNodeList.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, 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/g1/g1BufferNodeList.hpp"
+#include "utilities/debug.hpp"
+
+G1BufferNodeList::G1BufferNodeList() :
+ _head(NULL), _tail(NULL), _entry_count(0) {}
+
+G1BufferNodeList::G1BufferNodeList(BufferNode* head,
+ BufferNode* tail,
+ size_t entry_count) :
+ _head(head), _tail(tail), _entry_count(entry_count)
+{
+ assert((_head == NULL) == (_tail == NULL), "invariant");
+ assert((_head == NULL) == (_entry_count == 0), "invariant");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1BufferNodeList.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, 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_GC_G1_G1BUFFERNODELIST_HPP
+#define SHARE_GC_G1_G1BUFFERNODELIST_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+class BufferNode;
+
+struct G1BufferNodeList {
+ BufferNode* _head; // First node in list or NULL if empty.
+ BufferNode* _tail; // Last node in list or NULL if empty.
+ size_t _entry_count; // Sum of entries in nodes in list.
+
+ G1BufferNodeList();
+ G1BufferNodeList(BufferNode* head, BufferNode* tail, size_t entry_count);
+};
+
+#endif // SHARE_GC_G1_G1BUFFERNODELIST_HPP
+
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -74,6 +74,7 @@
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/generationSpec.hpp"
#include "gc/shared/isGCActiveMark.hpp"
+#include "gc/shared/locationPrinter.inline.hpp"
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
@@ -2490,6 +2491,10 @@
}
#endif // PRODUCT
+bool G1CollectedHeap::print_location(outputStream* st, void* addr) const {
+ return BlockLocationPrinter<G1CollectedHeap>::print_location(st, addr);
+}
+
G1HeapSummary G1CollectedHeap::create_g1_heap_summary() {
size_t eden_used_bytes = _eden.used_bytes();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -1211,11 +1211,11 @@
// address "addr". We say "blocks" instead of "object" since some heaps
// may not pack objects densely; a chunk may either be an object or a
// non-object.
- virtual HeapWord* block_start(const void* addr) const;
+ HeapWord* block_start(const void* addr) const;
// Requires "addr" to be the start of a block, and returns "TRUE" iff
// the block is an object.
- virtual bool block_is_obj(const HeapWord* addr) const;
+ bool block_is_obj(const HeapWord* addr) const;
// Section on thread-local allocation buffers (TLABs)
// See CollectedHeap for semantics.
@@ -1428,6 +1428,9 @@
void print_cset_rsets() PRODUCT_RETURN;
void print_all_rsets() PRODUCT_RETURN;
+ // Used to print information about locations in the hs_err file.
+ virtual bool print_location(outputStream* st, void* addr) const;
+
size_t pending_card_num();
};
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -107,7 +107,7 @@
}
};
-double G1ConcurrentMarkThread::mmu_sleep_time(G1Policy* g1_policy, bool remark) {
+double G1ConcurrentMarkThread::mmu_delay_end(G1Policy* g1_policy, bool remark) {
// There are 3 reasons to use SuspendibleThreadSetJoiner.
// 1. To avoid concurrency problem.
// - G1MMUTracker::add_pause(), when_sec() and its variation(when_ms() etc..) can be called
@@ -119,18 +119,30 @@
SuspendibleThreadSetJoiner sts_join;
const G1Analytics* analytics = g1_policy->analytics();
- double now = os::elapsedTime();
double prediction_ms = remark ? analytics->predict_remark_time_ms()
: analytics->predict_cleanup_time_ms();
+ double prediction = prediction_ms / MILLIUNITS;
G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
- return mmu_tracker->when_ms(now, prediction_ms);
+ double now = os::elapsedTime();
+ return now + mmu_tracker->when_sec(now, prediction);
}
void G1ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) {
if (g1_policy->use_adaptive_young_list_length()) {
- jlong sleep_time_ms = mmu_sleep_time(g1_policy, remark);
- if (!_cm->has_aborted() && sleep_time_ms > 0) {
- os::sleep(this, sleep_time_ms, false);
+ double delay_end_sec = mmu_delay_end(g1_policy, remark);
+ // Wait for timeout or thread termination request.
+ MonitorLocker ml(CGC_lock, Monitor::_no_safepoint_check_flag);
+ while (!_cm->has_aborted()) {
+ double sleep_time_sec = (delay_end_sec - os::elapsedTime());
+ jlong sleep_time_ms = ceil(sleep_time_sec * MILLIUNITS);
+ if (sleep_time_ms <= 0) {
+ break; // Passed end time.
+ } else if (ml.wait(sleep_time_ms, Monitor::_no_safepoint_check_flag)) {
+ break; // Timeout => reached end time.
+ } else if (should_terminate()) {
+ break; // Wakeup for pending termination request.
+ }
+ // Other (possibly spurious) wakeup. Retry with updated sleep time.
}
}
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -56,7 +56,7 @@
void sleep_before_next_cycle();
// Delay marking to meet MMU.
void delay_to_keep_mmu(G1Policy* g1_policy, bool remark);
- double mmu_sleep_time(G1Policy* g1_policy, bool remark);
+ double mmu_delay_end(G1Policy* g1_policy, bool remark);
void run_service();
void stop_service();
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc/g1/g1BufferNodeList.hpp"
#include "gc/g1/g1CardTableEntryClosure.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
@@ -215,7 +216,7 @@
// must share the monitor.
void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) {
assert(allocator() == src->allocator(), "precondition");
- const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
+ const G1BufferNodeList from = src->take_all_completed_buffers();
if (from._head == NULL) return;
MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
--- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -28,20 +28,6 @@
#include "utilities/debug.hpp"
#include "utilities/macros.hpp"
-// G1RedirtyCardsBufferList
-
-G1RedirtyCardsBufferList::G1RedirtyCardsBufferList() :
- _head(NULL), _tail(NULL), _entry_count(0) {}
-
-G1RedirtyCardsBufferList::G1RedirtyCardsBufferList(BufferNode* head,
- BufferNode* tail,
- size_t entry_count) :
- _head(head), _tail(tail), _entry_count(entry_count)
-{
- assert((_head == NULL) == (_tail == NULL), "invariant");
- assert((_head == NULL) == (_entry_count == 0), "invariant");
-}
-
// G1RedirtyCardsQueueBase::LocalQSet
G1RedirtyCardsQueueBase::LocalQSet::LocalQSet(G1RedirtyCardsQueueSet* shared_qset) :
@@ -67,9 +53,9 @@
}
}
-G1RedirtyCardsBufferList G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() {
- G1RedirtyCardsBufferList result = _buffers;
- _buffers = G1RedirtyCardsBufferList();
+G1BufferNodeList G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() {
+ G1BufferNodeList result = _buffers;
+ _buffers = G1BufferNodeList();
return result;
}
@@ -126,9 +112,9 @@
return _list.top();
}
-G1RedirtyCardsBufferList G1RedirtyCardsQueueSet::take_all_completed_buffers() {
+G1BufferNodeList G1RedirtyCardsQueueSet::take_all_completed_buffers() {
DEBUG_ONLY(_collecting = false;)
- G1RedirtyCardsBufferList result(_list.pop_all(), _tail, _entry_count);
+ G1BufferNodeList result(_list.pop_all(), _tail, _entry_count);
_tail = NULL;
_entry_count = 0;
DEBUG_ONLY(_collecting = true;)
@@ -154,7 +140,7 @@
void G1RedirtyCardsQueueSet::merge_bufferlist(LocalQSet* src) {
assert(_collecting, "precondition");
- const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
+ const G1BufferNodeList from = src->take_all_completed_buffers();
if (from._head != NULL) {
assert(from._tail != NULL, "invariant");
Atomic::add(from._entry_count, &_entry_count);
--- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -25,6 +25,7 @@
#ifndef SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
#define SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
+#include "gc/g1/g1BufferNodeList.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
#include "memory/padded.hpp"
@@ -33,15 +34,6 @@
class G1RedirtyCardsQueue;
class G1RedirtyCardsQueueSet;
-struct G1RedirtyCardsBufferList {
- BufferNode* _head;
- BufferNode* _tail;
- size_t _entry_count;
-
- G1RedirtyCardsBufferList();
- G1RedirtyCardsBufferList(BufferNode* head, BufferNode* tail, size_t entry_count);
-};
-
// Provide G1RedirtyCardsQueue with a thread-local qset. It provides an
// uncontended staging area for completed buffers, to be flushed to the
// shared qset en masse. Using the "base from member" idiom so the local
@@ -52,7 +44,7 @@
class LocalQSet : public PtrQueueSet {
G1RedirtyCardsQueueSet* _shared_qset;
- G1RedirtyCardsBufferList _buffers;
+ G1BufferNodeList _buffers;
public:
LocalQSet(G1RedirtyCardsQueueSet* shared_qset);
@@ -64,7 +56,7 @@
// Transfer all completed buffers to the shared qset.
void flush();
- G1RedirtyCardsBufferList take_all_completed_buffers();
+ G1BufferNodeList take_all_completed_buffers();
};
G1RedirtyCardsQueueBase(G1RedirtyCardsQueueSet* shared_qset) :
@@ -123,7 +115,7 @@
// Processing phase operations.
// precondition: Must not be concurrent with buffer collection.
BufferNode* all_completed_buffers() const;
- G1RedirtyCardsBufferList take_all_completed_buffers();
+ G1BufferNodeList take_all_completed_buffers();
};
#endif // SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
--- a/src/hotspot/share/gc/g1/g1_globals.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1_globals.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -245,9 +245,6 @@
"The target number of mixed GCs after a marking cycle.") \
range(0, max_uintx) \
\
- experimental(bool, G1PretouchAuxiliaryMemory, false, \
- "Pre-touch large auxiliary data structures used by the GC.") \
- \
experimental(bool, G1EagerReclaimHumongousObjects, true, \
"Try to reclaim dead large objects at every young GC.") \
\
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -41,6 +41,7 @@
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcWhen.hpp"
#include "gc/shared/genArguments.hpp"
+#include "gc/shared/locationPrinter.inline.hpp"
#include "gc/shared/scavengableNMethods.hpp"
#include "logging/log.hpp"
#include "memory/metaspaceCounters.hpp"
@@ -584,6 +585,10 @@
return PSHeapSummary(heap_summary, used(), old_summary, old_space, young_summary, eden_space, from_space, to_space);
}
+bool ParallelScavengeHeap::print_location(outputStream* st, void* addr) const {
+ return BlockLocationPrinter<ParallelScavengeHeap>::print_location(st, addr);
+}
+
void ParallelScavengeHeap::print_on(outputStream* st) const {
young_gen()->print_on(st);
old_gen()->print_on(st);
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -228,6 +228,9 @@
PreGenGCValues get_pre_gc_values() const;
void print_heap_change(const PreGenGCValues& pre_gc_values) const;
+ // Used to print information about locations in the hs_err file.
+ virtual bool print_location(outputStream* st, void* addr) const;
+
void verify(VerifyOption option /* ignored */);
// Resize the young generation. The reserved space for the
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -402,28 +402,6 @@
// over live objects.
virtual void safe_object_iterate(ObjectClosure* cl) = 0;
- // NOTE! There is no requirement that a collector implement these
- // functions.
- //
- // A CollectedHeap is divided into a dense sequence of "blocks"; that is,
- // each address in the (reserved) heap is a member of exactly
- // one block. The defining characteristic of a block is that it is
- // possible to find its size, and thus to progress forward to the next
- // block. (Blocks may be of different sizes.) Thus, blocks may
- // represent Java objects, or they might be free blocks in a
- // free-list-based heap (or subheap), as long as the two kinds are
- // distinguishable and the size of each is determinable.
-
- // Returns the address of the start of the "block" that contains the
- // address "addr". We say "blocks" instead of "object" since some heaps
- // may not pack objects densely; a chunk may either be an object or a
- // non-object.
- virtual HeapWord* block_start(const void* addr) const = 0;
-
- // Requires "addr" to be the start of a block, and returns "TRUE" iff
- // the block is an object.
- virtual bool block_is_obj(const HeapWord* addr) const = 0;
-
// Returns the longest time (in ms) that has elapsed since the last
// time that any part of the heap was examined by a garbage collection.
virtual jlong millis_since_last_gc() = 0;
@@ -461,6 +439,9 @@
virtual void print_on_error(outputStream* st) const;
+ // Used to print information about locations in the hs_err file.
+ virtual bool print_location(outputStream* st, void* addr) const = 0;
+
// Print all GC threads (other than the VM thread)
// used by this heap.
virtual void print_gc_threads_on(outputStream* st) const = 0;
--- a/src/hotspot/share/gc/shared/gcOverheadChecker.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "gc/shared/gcCause.hpp"
+#include "runtime/globals.hpp"
class SoftRefPolicy;
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -47,6 +47,7 @@
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/generationSpec.hpp"
+#include "gc/shared/locationPrinter.inline.hpp"
#include "gc/shared/oopStorageParState.inline.hpp"
#include "gc/shared/scavengableNMethods.hpp"
#include "gc/shared/space.hpp"
@@ -1260,6 +1261,10 @@
void GenCollectedHeap::print_gc_threads_on(outputStream* st) const {
}
+bool GenCollectedHeap::print_location(outputStream* st, void* addr) const {
+ return BlockLocationPrinter<GenCollectedHeap>::print_location(st, addr);
+}
+
void GenCollectedHeap::print_tracing_info() const {
if (log_is_enabled(Debug, gc, heap, exit)) {
LogStreamHandle(Debug, gc, heap, exit) lsh;
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -260,13 +260,13 @@
// address "addr". We say "blocks" instead of "object" since some heaps
// may not pack objects densely; a chunk may either be an object or a
// non-object.
- virtual HeapWord* block_start(const void* addr) const;
+ HeapWord* block_start(const void* addr) const;
// Requires "addr" to be the start of a block, and returns "TRUE" iff
// the block is an object. Assumes (and verifies in non-product
// builds) that addr is in the allocated part of the heap and is
// the start of a chunk.
- virtual bool block_is_obj(const HeapWord* addr) const;
+ bool block_is_obj(const HeapWord* addr) const;
// Section on TLAB's.
virtual bool supports_tlab_allocation() const;
@@ -332,6 +332,9 @@
virtual void gc_threads_do(ThreadClosure* tc) const;
virtual void print_tracing_info() const;
+ // Used to print information about locations in the hs_err file.
+ virtual bool print_location(outputStream* st, void* addr) const;
+
void print_heap_change(size_t young_prev_used, size_t old_prev_used) const;
// The functions below are helper functions that a subclass of
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/locationPrinter.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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/collectedHeap.hpp"
+#include "gc/shared/locationPrinter.hpp"
+#include "memory/universe.hpp"
+#include "runtime/os.hpp"
+#include "oops/klass.hpp"
+
+bool LocationPrinter::is_valid_obj(void* obj) {
+ if (!is_object_aligned(obj)) {
+ return false;
+ }
+ if (obj < (void*)os::min_page_size()) {
+ return false;
+ }
+
+ // We need at least the mark and the klass word in the committed region.
+ if (!os::is_readable_range(obj, (HeapWord*)obj + oopDesc::header_size())) {
+ return false;
+ }
+ if (!Universe::heap()->is_in(obj)) {
+ return false;
+ }
+
+ Klass* k = (Klass*)oopDesc::load_klass_raw((oopDesc*)obj);
+ return Klass::is_valid(k);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/locationPrinter.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019, 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_GC_SHARED_LOCATIONPRINTER_HPP
+#define SHARE_GC_SHARED_LOCATIONPRINTER_HPP
+
+#include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class outputStream;
+
+class LocationPrinter : AllStatic {
+ public:
+ static bool is_valid_obj(void* addr);
+};
+
+template <typename CollectedHeapT>
+class BlockLocationPrinter : public LocationPrinter {
+ static oop base_oop_or_null(void* addr);
+
+public:
+ static bool print_location(outputStream* st, void* addr);
+};
+
+
+#endif // SHARE_GC_SHARED_LOCATIONPRINTER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/locationPrinter.inline.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2019, 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_GC_SHARED_LOCATIONPRINTER_INLINE_HPP
+#define SHARE_GC_SHARED_LOCATIONPRINTER_INLINE_HPP
+
+#include "gc/shared/locationPrinter.hpp"
+#include "oops/compressedOops.inline.hpp"
+#include "oops/oopsHierarchy.hpp"
+
+template <typename CollectedHeapT>
+oop BlockLocationPrinter<CollectedHeapT>::base_oop_or_null(void* addr) {
+ if (is_valid_obj(addr)) {
+ // We were just given an oop directly.
+ return oop(addr);
+ }
+
+ // Try to find addr using block_start.
+ HeapWord* p = CollectedHeapT::heap()->block_start(addr);
+ if (p != NULL && CollectedHeapT::heap()->block_is_obj(p)) {
+ if (!is_valid_obj(p)) {
+ return NULL;
+ }
+ return oop(p);
+ }
+
+ return NULL;
+}
+
+template <typename CollectedHeapT>
+bool BlockLocationPrinter<CollectedHeapT>::print_location(outputStream* st, void* addr) {
+ // Check if addr points into Java heap.
+ if (CollectedHeapT::heap()->is_in(addr)) {
+ oop o = base_oop_or_null(addr);
+ if (o != NULL) {
+ if ((void*)o == addr) {
+ st->print(INTPTR_FORMAT " is an oop: ", p2i(addr));
+ } else {
+ st->print(INTPTR_FORMAT " is pointing into object: " , p2i(addr));
+ }
+ o->print_on(st);
+ return true;
+ }
+ } else if (CollectedHeapT::heap()->is_in_reserved(addr)) {
+ st->print_cr(INTPTR_FORMAT " is an unallocated location in the heap", p2i(addr));
+ return true;
+ }
+
+ // Compressed oop needs to be decoded first.
+#ifdef _LP64
+ if (UseCompressedOops && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) {
+ narrowOop narrow_oop = (narrowOop)(uintptr_t)addr;
+ oop o = CompressedOops::decode_raw(narrow_oop);
+
+ if (is_valid_obj((address)o)) {
+ st->print(UINT32_FORMAT " is a compressed pointer to object: ", narrow_oop);
+ o->print_on(st);
+ return true;
+ }
+ }
+#endif
+
+ return false;
+}
+
+#endif // SHARE_GC_SHARED_LOCATIONPRINTER_INLINE_HPP
--- a/src/hotspot/share/gc/shared/weakProcessor.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shared/weakProcessor.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -116,10 +116,10 @@
StorageState* cur_state = _storage_states;
OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
for ( ; !it.is_end(); ++it, ++cur_state) {
- assert((cur_state - _storage_states) < storage_count, "invariant");
+ assert(pointer_delta(cur_state, _storage_states, sizeof(StorageState)) < storage_count, "invariant");
new (cur_state) StorageState(*it, _nworkers);
}
- assert((cur_state - _storage_states) == storage_count, "invariant");
+ assert(pointer_delta(cur_state, _storage_states, sizeof(StorageState)) == storage_count, "invariant");
StringTable::reset_dead_counter();
ResolvedMethodTable::reset_dead_counter();
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -363,7 +363,7 @@
}
}
-void ShenandoahAsserts::assert_locked_or_shenandoah_safepoint(const Mutex* lock, const char* file, int line) {
+void ShenandoahAsserts::assert_locked_or_shenandoah_safepoint(Mutex* lock, const char* file, int line) {
if (ShenandoahSafepoint::is_at_shenandoah_safepoint()) {
return;
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -66,7 +66,7 @@
static void assert_rp_isalive_not_installed(const char *file, int line);
static void assert_rp_isalive_installed(const char *file, int line);
- static void assert_locked_or_shenandoah_safepoint(const Mutex* lock, const char*file, int line);
+ static void assert_locked_or_shenandoah_safepoint(Mutex* lock, const char* file, int line);
#ifdef ASSERT
#define shenandoah_assert_in_heap(interior_loc, obj) \
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -28,6 +28,7 @@
#include "gc/shared/gcArguments.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
+#include "gc/shared/locationPrinter.inline.hpp"
#include "gc/shared/memAllocator.hpp"
#include "gc/shared/plab.hpp"
@@ -1133,6 +1134,10 @@
return sp->block_is_obj(addr);
}
+bool ShenandoahHeap::print_location(outputStream* st, void* addr) const {
+ return BlockLocationPrinter<ShenandoahHeap>::print_location(st, addr);
+}
+
jlong ShenandoahHeap::millis_since_last_gc() {
double v = heuristics()->time_since_last_gc() * 1000;
assert(0 <= v && v <= max_jlong, "value should fit: %f", v);
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -536,6 +536,7 @@
// Used for parsing heap during error printing
HeapWord* block_start(const void* addr) const;
bool block_is_obj(const HeapWord* addr) const;
+ bool print_location(outputStream* st, void* addr) const;
// Used for native heap walkers: heap dumpers, mostly
void object_iterate(ObjectClosure* cl);
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1217,7 +1217,7 @@
}
// Sort out the loads that are between a call ant its catch blocks
-static void process_catch_cleanup_candidate(PhaseIdealLoop* phase, LoadNode* load) {
+static void process_catch_cleanup_candidate(PhaseIdealLoop* phase, LoadNode* load, bool verify) {
bool trace = phase->C->directive()->ZTraceLoadBarriersOption;
Node* ctrl = get_ctrl_normalized(phase, load);
@@ -1228,6 +1228,7 @@
Node* catch_node = ctrl->isa_Proj()->raw_out(0);
if (catch_node->is_Catch()) {
if (catch_node->outcnt() > 1) {
+ assert(!verify, "All loads should already have been moved");
call_catch_cleanup_one(phase, load, ctrl);
} else {
if (trace) tty->print_cr("Call catch cleanup with only one catch: load %i ", load->_idx);
@@ -1245,6 +1246,7 @@
if (mode == LoopOptsZBarrierInsertion) {
// First make sure all loads between call and catch are moved to the catch block
clean_catch_blocks(phase);
+ DEBUG_ONLY(clean_catch_blocks(phase, true /* verify */);)
// Then expand barriers on all loads
insert_load_barriers(phase);
@@ -1398,7 +1400,7 @@
// Sometimes the loads use will be at a place dominated by all catch blocks, then we need
// a load in each catch block, and a Phi at the dominated use.
-void ZBarrierSetC2::clean_catch_blocks(PhaseIdealLoop* phase) const {
+void ZBarrierSetC2::clean_catch_blocks(PhaseIdealLoop* phase, bool verify) const {
Compile *C = phase->C;
uint new_ids = C->unique();
@@ -1425,7 +1427,7 @@
LoadNode* load = n->isa_Load();
// only care about loads that will have a barrier
if (load_require_barrier(load)) {
- process_catch_cleanup_candidate(phase, load);
+ process_catch_cleanup_candidate(phase, load, verify);
}
}
}
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -207,7 +207,7 @@
private:
// Load barrier insertion and expansion internal
void insert_barriers_on_unsafe(PhaseIdealLoop* phase) const;
- void clean_catch_blocks(PhaseIdealLoop* phase) const;
+ void clean_catch_blocks(PhaseIdealLoop* phase, bool verify = false) const;
void insert_load_barriers(PhaseIdealLoop* phase) const;
LoadNode* insert_one_loadbarrier(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl) const;
void insert_one_loadbarrier_inner(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl, VectorSet visited) const;
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -23,6 +23,7 @@
#include "precompiled.hpp"
#include "gc/shared/gcHeapSummary.hpp"
+#include "gc/shared/locationPrinter.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zGlobals.hpp"
@@ -249,14 +250,6 @@
_heap.object_iterate(cl, true /* visit_weaks */);
}
-HeapWord* ZCollectedHeap::block_start(const void* addr) const {
- return (HeapWord*)_heap.block_start((uintptr_t)addr);
-}
-
-bool ZCollectedHeap::block_is_obj(const HeapWord* addr) const {
- return _heap.block_is_obj((uintptr_t)addr);
-}
-
void ZCollectedHeap::register_nmethod(nmethod* nm) {
ZNMethod::register_nmethod(nm);
}
@@ -356,6 +349,16 @@
// Does nothing
}
+bool ZCollectedHeap::print_location(outputStream* st, void* addr) const {
+ if (LocationPrinter::is_valid_obj(addr)) {
+ st->print(INTPTR_FORMAT " is a %s oop: ", p2i(addr),
+ ZAddress::is_good(reinterpret_cast<uintptr_t>(addr)) ? "good" : "bad");
+ cast_to_oop(addr)->print_on(st);
+ return true;
+ }
+ return false;
+}
+
void ZCollectedHeap::verify(VerifyOption option /* ignored */) {
_heap.verify();
}
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -100,9 +100,6 @@
virtual void object_iterate(ObjectClosure* cl);
virtual void safe_object_iterate(ObjectClosure* cl);
- virtual HeapWord* block_start(const void* addr) const;
- virtual bool block_is_obj(const HeapWord* addr) const;
-
virtual void register_nmethod(nmethod* nm);
virtual void unregister_nmethod(nmethod* nm);
virtual void flush_nmethod(nmethod* nm);
@@ -124,6 +121,7 @@
virtual void print_extended_on(outputStream* st) const;
virtual void print_gc_threads_on(outputStream* st) const;
virtual void print_tracing_info() const;
+ virtual bool print_location(outputStream* st, void* addr) const;
virtual void prepare_for_verify();
virtual void verify(VerifyOption option /* ignored */);
--- a/src/hotspot/share/gc/z/zHeap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zHeap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -64,7 +64,7 @@
ZHeap::ZHeap() :
_workers(),
- _object_allocator(_workers.nworkers()),
+ _object_allocator(),
_page_allocator(heap_min_size(), heap_initial_size(), heap_max_size(), heap_max_reserve_size()),
_page_table(),
_forwarding_table(),
@@ -194,16 +194,6 @@
return false;
}
-uintptr_t ZHeap::block_start(uintptr_t addr) const {
- const ZPage* const page = _page_table.get(addr);
- return page->block_start(addr);
-}
-
-bool ZHeap::block_is_obj(uintptr_t addr) const {
- const ZPage* const page = _page_table.get(addr);
- return page->block_is_obj(addr);
-}
-
uint ZHeap::nconcurrent_worker_threads() const {
return _workers.nconcurrent();
}
--- a/src/hotspot/share/gc/z/zHeap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zHeap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -107,10 +107,6 @@
bool is_in(uintptr_t addr) const;
uint32_t hash_oop(oop obj) const;
- // Block
- uintptr_t block_start(uintptr_t addr) const;
- bool block_is_obj(uintptr_t addr) const;
-
// Workers
uint nconcurrent_worker_threads() const;
uint nconcurrent_no_boost_worker_threads() const;
--- a/src/hotspot/share/gc/z/zObjectAllocator.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zObjectAllocator.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -41,8 +41,7 @@
static const ZStatCounter ZCounterUndoObjectAllocationSucceeded("Memory", "Undo Object Allocation Succeeded", ZStatUnitOpsPerSecond);
static const ZStatCounter ZCounterUndoObjectAllocationFailed("Memory", "Undo Object Allocation Failed", ZStatUnitOpsPerSecond);
-ZObjectAllocator::ZObjectAllocator(uint nworkers) :
- _nworkers(nworkers),
+ZObjectAllocator::ZObjectAllocator() :
_used(0),
_undone(0),
_shared_medium_page(NULL),
--- a/src/hotspot/share/gc/z/zObjectAllocator.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zObjectAllocator.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -31,7 +31,6 @@
class ZObjectAllocator {
private:
- const uint _nworkers;
ZPerCPU<size_t> _used;
ZPerCPU<size_t> _undone;
ZContended<ZPage*> _shared_medium_page;
@@ -64,7 +63,7 @@
bool undo_alloc_object(ZPage* page, uintptr_t addr, size_t size);
public:
- ZObjectAllocator(uint nworkers);
+ ZObjectAllocator();
uintptr_t alloc_object(size_t size);
--- a/src/hotspot/share/gc/z/zPage.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zPage.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -90,9 +90,6 @@
bool is_in(uintptr_t addr) const;
- uintptr_t block_start(uintptr_t addr) const;
- bool block_is_obj(uintptr_t addr) const;
-
bool is_marked() const;
bool is_object_live(uintptr_t addr) const;
bool is_object_strongly_live(uintptr_t addr) const;
--- a/src/hotspot/share/gc/z/zPage.inline.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zPage.inline.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -177,18 +177,6 @@
return offset >= start() && offset < top();
}
-inline uintptr_t ZPage::block_start(uintptr_t addr) const {
- if (block_is_obj(addr)) {
- return addr;
- } else {
- return ZAddress::good(top());
- }
-}
-
-inline bool ZPage::block_is_obj(uintptr_t addr) const {
- return ZAddress::offset(addr) < top();
-}
-
inline bool ZPage::is_marked() const {
assert(is_relocatable(), "Invalid page state");
return _livemap.is_marked();
--- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -25,7 +25,7 @@
#define SHARE_GC_Z_ZPHYSICALMEMORY_HPP
#include "memory/allocation.hpp"
-#include OS_CPU_HEADER(gc/z/zPhysicalMemoryBacking)
+#include OS_HEADER(gc/z/zPhysicalMemoryBacking)
class ZPhysicalMemorySegment : public CHeapObj<mtGC> {
private:
--- a/src/hotspot/share/gc/z/zValue.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/gc/z/zValue.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -30,6 +30,7 @@
#include "gc/z/zNUMA.hpp"
#include "gc/z/zThread.hpp"
#include "gc/z/zUtils.hpp"
+#include "runtime/globals.hpp"
#include "utilities/align.hpp"
template <typename S>
--- a/src/hotspot/share/include/cds.h Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/include/cds.h Thu Aug 29 16:11:22 2019 +0530
@@ -36,7 +36,7 @@
#define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions
#define CDS_ARCHIVE_MAGIC 0xf00baba2
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
-#define CURRENT_CDS_ARCHIVE_VERSION 6
+#define CURRENT_CDS_ARCHIVE_VERSION 7
#define INVALID_CDS_ARCHIVE_VERSION -1
struct CDSFileMapRegion {
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -771,12 +771,7 @@
Handle h_obj(thread, elem->obj());
assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
"must be NULL or an object");
- if (UseBiasedLocking) {
- // Retry fast entry if bias is revoked to avoid unnecessary inflation
- ObjectSynchronizer::fast_enter(h_obj, elem->lock(), true, CHECK);
- } else {
- ObjectSynchronizer::slow_enter(h_obj, elem->lock(), CHECK);
- }
+ ObjectSynchronizer::enter(h_obj, elem->lock(), CHECK);
assert(Universe::heap()->is_in_reserved_or_null(elem->obj()),
"must be NULL or an object");
#ifdef ASSERT
@@ -796,7 +791,7 @@
if (elem == NULL || h_obj()->is_unlocked()) {
THROW(vmSymbols::java_lang_IllegalMonitorStateException());
}
- ObjectSynchronizer::slow_exit(h_obj(), elem->lock(), thread);
+ ObjectSynchronizer::exit(h_obj(), elem->lock(), thread);
// Free entry. This must be done here, since a pending exception might be installed on
// exit. If it is not cleared, the exception handling code will try to unlock the monitor again.
elem->set_obj(NULL);
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -205,7 +205,7 @@
JVMCI_THROW_NULL(NullPointerException);
}
const char* cstring = JVMCIENV->as_utf8_string(name);
- JVMFlag* flag = JVMFlag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
+ const JVMFlag* flag = JVMFlag::find_declared_flag(cstring);
if (flag == NULL) {
return c2vm;
}
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -369,7 +369,7 @@
#define COUNT_FLAG(ignore) +1
#ifdef ASSERT
#define CHECK_FLAG(type, name) { \
- JVMFlag* flag = JVMFlag::find_flag(#name, strlen(#name), /*allow_locked*/ true, /* return_flag */ true); \
+ const JVMFlag* flag = JVMFlag::find_declared_flag(#name); \
assert(flag != NULL, "No such flag named " #name); \
assert(flag->is_##type(), "JVMFlag " #name " is not of type " #type); \
}
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -394,17 +394,7 @@
}
Handle h_obj(thread, obj);
assert(oopDesc::is_oop(h_obj()), "must be NULL or an object");
- if (UseBiasedLocking) {
- // Retry fast entry if bias is revoked to avoid unnecessary inflation
- ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
- } else {
- if (JVMCIUseFastLocking) {
- // When using fast locking, the compiled code has already tried the fast case
- ObjectSynchronizer::slow_enter(h_obj, lock, THREAD);
- } else {
- ObjectSynchronizer::fast_enter(h_obj, lock, false, THREAD);
- }
- }
+ ObjectSynchronizer::enter(h_obj, lock, THREAD);
TRACE_jvmci_3("%s: exiting locking slow with obj=" INTPTR_FORMAT, thread->name(), p2i(obj));
JRT_END
@@ -426,12 +416,7 @@
}
#endif
- if (JVMCIUseFastLocking) {
- // When using fast locking, the compiled code has already tried the fast case
- ObjectSynchronizer::slow_exit(obj, lock, THREAD);
- } else {
- ObjectSynchronizer::fast_exit(obj, lock, THREAD);
- }
+ ObjectSynchronizer::exit(obj, lock, THREAD);
IF_TRACE_jvmci_3 {
char type[O_BUFLEN];
obj->klass()->name()->as_C_string(type, O_BUFLEN);
--- a/src/hotspot/share/memory/allocation.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/allocation.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -25,12 +25,12 @@
#ifndef SHARE_MEMORY_ALLOCATION_HPP
#define SHARE_MEMORY_ALLOCATION_HPP
-#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include <new>
+class outputStream;
class Thread;
class AllocFailStrategy {
--- a/src/hotspot/share/memory/allocation.inline.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/allocation.inline.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -26,6 +26,7 @@
#define SHARE_MEMORY_ALLOCATION_INLINE_HPP
#include "runtime/atomic.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
--- a/src/hotspot/share/memory/filemap.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/filemap.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -55,6 +55,7 @@
#include "runtime/vm_version.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
+#include "utilities/classpathStream.hpp"
#include "utilities/defaultStream.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
@@ -240,7 +241,6 @@
// JVM version string ... changes on each build.
get_header_version(_jvm_ident);
- ClassLoaderExt::finalize_shared_paths_misc_info();
_app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
_app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
_num_module_paths = ClassLoader::num_module_path_entries();
@@ -256,6 +256,11 @@
_base_archive_is_default = false;
}
+void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
+ _type = non_existent_entry;
+ set_name(path, THREAD);
+}
+
void SharedClassPathEntry::init(bool is_modules_image,
ClassPathEntry* cpe, TRAPS) {
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
@@ -287,26 +292,35 @@
FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
}
- size_t len = strlen(cpe->name()) + 1;
+ // No need to save the name of the module file, as it will be computed at run time
+ // to allow relocation of the JDK directory.
+ const char* name = is_modules_image ? "" : cpe->name();
+ set_name(name, THREAD);
+}
+
+void SharedClassPathEntry::set_name(const char* name, TRAPS) {
+ size_t len = strlen(name) + 1;
_name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
- strcpy(_name->data(), cpe->name());
+ strcpy(_name->data(), name);
}
-bool SharedClassPathEntry::validate(bool is_class_path) {
+const char* SharedClassPathEntry::name() const {
+ if (UseSharedSpaces && is_modules_image()) {
+ // In order to validate the runtime modules image file size against the archived
+ // size information, we need to obtain the runtime modules image path. The recorded
+ // dump time modules image path in the archive may be different from the runtime path
+ // if the JDK image has beed moved after generating the archive.
+ return ClassLoader::get_jrt_entry()->name();
+ } else {
+ return _name->data();
+ }
+}
+
+bool SharedClassPathEntry::validate(bool is_class_path) const {
assert(UseSharedSpaces, "runtime only");
struct stat st;
- const char* name;
-
- // In order to validate the runtime modules image file size against the archived
- // size information, we need to obtain the runtime modules image path. The recorded
- // dump time modules image path in the archive may be different from the runtime path
- // if the JDK image has beed moved after generating the archive.
- if (is_modules_image()) {
- name = ClassLoader::get_jrt_entry()->name();
- } else {
- name = this->name();
- }
+ const char* name = this->name();
bool ok = true;
log_info(class, path)("checking shared classpath entry: %s", name);
@@ -344,6 +358,19 @@
return ok;
}
+bool SharedClassPathEntry::check_non_existent() const {
+ assert(_type == non_existent_entry, "must be");
+ log_info(class, path)("should be non-existent: %s", name());
+ struct stat st;
+ if (os::stat(name(), &st) != 0) {
+ log_info(class, path)("ok");
+ return true; // file doesn't exist
+ } else {
+ return false;
+ }
+}
+
+
void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) {
it->push(&_name);
it->push(&_manifest);
@@ -358,10 +385,11 @@
void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD) {
size_t entry_size = sizeof(SharedClassPathEntry);
- int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries();
- int num_app_classpath_entries = ClassLoader::num_app_classpath_entries();
- int num_module_path_entries = ClassLoader::num_module_path_entries();
- int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries;
+ int num_entries = 0;
+ num_entries += ClassLoader::num_boot_classpath_entries();
+ num_entries += ClassLoader::num_app_classpath_entries();
+ num_entries += ClassLoader::num_module_path_entries();
+ num_entries += FileMapInfo::num_non_existent_class_paths();
size_t bytes = entry_size * num_entries;
_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
@@ -371,7 +399,7 @@
void FileMapInfo::allocate_shared_path_table() {
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
- Thread* THREAD = Thread::current();
+ EXCEPTION_MARK; // The following calls should never throw, but would exit VM on error.
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
ClassPathEntry* jrt = ClassLoader::get_jrt_entry();
@@ -382,47 +410,37 @@
// 1. boot class path
int i = 0;
- ClassPathEntry* cpe = jrt;
+ i = add_shared_classpaths(i, "boot", jrt, THREAD);
+ i = add_shared_classpaths(i, "app", ClassLoader::app_classpath_entries(), THREAD);
+ i = add_shared_classpaths(i, "module", ClassLoader::module_path_entries(), THREAD);
+
+ for (int x = 0; x < num_non_existent_class_paths(); x++, i++) {
+ const char* path = _non_existent_class_paths->at(x);
+ shared_path(i)->init_as_non_existent(path, THREAD);
+ }
+
+ assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
+}
+
+int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) {
while (cpe != NULL) {
- bool is_jrt = (cpe == jrt);
+ bool is_jrt = (cpe == ClassLoader::get_jrt_entry());
const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
- log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
+ log_info(class, path)("add %s shared path (%s) %s", which, type, cpe->name());
SharedClassPathEntry* ent = shared_path(i);
ent->init(is_jrt, cpe, THREAD);
- if (!is_jrt) { // No need to do the modules image.
- EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
- update_shared_classpath(cpe, ent, THREAD);
+ if (cpe->is_jar_file()) {
+ update_jar_manifest(cpe, ent, THREAD);
}
- cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
- i++;
- }
- assert(i == ClassLoader::num_boot_classpath_entries(),
- "number of boot class path entry mismatch");
-
- // 2. app class path
- ClassPathEntry *acpe = ClassLoader::app_classpath_entries();
- while (acpe != NULL) {
- log_info(class, path)("add app shared path %s", acpe->name());
- SharedClassPathEntry* ent = shared_path(i);
- ent->init(false, acpe, THREAD);
- EXCEPTION_MARK;
- update_shared_classpath(acpe, ent, THREAD);
- acpe = acpe->next();
+ if (is_jrt) {
+ cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
+ } else {
+ cpe = cpe->next();
+ }
i++;
}
- // 3. module path
- ClassPathEntry *mpe = ClassLoader::module_path_entries();
- while (mpe != NULL) {
- log_info(class, path)("add module path %s",mpe->name());
- SharedClassPathEntry* ent = shared_path(i);
- ent->init(false, mpe, THREAD);
- EXCEPTION_MARK;
- update_shared_classpath(mpe, ent, THREAD);
- mpe = mpe->next();
- i++;
- }
- assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
+ return i;
}
void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
@@ -452,6 +470,24 @@
}
}
+void FileMapInfo::record_non_existent_class_path_entry(const char* path) {
+ assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
+ log_info(class, path)("non-existent Class-Path entry %s", path);
+ if (_non_existent_class_paths == NULL) {
+ _non_existent_class_paths = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<const char*>(10, true);
+ }
+ _non_existent_class_paths->append(os::strdup(path));
+}
+
+int FileMapInfo::num_non_existent_class_paths() {
+ assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
+ if (_non_existent_class_paths != NULL) {
+ return _non_existent_class_paths->length();
+ } else {
+ return 0;
+ }
+}
+
class ManifestStream: public ResourceObj {
private:
u1* _buffer_start; // Buffer bottom
@@ -500,29 +536,27 @@
}
};
-void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
+void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
ResourceMark rm(THREAD);
jint manifest_size;
- if (cpe->is_jar_file()) {
- assert(ent->is_jar(), "the shared class path entry is not a JAR file");
- char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
- if (manifest != NULL) {
- ManifestStream* stream = new ManifestStream((u1*)manifest,
- manifest_size);
- if (stream->check_is_signed()) {
- ent->set_is_signed();
- } else {
- // Copy the manifest into the shared archive
- manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
- Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
- manifest_size,
- THREAD);
- char* p = (char*)(buf->data());
- memcpy(p, manifest, manifest_size);
- ent->set_manifest(buf);
- }
+ assert(cpe->is_jar_file() && ent->is_jar(), "the shared class path entry is not a JAR file");
+ char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
+ if (manifest != NULL) {
+ ManifestStream* stream = new ManifestStream((u1*)manifest,
+ manifest_size);
+ if (stream->check_is_signed()) {
+ ent->set_is_signed();
+ } else {
+ // Copy the manifest into the shared archive
+ manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
+ Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
+ manifest_size,
+ THREAD);
+ char* p = (char*)(buf->data());
+ memcpy(p, manifest, manifest_size);
+ ent->set_manifest(buf);
}
}
}
@@ -566,32 +600,16 @@
return npaths;
}
-GrowableArray<char*>* FileMapInfo::create_path_array(const char* path) {
- GrowableArray<char*>* path_array = new(ResourceObj::RESOURCE_AREA, mtInternal)
- GrowableArray<char*>(10);
- char* begin_ptr = (char*)path;
- char* end_ptr = strchr((char*)path, os::path_separator()[0]);
- if (end_ptr == NULL) {
- end_ptr = strchr((char*)path, '\0');
- }
- while (end_ptr != NULL) {
- if ((end_ptr - begin_ptr) > 1) {
- struct stat st;
- char* temp_name = NEW_RESOURCE_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1));
- strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
- temp_name[end_ptr - begin_ptr] = '\0';
- if (os::stat(temp_name, &st) == 0) {
- path_array->append(temp_name);
- }
- }
- if (end_ptr < (path + strlen(path))) {
- begin_ptr = ++end_ptr;
- end_ptr = strchr(begin_ptr, os::path_separator()[0]);
- if (end_ptr == NULL) {
- end_ptr = strchr(begin_ptr, '\0');
- }
- } else {
- break;
+GrowableArray<const char*>* FileMapInfo::create_path_array(const char* paths) {
+ GrowableArray<const char*>* path_array = new(ResourceObj::RESOURCE_AREA, mtInternal)
+ GrowableArray<const char*>(10);
+
+ ClasspathStream cp_stream(paths);
+ while (cp_stream.has_next()) {
+ const char* path = cp_stream.get_next();
+ struct stat st;
+ if (os::stat(path, &st) == 0) {
+ path_array->append(path);
}
}
return path_array;
@@ -603,7 +621,7 @@
return false;
}
-bool FileMapInfo::check_paths(int shared_path_start_idx, int num_paths, GrowableArray<char*>* rp_array) {
+bool FileMapInfo::check_paths(int shared_path_start_idx, int num_paths, GrowableArray<const char*>* rp_array) {
int i = 0;
int j = shared_path_start_idx;
bool mismatch = false;
@@ -657,7 +675,7 @@
} else if (dp_len > 0 && rp != NULL) {
int num;
ResourceMark rm;
- GrowableArray<char*>* rp_array = create_path_array(rp);
+ GrowableArray<const char*>* rp_array = create_path_array(rp);
int rp_len = rp_array->length();
if (rp_len >= dp_len) {
if (relaxed_check) {
@@ -690,11 +708,21 @@
if (shared_app_paths_len != 0 && rp_len != 0) {
// Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
ResourceMark rm;
- GrowableArray<char*>* rp_array = create_path_array(appcp);
+ GrowableArray<const char*>* rp_array = create_path_array(appcp);
if (rp_array->length() == 0) {
// None of the jar file specified in the runtime -cp exists.
return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
}
+
+ // Handling of non-existent entries in the classpath: we eliminate all the non-existent
+ // entries from both the dump time classpath (ClassLoader::update_class_path_entry_list)
+ // and the runtime classpath (FileMapInfo::create_path_array), and check the remaining
+ // entries. E.g.:
+ //
+ // dump : -cp a.jar:NE1:NE2:b.jar -> a.jar:b.jar -> recorded in archive.
+ // run 1: -cp NE3:a.jar:NE4:b.jar -> a.jar:b.jar -> matched
+ // run 2: -cp x.jar:NE4:b.jar -> x.jar:b.jar -> mismatched
+
int j = _header->_app_class_paths_start_index;
mismatch = check_paths(j, shared_app_paths_len, rp_array);
if (mismatch) {
@@ -704,6 +732,20 @@
return true;
}
+void FileMapInfo::log_paths(const char* msg, int start_idx, int end_idx) {
+ LogTarget(Info, class, path) lt;
+ if (lt.is_enabled()) {
+ LogStream ls(lt);
+ ls.print("%s", msg);
+ const char* prefix = "";
+ for (int i = start_idx; i < end_idx; i++) {
+ ls.print("%s%s", prefix, shared_path(i)->name());
+ prefix = os::path_separator();
+ }
+ ls.cr();
+ }
+}
+
bool FileMapInfo::validate_shared_path_table() {
assert(UseSharedSpaces, "runtime only");
@@ -732,6 +774,9 @@
}
}
+ log_paths("Expecting BOOT path=", 0, _header->_app_class_paths_start_index);
+ log_paths("Expecting -Djava.class.path=", _header->_app_class_paths_start_index, _header->_app_module_paths_start_index);
+
int module_paths_start_index = _header->_app_module_paths_start_index;
int shared_app_paths_len = 0;
@@ -772,6 +817,8 @@
}
}
+ validate_non_existent_class_paths();
+
_validating_shared_path_table = false;
#if INCLUDE_JVMTI
@@ -786,6 +833,26 @@
return true;
}
+void FileMapInfo::validate_non_existent_class_paths() {
+ // All of the recorded non-existent paths came from the Class-Path: attribute from the JAR
+ // files on the app classpath. If any of these are found to exist during runtime,
+ // it will change how classes are loading for the app loader. For safety, disable
+ // loading of archived platform/app classes (currently there's no way to disable just the
+ // app classes).
+
+ assert(UseSharedSpaces, "runtime only");
+ for (int i = _header->_app_module_paths_start_index + _header->_num_module_paths;
+ i < get_number_of_shared_paths();
+ i++) {
+ SharedClassPathEntry* ent = shared_path(i);
+ if (!ent->check_non_existent()) {
+ warning("Archived non-system classes are disabled because the "
+ "file %s exists", ent->name());
+ _header->_has_platform_or_app_classes = false;
+ }
+ }
+}
+
bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
if (fd < 0) {
@@ -855,9 +922,6 @@
if (dynamic_header->_base_archive_is_default) {
*base_archive_name = Arguments::get_default_shared_archive_path();
} else {
- // skip over the _paths_misc_info
- sz = dynamic_header->_paths_misc_info_size;
- lseek(fd, (long)sz, SEEK_CUR);
// read the base archive name
size_t name_size = dynamic_header->_base_archive_name_size;
if (name_size == 0) {
@@ -948,18 +1012,7 @@
}
}
- _file_offset = n;
-
- size_t info_size = _header->_paths_misc_info_size;
- _paths_misc_info = NEW_C_HEAP_ARRAY(char, info_size, mtClass);
- n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
- if (n != info_size) {
- fail_continue("Unable to read the shared path info header.");
- FREE_C_HEAP_ARRAY(char, _paths_misc_info);
- _paths_misc_info = NULL;
- return false;
- }
- _file_offset += n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
+ _file_offset = n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
if (is_static) {
// just checking the last region is sufficient since the archive is written
@@ -1041,10 +1094,6 @@
// Write the header to the file, seek to the next allocation boundary.
void FileMapInfo::write_header() {
- int info_size = ClassLoader::get_shared_paths_misc_info_size();
-
- _header->_paths_misc_info_size = info_size;
-
char* base_archive_name = NULL;
if (_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC) {
base_archive_name = (char*)Arguments::GetSharedArchivePath();
@@ -1054,7 +1103,6 @@
assert(is_file_position_aligned(), "must be");
write_bytes(_header, _header->_header_size);
- write_bytes(ClassLoader::get_shared_paths_misc_info(), (size_t)info_size);
if (base_archive_name != NULL) {
write_bytes(base_archive_name, (size_t)_header->_base_archive_name_size);
}
@@ -1743,6 +1791,7 @@
SharedPathTable FileMapInfo::_shared_path_table;
bool FileMapInfo::_validating_shared_path_table = false;
bool FileMapInfo::_memory_mapping_failed = false;
+GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL;
// Open the shared archive file, read and validate the header
// information (version, boot classpath, etc.). If initialization
@@ -1751,7 +1800,7 @@
//
// Validation of the archive is done in two steps:
//
-// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
+// [1] validate_header() - done here.
// [2] validate_shared_path_table - this is done later, because the table is in the RW
// region of the archive, which is not mapped yet.
bool FileMapInfo::initialize(bool is_static) {
@@ -1855,22 +1904,7 @@
}
bool FileMapInfo::validate_header(bool is_static) {
- bool status = _header->validate();
-
- if (status) {
- if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size, is_static)) {
- if (!PrintSharedArchiveAndExit) {
- fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
- status = false;
- }
- }
- }
-
- if (_paths_misc_info != NULL) {
- FREE_C_HEAP_ARRAY(char, _paths_misc_info);
- _paths_misc_info = NULL;
- }
- return status;
+ return _header->validate();
}
// Check if a given address is within one of the shared regions
@@ -1922,7 +1956,7 @@
ClassPathEntry* ent = _classpath_entries_for_jvmti[i];
if (ent == NULL) {
if (i == 0) {
- ent = ClassLoader:: get_jrt_entry();
+ ent = ClassLoader::get_jrt_entry();
assert(ent != NULL, "must be");
} else {
SharedClassPathEntry* scpe = shared_path(i);
--- a/src/hotspot/share/memory/filemap.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/filemap.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -49,8 +49,12 @@
jar_entry,
signed_jar_entry,
dir_entry,
+ non_existent_entry,
unknown_entry
};
+
+ void set_name(const char* name, TRAPS);
+
protected:
u1 _type;
bool _from_class_path_attr;
@@ -61,24 +65,25 @@
public:
void init(bool is_modules_image, ClassPathEntry* cpe, TRAPS);
+ void init_as_non_existent(const char* path, TRAPS);
void metaspace_pointers_do(MetaspaceClosure* it);
- bool validate(bool is_class_path = true);
+ bool validate(bool is_class_path = true) const;
// The _timestamp only gets set for jar files.
- bool has_timestamp() {
+ bool has_timestamp() const {
return _timestamp != 0;
}
- bool is_dir() { return _type == dir_entry; }
- bool is_modules_image() { return _type == modules_image_entry; }
- bool is_jar() { return _type == jar_entry; }
- bool is_signed() { return _type == signed_jar_entry; }
- void set_is_signed() {
+ bool is_dir() const { return _type == dir_entry; }
+ bool is_modules_image() const { return _type == modules_image_entry; }
+ bool is_jar() const { return _type == jar_entry; }
+ bool is_signed() const { return _type == signed_jar_entry; }
+ void set_is_signed() {
_type = signed_jar_entry;
}
bool from_class_path_attr() { return _from_class_path_attr; }
time_t timestamp() const { return _timestamp; }
long filesize() const { return _filesize; }
- const char* name() const { return _name->data(); }
+ const char* name() const;
const char* manifest() const {
return (_manifest == NULL) ? NULL : (const char*)_manifest->data();
}
@@ -88,6 +93,7 @@
void set_manifest(Array<u1>* manifest) {
_manifest = manifest;
}
+ bool check_non_existent() const;
};
struct ArchiveHeapOopmapInfo {
@@ -147,30 +153,12 @@
// size of the base archive name including NULL terminator
int _base_archive_name_size;
- // The _paths_misc_info is a variable-size structure that records "miscellaneous"
- // information during dumping. It is generated and validated by the
- // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
- // detailed description.
- //
- // The _paths_misc_info data is stored as a byte array in the archive file header,
- // immediately after the _header field. This information is used only when
- // checking the validity of the archive and is deallocated after the archive is loaded.
- //
- // Note that the _paths_misc_info does NOT include information for JAR files
- // that existed during dump time. Their information is stored in _shared_path_table.
- int _paths_misc_info_size;
-
- // The following is a table of all the class path entries that were used
- // during dumping. At run time, we require these files to exist and have the same
- // size/modification time, or else the archive will refuse to load.
- //
- // All of these entries must be JAR files. The dumping process would fail if a non-empty
- // directory was specified in the classpaths. If an empty directory was specified
- // it is checked by the _paths_misc_info as described above.
- //
- // FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
- // they should be removed from this table, to save space and to avoid spurious
- // loading failures during runtime.
+ // The following is a table of all the boot/app/module path entries that were used
+ // during dumping. At run time, we validate these entries according to their
+ // SharedClassPathEntry::_type. See:
+ // check_nonempty_dir_in_shared_path_table()
+ // validate_shared_path_table()
+ // validate_non_existent_class_paths()
SharedPathTable _shared_path_table;
jshort _app_class_paths_start_index; // Index of first app classpath entry
@@ -232,13 +220,14 @@
FileMapHeader * _header;
const char* _full_path;
- char* _paths_misc_info;
char* _base_archive_name;
static FileMapInfo* _current_info;
static FileMapInfo* _dynamic_archive_info;
static bool _heap_pointers_need_patching;
static bool _memory_mapping_failed;
+ static GrowableArray<const char*>* _non_existent_class_paths;
+
static bool get_base_archive_name_from_header(const char* archive_name,
int* size, char** base_archive_name);
static bool check_archive(const char* archive_name, bool is_static);
@@ -246,6 +235,8 @@
bool init_from_file(int fd, bool is_static);
static void metaspace_pointers_do(MetaspaceClosure* it);
+ void log_paths(const char* msg, int start_idx, int end_idx);
+
public:
FileMapInfo(bool is_static);
~FileMapInfo();
@@ -353,9 +344,13 @@
static void stop_sharing_and_unmap(const char* msg);
static void allocate_shared_path_table();
+ static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS);
static void check_nonempty_dir_in_shared_path_table();
bool validate_shared_path_table();
- static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
+ void validate_non_existent_class_paths();
+ static void update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
+ static int num_non_existent_class_paths();
+ static void record_non_existent_class_path_entry(const char* path);
#if INCLUDE_JVMTI
static ClassFileStream* open_stream_for_jvmti(InstanceKlass* ik, Handle class_loader, TRAPS);
@@ -379,11 +374,10 @@
private:
char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
int num_paths(const char* path) NOT_CDS_RETURN_(0);
- GrowableArray<char*>* create_path_array(const char* path) NOT_CDS_RETURN_(NULL);
+ GrowableArray<const char*>* create_path_array(const char* path) NOT_CDS_RETURN_(NULL);
bool fail(const char* msg, const char* name) NOT_CDS_RETURN_(false);
- bool check_paths(int shared_path_start_idx,
- int num_paths,
- GrowableArray<char*>* rp_array) NOT_CDS_RETURN_(false);
+ bool check_paths(int shared_path_start_idx, int num_paths,
+ GrowableArray<const char*>* rp_array) NOT_CDS_RETURN_(false);
bool validate_boot_class_paths() NOT_CDS_RETURN_(false);
bool validate_app_class_paths(int shared_app_paths_len) NOT_CDS_RETURN_(false);
bool map_heap_data(MemRegion **heap_mem, int first, int max, int* num,
--- a/src/hotspot/share/memory/heapShared.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/heapShared.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -79,6 +79,7 @@
{"java/util/ImmutableCollections$MapN", "EMPTY_MAP"},
{"java/util/ImmutableCollections$SetN", "EMPTY_SET"},
{"java/lang/module/Configuration", "EMPTY_CONFIGURATION"},
+ {"jdk/internal/math/FDBigInteger", "archivedCaches"},
};
const static int num_closed_archive_subgraph_entry_fields =
--- a/src/hotspot/share/memory/metaspace.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/memory/metaspace.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -29,6 +29,7 @@
#include "memory/metaspaceChunkFreeListSummary.hpp"
#include "memory/virtualspace.hpp"
#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
+#include "runtime/globals.hpp"
#include "utilities/exceptions.hpp"
// Metaspace
--- a/src/hotspot/share/oops/accessBackend.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/accessBackend.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -38,6 +38,7 @@
#include "metaprogramming/isVolatile.hpp"
#include "oops/accessDecorators.hpp"
#include "oops/oopsHierarchy.hpp"
+#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -946,7 +946,7 @@
while (is_being_initialized() && !is_reentrant_initialization(jt)) {
wait = true;
jt->set_class_to_be_initialized(this);
- ol.waitUninterruptibly(jt);
+ ol.wait_uninterruptibly(jt);
jt->set_class_to_be_initialized(NULL);
}
--- a/src/hotspot/share/oops/markWord.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/markWord.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -28,6 +28,7 @@
#include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/primitiveConversions.hpp"
#include "oops/oopsHierarchy.hpp"
+#include "runtime/globals.hpp"
// The markWord describes the header of an object.
//
--- a/src/hotspot/share/oops/oop.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/oop.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -173,35 +173,6 @@
}
}
-bool oopDesc::is_valid(oop obj) {
- if (!is_object_aligned(obj)) return false;
- if ((size_t)(oopDesc*)obj < os::min_page_size()) return false;
-
- // We need at least the mark and the klass word in the committed region.
- if (!os::is_readable_range(obj, (oopDesc*)obj + 1)) return false;
- if (!Universe::heap()->is_in(obj)) return false;
-
- Klass* k = (Klass*)load_klass_raw(obj);
- return Klass::is_valid(k);
-}
-
-oop oopDesc::oop_or_null(address addr) {
- if (is_valid(oop(addr))) {
- // We were just given an oop directly.
- return oop(addr);
- }
-
- // Try to find addr using block_start.
- HeapWord* p = Universe::heap()->block_start(addr);
- if (p != NULL && Universe::heap()->block_is_obj(p)) {
- if (!is_valid(oop(p))) return NULL;
- return oop(p);
- }
-
- // If we can't find it it just may mean that heap wasn't parsable.
- return NULL;
-}
-
oop oopDesc::obj_field_acquire(int offset) const { return HeapAccess<MO_ACQUIRE>::oop_load_at(as_oop(), offset); }
void oopDesc::obj_field_put_raw(int offset, oop value) { RawAccess<>::oop_store_at(as_oop(), offset, value); }
--- a/src/hotspot/share/oops/oop.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/oop.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -331,8 +331,6 @@
// for error reporting
static void* load_klass_raw(oop obj);
static void* load_oop_raw(oop obj, int offset);
- static bool is_valid(oop obj);
- static oop oop_or_null(address addr);
};
#endif // SHARE_OOPS_OOP_HPP
--- a/src/hotspot/share/oops/oopsHierarchy.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/oops/oopsHierarchy.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -73,7 +73,7 @@
class PromotedObject;
class oopDesc;
-extern bool CheckUnhandledOops;
+extern "C" bool CheckUnhandledOops;
class oop {
oopDesc* _o;
--- a/src/hotspot/share/prims/cdsoffsets.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/prims/cdsoffsets.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -53,7 +53,6 @@
ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapHeader, _space)); \
ADD_NEXT(_all, "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc)); \
ADD_NEXT(_all, "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used)); \
- ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapHeader, _paths_misc_info_size)); \
ADD_NEXT(_all, "file_header_size", sizeof(FileMapHeader)); \
ADD_NEXT(_all, "DynamicArchiveHeader::_base_archive_crc", offset_of(DynamicArchiveHeader, _base_archive_crc)); \
ADD_NEXT(_all, "CDSFileMapRegion_size", sizeof(CDSFileMapRegion));
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -960,7 +960,7 @@
if (at_safepoint) {
BiasedLocking::revoke_at_safepoint(hobj);
} else {
- BiasedLocking::revoke_and_rebias(hobj, false, calling_thread);
+ BiasedLocking::revoke(hobj, calling_thread);
}
address owner = NULL;
--- a/src/hotspot/share/prims/whitebox.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1137,27 +1137,29 @@
WB_END
template <typename T>
-static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAt)(const char*, T*, bool, bool)) {
+static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAt)(const JVMFlag*, T*)) {
if (name == NULL) {
return false;
}
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
const char* flag_name = env->GetStringUTFChars(name, NULL);
CHECK_JNI_EXCEPTION_(env, false);
- JVMFlag::Error result = (*TAt)(flag_name, value, true, true);
+ const JVMFlag* flag = JVMFlag::find_declared_flag(flag_name);
+ JVMFlag::Error result = (*TAt)(flag, value);
env->ReleaseStringUTFChars(name, flag_name);
return (result == JVMFlag::SUCCESS);
}
template <typename T>
-static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAtPut)(const char*, T*, JVMFlag::Flags)) {
+static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAtPut)(JVMFlag* flag, T*, JVMFlag::Flags)) {
if (name == NULL) {
return false;
}
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
const char* flag_name = env->GetStringUTFChars(name, NULL);
CHECK_JNI_EXCEPTION_(env, false);
- JVMFlag::Error result = (*TAtPut)(flag_name, value, JVMFlag::INTERNAL);
+ JVMFlag* flag = JVMFlag::find_flag(flag_name);
+ JVMFlag::Error result = (*TAtPut)(flag, value, JVMFlag::INTERNAL);
env->ReleaseStringUTFChars(name, flag_name);
return (result == JVMFlag::SUCCESS);
}
@@ -1192,22 +1194,22 @@
return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}
-static JVMFlag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
+static const JVMFlag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
const char* flag_name = env->GetStringUTFChars(name, NULL);
CHECK_JNI_EXCEPTION_(env, NULL);
- JVMFlag* result = JVMFlag::find_flag(flag_name, strlen(flag_name), true, true);
+ const JVMFlag* result = JVMFlag::find_declared_flag(flag_name);
env->ReleaseStringUTFChars(name, flag_name);
return result;
}
WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
- JVMFlag* flag = getVMFlag(thread, env, name);
+ const JVMFlag* flag = getVMFlag(thread, env, name);
return (flag != NULL) && flag->is_constant_in_binary();
WB_END
WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
- JVMFlag* flag = getVMFlag(thread, env, name);
+ const JVMFlag* flag = getVMFlag(thread, env, name);
return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
WB_END
--- a/src/hotspot/share/runtime/arguments.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -750,7 +750,7 @@
// if flag has become obsolete it should not have a "globals" flag defined anymore.
if (!version_less_than(JDK_Version::current(), flag.obsolete_in)) {
- if (JVMFlag::find_flag(flag.name) != NULL) {
+ if (JVMFlag::find_declared_flag(flag.name) != NULL) {
// Temporarily disable the warning: 8196739
// warning("Global variable for obsolete special flag entry \"%s\" should be removed", flag.name);
}
@@ -760,7 +760,7 @@
if (!flag.expired_in.is_undefined()) {
// if flag has become expired it should not have a "globals" flag defined anymore.
if (!version_less_than(JDK_Version::current(), flag.expired_in)) {
- if (JVMFlag::find_flag(flag.name) != NULL) {
+ if (JVMFlag::find_declared_flag(flag.name) != NULL) {
// Temporarily disable the warning: 8196739
// warning("Global variable for expired flag entry \"%s\" should be removed", flag.name);
}
@@ -844,15 +844,15 @@
}
}
-static bool set_bool_flag(const char* name, bool value, JVMFlag::Flags origin) {
- if (JVMFlag::boolAtPut(name, &value, origin) == JVMFlag::SUCCESS) {
+static bool set_bool_flag(JVMFlag* flag, bool value, JVMFlag::Flags origin) {
+ if (JVMFlag::boolAtPut(flag, &value, origin) == JVMFlag::SUCCESS) {
return true;
} else {
return false;
}
}
-static bool set_fp_numeric_flag(const char* name, char* value, JVMFlag::Flags origin) {
+static bool set_fp_numeric_flag(JVMFlag* flag, char* value, JVMFlag::Flags origin) {
char* end;
errno = 0;
double v = strtod(value, &end);
@@ -860,26 +860,25 @@
return false;
}
- if (JVMFlag::doubleAtPut(name, &v, origin) == JVMFlag::SUCCESS) {
+ if (JVMFlag::doubleAtPut(flag, &v, origin) == JVMFlag::SUCCESS) {
return true;
}
return false;
}
-static bool set_numeric_flag(const char* name, char* value, JVMFlag::Flags origin) {
+static bool set_numeric_flag(JVMFlag* flag, char* value, JVMFlag::Flags origin) {
julong v;
int int_v;
intx intx_v;
bool is_neg = false;
- JVMFlag* result = JVMFlag::find_flag(name, strlen(name));
-
- if (result == NULL) {
+
+ if (flag == NULL) {
return false;
}
// Check the sign first since atojulong() parses only unsigned values.
if (*value == '-') {
- if (!result->is_intx() && !result->is_int()) {
+ if (!flag->is_intx() && !flag->is_int()) {
return false;
}
value++;
@@ -888,48 +887,48 @@
if (!Arguments::atojulong(value, &v)) {
return false;
}
- if (result->is_int()) {
+ if (flag->is_int()) {
int_v = (int) v;
if (is_neg) {
int_v = -int_v;
}
- return JVMFlag::intAtPut(result, &int_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_uint()) {
+ return JVMFlag::intAtPut(flag, &int_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_uint()) {
uint uint_v = (uint) v;
- return JVMFlag::uintAtPut(result, &uint_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_intx()) {
+ return JVMFlag::uintAtPut(flag, &uint_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_intx()) {
intx_v = (intx) v;
if (is_neg) {
intx_v = -intx_v;
}
- return JVMFlag::intxAtPut(result, &intx_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_uintx()) {
+ return JVMFlag::intxAtPut(flag, &intx_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_uintx()) {
uintx uintx_v = (uintx) v;
- return JVMFlag::uintxAtPut(result, &uintx_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_uint64_t()) {
+ return JVMFlag::uintxAtPut(flag, &uintx_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_uint64_t()) {
uint64_t uint64_t_v = (uint64_t) v;
- return JVMFlag::uint64_tAtPut(result, &uint64_t_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_size_t()) {
+ return JVMFlag::uint64_tAtPut(flag, &uint64_t_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_size_t()) {
size_t size_t_v = (size_t) v;
- return JVMFlag::size_tAtPut(result, &size_t_v, origin) == JVMFlag::SUCCESS;
- } else if (result->is_double()) {
+ return JVMFlag::size_tAtPut(flag, &size_t_v, origin) == JVMFlag::SUCCESS;
+ } else if (flag->is_double()) {
double double_v = (double) v;
- return JVMFlag::doubleAtPut(result, &double_v, origin) == JVMFlag::SUCCESS;
+ return JVMFlag::doubleAtPut(flag, &double_v, origin) == JVMFlag::SUCCESS;
} else {
return false;
}
}
-static bool set_string_flag(const char* name, const char* value, JVMFlag::Flags origin) {
- if (JVMFlag::ccstrAtPut(name, &value, origin) != JVMFlag::SUCCESS) return false;
+static bool set_string_flag(JVMFlag* flag, const char* value, JVMFlag::Flags origin) {
+ if (JVMFlag::ccstrAtPut(flag, &value, origin) != JVMFlag::SUCCESS) return false;
// Contract: JVMFlag always returns a pointer that needs freeing.
FREE_C_HEAP_ARRAY(char, value);
return true;
}
-static bool append_to_string_flag(const char* name, const char* new_value, JVMFlag::Flags origin) {
+static bool append_to_string_flag(JVMFlag* flag, const char* new_value, JVMFlag::Flags origin) {
const char* old_value = "";
- if (JVMFlag::ccstrAt(name, &old_value) != JVMFlag::SUCCESS) return false;
+ if (JVMFlag::ccstrAt(flag, &old_value) != JVMFlag::SUCCESS) return false;
size_t old_len = old_value != NULL ? strlen(old_value) : 0;
size_t new_len = strlen(new_value);
const char* value;
@@ -946,7 +945,7 @@
value = buf;
free_this_too = buf;
}
- (void) JVMFlag::ccstrAtPut(name, &value, origin);
+ (void) JVMFlag::ccstrAtPut(flag, &value, origin);
// JVMFlag always returns a pointer that needs freeing.
FREE_C_HEAP_ARRAY(char, value);
if (free_this_too != NULL) {
@@ -1041,7 +1040,8 @@
if (real_name == NULL) {
return false;
}
- return set_bool_flag(real_name, false, origin);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
+ return set_bool_flag(flag, false, origin);
}
if (sscanf(arg, "+%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) {
AliasedLoggingFlag alf = catch_logging_aliases(name, true);
@@ -1053,13 +1053,13 @@
if (real_name == NULL) {
return false;
}
- return set_bool_flag(real_name, true, origin);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
+ return set_bool_flag(flag, true, origin);
}
char punct;
if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "%c", name, &punct) == 2 && punct == '=') {
const char* value = strchr(arg, '=') + 1;
- JVMFlag* flag;
// this scanf pattern matches both strings (handled here) and numbers (handled later))
AliasedLoggingFlag alf = catch_logging_aliases(name, true);
@@ -1071,15 +1071,15 @@
if (real_name == NULL) {
return false;
}
- flag = JVMFlag::find_flag(real_name);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
if (flag != NULL && flag->is_ccstr()) {
if (flag->ccstr_accumulates()) {
- return append_to_string_flag(real_name, value, origin);
+ return append_to_string_flag(flag, value, origin);
} else {
if (value[0] == '\0') {
value = NULL;
}
- return set_string_flag(real_name, value, origin);
+ return set_string_flag(flag, value, origin);
}
} else {
warn_if_deprecated = false; // if arg is deprecated, we've already done warning...
@@ -1096,7 +1096,8 @@
if (real_name == NULL) {
return false;
}
- return set_string_flag(real_name, value, origin);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
+ return set_string_flag(flag, value, origin);
}
#define SIGNED_FP_NUMBER_RANGE "[-0123456789.eE+]"
@@ -1111,7 +1112,8 @@
if (real_name == NULL) {
return false;
}
- return set_fp_numeric_flag(real_name, value, origin);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
+ return set_fp_numeric_flag(flag, value, origin);
}
}
@@ -1121,7 +1123,8 @@
if (real_name == NULL) {
return false;
}
- return set_numeric_flag(real_name, value, origin);
+ JVMFlag* flag = JVMFlag::find_flag(real_name);
+ return set_numeric_flag(flag, value, origin);
}
return false;
@@ -1277,7 +1280,7 @@
// For locked flags, report a custom error message if available.
// Otherwise, report the standard unrecognized VM option.
- JVMFlag* found_flag = JVMFlag::find_flag((const char*)argname, arg_len, true, true);
+ const JVMFlag* found_flag = JVMFlag::find_declared_flag((const char*)argname, arg_len);
if (found_flag != NULL) {
char locked_message_buf[BUFLEN];
JVMFlag::MsgType msg_type = found_flag->get_locked_message(locked_message_buf, BUFLEN);
--- a/src/hotspot/share/runtime/biasedLocking.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/biasedLocking.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -157,7 +157,7 @@
// After the call, *biased_locker will be set to obj->mark()->biased_locker() if biased_locker != NULL,
// AND it is a living thread. Otherwise it will not be updated, (i.e. the caller is responsible for initialization).
-BiasedLocking::Condition BiasedLocking::single_revoke_at_safepoint(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) {
+void BiasedLocking::single_revoke_at_safepoint(oop obj, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) {
assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
assert(Thread::current()->is_VM_thread(), "must be VMThread");
@@ -173,11 +173,10 @@
obj->klass()->external_name(),
(intptr_t) requesting_thread);
}
- return NOT_BIASED;
+ return;
}
uint age = mark.age();
- markWord biased_prototype = markWord::biased_locking_prototype().set_age(age);
markWord unbiased_prototype = markWord::prototype().set_age(age);
// Log at "info" level if not bulk, else "trace" level
@@ -185,23 +184,21 @@
ResourceMark rm;
log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT ", mark "
INTPTR_FORMAT ", type %s, prototype header " INTPTR_FORMAT
- ", allow rebias %d, requesting thread " INTPTR_FORMAT,
+ ", requesting thread " INTPTR_FORMAT,
p2i((void *)obj),
mark.value(),
obj->klass()->external_name(),
obj->klass()->prototype_header().value(),
- (allow_rebias ? 1 : 0),
(intptr_t) requesting_thread);
} else {
ResourceMark rm;
log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark "
INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT
- " , allow rebias %d , requesting thread " INTPTR_FORMAT,
+ " , requesting thread " INTPTR_FORMAT,
p2i((void *)obj),
mark.value(),
obj->klass()->external_name(),
obj->klass()->prototype_header().value(),
- (allow_rebias ? 1 : 0),
(intptr_t) requesting_thread);
}
@@ -210,16 +207,15 @@
// Object is anonymously biased. We can get here if, for
// example, we revoke the bias due to an identity hash code
// being computed for an object.
- if (!allow_rebias) {
- obj->set_mark(unbiased_prototype);
- }
+ obj->set_mark(unbiased_prototype);
+
// Log at "info" level if not bulk, else "trace" level
if (!is_bulk) {
log_info(biasedlocking)(" Revoked bias of anonymously-biased object");
} else {
log_trace(biasedlocking)(" Revoked bias of anonymously-biased object");
}
- return BIAS_REVOKED;
+ return;
}
// Handle case where the thread toward which the object was biased has exited
@@ -231,11 +227,7 @@
thread_is_alive = tlh.includes(biased_thread);
}
if (!thread_is_alive) {
- if (allow_rebias) {
- obj->set_mark(biased_prototype);
- } else {
- obj->set_mark(unbiased_prototype);
- }
+ obj->set_mark(unbiased_prototype);
// Log at "info" level if not bulk, else "trace" level
if (!is_bulk) {
log_info(biasedlocking)(" Revoked bias of object biased toward dead thread ("
@@ -244,7 +236,7 @@
log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread ("
PTR_FORMAT ")", p2i(biased_thread));
}
- return BIAS_REVOKED;
+ return;
}
// Log at "info" level if not bulk, else "trace" level
@@ -301,20 +293,14 @@
} else {
log_trace(biasedlocking)(" Revoked bias of currently-unlocked object");
}
- if (allow_rebias) {
- obj->set_mark(biased_prototype);
- } else {
- // Store the unlocked value into the object's header.
- obj->set_mark(unbiased_prototype);
- }
+ // Store the unlocked value into the object's header.
+ obj->set_mark(unbiased_prototype);
}
// If requested, return information on which thread held the bias
if (biased_locker != NULL) {
*biased_locker = biased_thread;
}
-
- return BIAS_REVOKED;
}
@@ -379,10 +365,7 @@
}
-BiasedLocking::Condition BiasedLocking::bulk_revoke_or_rebias_at_safepoint(oop o,
- bool bulk_rebias,
- bool attempt_rebias_of_object,
- JavaThread* requesting_thread) {
+void BiasedLocking::bulk_revoke_at_safepoint(oop o, bool bulk_rebias, JavaThread* requesting_thread) {
assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
assert(Thread::current()->is_VM_thread(), "must be VMThread");
@@ -437,7 +420,7 @@
// At this point we're done. All we have to do is potentially
// adjust the header of the given object to revoke its bias.
- single_revoke_at_safepoint(o, attempt_rebias_of_object && klass->prototype_header().has_bias_pattern(), true, requesting_thread, NULL);
+ single_revoke_at_safepoint(o, true, requesting_thread, NULL);
} else {
if (log_is_enabled(Info, biasedlocking)) {
ResourceMark rm;
@@ -459,36 +442,20 @@
oop owner = mon_info->owner();
markWord mark = owner->mark();
if ((owner->klass() == k_o) && mark.has_bias_pattern()) {
- single_revoke_at_safepoint(owner, false, true, requesting_thread, NULL);
+ single_revoke_at_safepoint(owner, true, requesting_thread, NULL);
}
}
}
// Must force the bias of the passed object to be forcibly revoked
// as well to ensure guarantees to callers
- single_revoke_at_safepoint(o, false, true, requesting_thread, NULL);
+ single_revoke_at_safepoint(o, true, requesting_thread, NULL);
}
} // ThreadsListHandle is destroyed here.
log_info(biasedlocking)("* Ending bulk revocation");
- BiasedLocking::Condition status_code = BIAS_REVOKED;
-
- if (attempt_rebias_of_object &&
- o->mark().has_bias_pattern() &&
- klass->prototype_header().has_bias_pattern()) {
- markWord new_mark = markWord::encode(requesting_thread, o->mark().age(),
- klass->prototype_header().bias_epoch());
- o->set_mark(new_mark);
- status_code = BIAS_REVOKED_AND_REBIASED;
- log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
- }
-
- assert(!o->mark().has_bias_pattern() ||
- (attempt_rebias_of_object && (o->mark().biased_locker() == requesting_thread)),
- "bug in bulk bias revocation");
-
- return status_code;
+ assert(!o->mark().has_bias_pattern(), "bug in bulk bias revocation");
}
@@ -509,25 +476,20 @@
Handle* _obj;
JavaThread* _requesting_thread;
bool _bulk_rebias;
- bool _attempt_rebias_of_object;
- BiasedLocking::Condition _status_code;
uint64_t _safepoint_id;
public:
VM_BulkRevokeBias(Handle* obj, JavaThread* requesting_thread,
- bool bulk_rebias,
- bool attempt_rebias_of_object)
+ bool bulk_rebias)
: _obj(obj)
, _requesting_thread(requesting_thread)
, _bulk_rebias(bulk_rebias)
- , _attempt_rebias_of_object(attempt_rebias_of_object)
- , _status_code(BiasedLocking::NOT_BIASED)
, _safepoint_id(0) {}
virtual VMOp_Type type() const { return VMOp_BulkRevokeBias; }
virtual void doit() {
- _status_code = BiasedLocking::bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
+ BiasedLocking::bulk_revoke_at_safepoint((*_obj)(), _bulk_rebias, _requesting_thread);
_safepoint_id = SafepointSynchronize::safepoint_id();
clean_up_cached_monitor_info();
}
@@ -536,10 +498,6 @@
return _bulk_rebias;
}
- BiasedLocking::Condition status_code() const {
- return _status_code;
- }
-
uint64_t safepoint_id() const {
return _safepoint_id;
}
@@ -769,7 +727,7 @@
}
-BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {
+void BiasedLocking::revoke(Handle obj, TRAPS) {
assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");
while (true) {
@@ -778,7 +736,12 @@
// update the heuristics because doing so may cause unwanted bulk
// revocations (which are expensive) to occur.
markWord mark = obj->mark();
- if (mark.is_biased_anonymously() && !attempt_rebias) {
+
+ if (!mark.has_bias_pattern()) {
+ return;
+ }
+
+ if (mark.is_biased_anonymously()) {
// We are probably trying to revoke the bias of this object due to
// an identity hash code computation. Try to revoke the bias
// without a safepoint. This is possible if we can successfully
@@ -789,10 +752,10 @@
markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
markWord res_mark = obj->cas_set_mark(unbiased_prototype, mark);
if (res_mark == biased_value) {
- return BIAS_REVOKED;
+ return;
}
mark = res_mark; // Refresh mark with the latest value.
- } else if (mark.has_bias_pattern()) {
+ } else {
Klass* k = obj->klass();
markWord prototype_header = k->prototype_header();
if (!prototype_header.has_bias_pattern()) {
@@ -804,31 +767,20 @@
// with it.
obj->cas_set_mark(prototype_header.set_age(mark.age()), mark);
assert(!obj->mark().has_bias_pattern(), "even if we raced, should still be revoked");
- return BIAS_REVOKED;
+ return;
} else if (prototype_header.bias_epoch() != mark.bias_epoch()) {
// The epoch of this biasing has expired indicating that the
- // object is effectively unbiased. Depending on whether we need
- // to rebias or revoke the bias of this object we can do it
- // efficiently enough with a CAS that we shouldn't update the
+ // object is effectively unbiased. We can revoke the bias of this
+ // object efficiently enough with a CAS that we shouldn't update the
// heuristics. This is normally done in the assembly code but we
// can reach this point due to various points in the runtime
// needing to revoke biases.
markWord res_mark;
- if (attempt_rebias) {
- assert(THREAD->is_Java_thread(), "");
- markWord biased_value = mark;
- markWord rebiased_prototype = markWord::encode((JavaThread*) THREAD, mark.age(), prototype_header.bias_epoch());
- res_mark = obj->cas_set_mark(rebiased_prototype, mark);
- if (res_mark == biased_value) {
- return BIAS_REVOKED_AND_REBIASED;
- }
- } else {
- markWord biased_value = mark;
- markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
- res_mark = obj->cas_set_mark(unbiased_prototype, mark);
- if (res_mark == biased_value) {
- return BIAS_REVOKED;
- }
+ markWord biased_value = mark;
+ markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
+ res_mark = obj->cas_set_mark(unbiased_prototype, mark);
+ if (res_mark == biased_value) {
+ return;
}
mark = res_mark; // Refresh mark with the latest value.
}
@@ -836,7 +788,7 @@
HeuristicsResult heuristics = update_heuristics(obj());
if (heuristics == HR_NOT_BIASED) {
- return NOT_BIASED;
+ return;
} else if (heuristics == HR_SINGLE_REVOKE) {
JavaThread *blt = mark.biased_locker();
assert(blt != NULL, "invariant");
@@ -855,11 +807,11 @@
if (event.should_commit()) {
post_self_revocation_event(&event, obj->klass());
}
- return BIAS_REVOKED;
+ return;
} else {
BiasedLocking::Condition cond = single_revoke_with_handshake(obj, (JavaThread*)THREAD, blt);
if (cond != NOT_REVOKED) {
- return cond;
+ return;
}
}
} else {
@@ -867,13 +819,12 @@
(heuristics == HR_BULK_REBIAS), "?");
EventBiasedLockClassRevocation event;
VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*)THREAD,
- (heuristics == HR_BULK_REBIAS),
- attempt_rebias);
+ (heuristics == HR_BULK_REBIAS));
VMThread::execute(&bulk_revoke);
if (event.should_commit()) {
post_class_revocation_event(&event, obj->klass(), &bulk_revoke);
}
- return bulk_revoke.status_code();
+ return;
}
}
}
@@ -901,13 +852,13 @@
HeuristicsResult heuristics = update_heuristics(obj);
if (heuristics == HR_SINGLE_REVOKE) {
JavaThread* biased_locker = NULL;
- single_revoke_at_safepoint(obj, false, false, NULL, &biased_locker);
+ single_revoke_at_safepoint(obj, false, NULL, &biased_locker);
if (biased_locker) {
clean_up_cached_monitor_info(biased_locker);
}
} else if ((heuristics == HR_BULK_REBIAS) ||
(heuristics == HR_BULK_REVOKE)) {
- bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
+ bulk_revoke_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), NULL);
clean_up_cached_monitor_info();
}
}
@@ -920,10 +871,10 @@
oop obj = (objs->at(i))();
HeuristicsResult heuristics = update_heuristics(obj);
if (heuristics == HR_SINGLE_REVOKE) {
- single_revoke_at_safepoint(obj, false, false, NULL, NULL);
+ single_revoke_at_safepoint(obj, false, NULL, NULL);
} else if ((heuristics == HR_BULK_REBIAS) ||
(heuristics == HR_BULK_REVOKE)) {
- bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
+ bulk_revoke_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), NULL);
}
}
clean_up_cached_monitor_info();
--- a/src/hotspot/share/runtime/biasedLocking.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/biasedLocking.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -168,13 +168,12 @@
enum Condition {
NOT_BIASED = 1,
BIAS_REVOKED = 2,
- BIAS_REVOKED_AND_REBIASED = 3,
- NOT_REVOKED = 4
+ NOT_REVOKED = 3
};
private:
- static Condition single_revoke_at_safepoint(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requester, JavaThread** biaser);
- static Condition bulk_revoke_or_rebias_at_safepoint(oop o, bool bulk_rebias, bool attempt_rebias, JavaThread* requester);
+ static void single_revoke_at_safepoint(oop obj, bool is_bulk, JavaThread* requester, JavaThread** biaser);
+ static void bulk_revoke_at_safepoint(oop o, bool bulk_rebias, JavaThread* requester);
static Condition single_revoke_with_handshake(Handle obj, JavaThread *requester, JavaThread *biaser);
static void walk_stack_and_revoke(oop obj, JavaThread* biased_locker);
@@ -189,12 +188,13 @@
static bool enabled();
// This should be called by JavaThreads to revoke the bias of an object
- static Condition revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS);
+ static void revoke(Handle obj, TRAPS);
+
+ static void revoke_at_safepoint(Handle obj);
- // These do not allow rebiasing; they are used by deoptimization to
- // ensure that monitors on the stack can be migrated
+ // These are used by deoptimization to ensure that monitors on the stack
+ // can be migrated
static void revoke(GrowableArray<Handle>* objs, JavaThread *biaser);
- static void revoke_at_safepoint(Handle obj);
static void revoke_at_safepoint(GrowableArray<Handle>* objs);
static void print_counters() { _counters.print(); }
--- a/src/hotspot/share/runtime/deoptimization.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/deoptimization.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1264,7 +1264,7 @@
obj->set_mark(unbiased_prototype);
}
BasicLock* lock = mon_info->lock();
- ObjectSynchronizer::slow_enter(obj, lock, thread);
+ ObjectSynchronizer::enter(obj, lock, thread);
assert(mon_info->owner()->is_locked(), "object must be locked now");
}
}
@@ -1374,7 +1374,7 @@
for (int j = 0; j < monitors->number_of_monitors(); j++) {
BasicObjectLock* src = monitors->at(j);
if (src->obj() != NULL) {
- ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
+ ObjectSynchronizer::exit(src->obj(), src->lock(), thread);
}
}
array->element(i)->free_monitors(thread);
--- a/src/hotspot/share/runtime/flags/jvmFlag.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlag.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -604,7 +604,7 @@
st->cr();
return;
}
- JVMFlagRangeList::print(st, _name, func);
+ JVMFlagRangeList::print(st, this, func);
fill_to_pos(st, col5_pos);
print_kind(st, col5_width);
@@ -957,103 +957,82 @@
}
// Returns the address of the index'th element
-static JVMFlag* address_of_flag(JVMFlagsEnum flag) {
+JVMFlag* JVMFlagEx::flag_from_enum(JVMFlagsEnum flag) {
assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
return &JVMFlag::flags[flag];
}
bool JVMFlagEx::is_default(JVMFlagsEnum flag) {
- assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
- JVMFlag* f = &JVMFlag::flags[flag];
- return f->is_default();
+ return flag_from_enum(flag)->is_default();
}
bool JVMFlagEx::is_ergo(JVMFlagsEnum flag) {
- assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
- JVMFlag* f = &JVMFlag::flags[flag];
- return f->is_ergonomic();
+ return flag_from_enum(flag)->is_ergonomic();
}
bool JVMFlagEx::is_cmdline(JVMFlagsEnum flag) {
- assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
- JVMFlag* f = &JVMFlag::flags[flag];
- return f->is_command_line();
-}
-
-bool JVMFlag::wasSetOnCmdline(const char* name, bool* value) {
- JVMFlag* result = JVMFlag::find_flag((char*)name, strlen(name));
- if (result == NULL) return false;
- *value = result->is_command_line();
- return true;
+ return flag_from_enum(flag)->is_command_line();
}
void JVMFlagEx::setOnCmdLine(JVMFlagsEnum flag) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
assert(faddr != NULL, "Unknown flag");
faddr->set_command_line();
}
template<class E, class T>
-static void trace_flag_changed(const char* name, const T old_value, const T new_value, const JVMFlag::Flags origin) {
+static void trace_flag_changed(const JVMFlag* flag, const T old_value, const T new_value, const JVMFlag::Flags origin) {
E e;
- e.set_name(name);
+ e.set_name(flag->_name);
e.set_oldValue(old_value);
e.set_newValue(new_value);
e.set_origin(origin);
e.commit();
}
-static JVMFlag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_bool(const JVMFlag* flag, bool new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_bool(new_value, verbose);
}
return status;
}
-JVMFlag::Error JVMFlag::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_bool()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_bool();
+JVMFlag::Error JVMFlag::boolAt(const JVMFlag* flag, bool* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_bool()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_bool();
return JVMFlag::SUCCESS;
}
JVMFlag::Error JVMFlag::boolAtPut(JVMFlag* flag, bool* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_bool()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_bool(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_bool(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
bool old_value = flag->get_bool();
- trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
+ trace_flag_changed<EventBooleanFlagChanged, bool>(flag, old_value, *value, origin);
check = flag->set_bool(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::boolAtPut(const char* name, size_t len, bool* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return boolAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::boolAtPut(JVMFlagsEnum flag, bool value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
return JVMFlag::boolAtPut(faddr, &value, origin);
}
-static JVMFlag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_int(const JVMFlag* flag, int new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_int(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_int(new_value, verbose);
}
@@ -1061,48 +1040,40 @@
return status;
}
-JVMFlag::Error JVMFlag::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_int()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_int();
+JVMFlag::Error JVMFlag::intAt(const JVMFlag* flag, int* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_int()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_int();
return JVMFlag::SUCCESS;
}
JVMFlag::Error JVMFlag::intAtPut(JVMFlag* flag, int* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_int()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_int(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_int(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
int old_value = flag->get_int();
- trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
+ trace_flag_changed<EventIntFlagChanged, s4>(flag, old_value, *value, origin);
check = flag->set_int(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::intAtPut(const char* name, size_t len, int* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return intAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::intAtPut(JVMFlagsEnum flag, int value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_int(), "wrong flag type");
return JVMFlag::intAtPut(faddr, &value, origin);
}
-static JVMFlag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_uint(const JVMFlag* flag, uint new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_uint(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_uint(new_value, verbose);
}
@@ -1110,56 +1081,47 @@
return status;
}
-JVMFlag::Error JVMFlag::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_uint()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_uint();
+JVMFlag::Error JVMFlag::uintAt(const JVMFlag* flag, uint* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_uint()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_uint();
return JVMFlag::SUCCESS;
}
JVMFlag::Error JVMFlag::uintAtPut(JVMFlag* flag, uint* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_uint()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_uint(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_uint(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
uint old_value = flag->get_uint();
- trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
+ trace_flag_changed<EventUnsignedIntFlagChanged, u4>(flag, old_value, *value, origin);
check = flag->set_uint(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::uintAtPut(const char* name, size_t len, uint* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return uintAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::uintAtPut(JVMFlagsEnum flag, uint value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type");
return JVMFlag::uintAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_intx()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_intx();
+JVMFlag::Error JVMFlag::intxAt(const JVMFlag* flag, intx* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_intx()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_intx();
return JVMFlag::SUCCESS;
}
-static JVMFlag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_intx(const JVMFlag* flag, intx new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_intx(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_intx(new_value, verbose);
}
@@ -1168,47 +1130,39 @@
}
JVMFlag::Error JVMFlag::intxAtPut(JVMFlag* flag, intx* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_intx()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_intx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_intx(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
intx old_value = flag->get_intx();
- trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
+ trace_flag_changed<EventLongFlagChanged, intx>(flag, old_value, *value, origin);
check = flag->set_intx(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::intxAtPut(const char* name, size_t len, intx* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return intxAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::intxAtPut(JVMFlagsEnum flag, intx value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
return JVMFlag::intxAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_uintx()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_uintx();
+JVMFlag::Error JVMFlag::uintxAt(const JVMFlag* flag, uintx* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_uintx()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_uintx();
return JVMFlag::SUCCESS;
}
-static JVMFlag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_uintx(const JVMFlag* flag, uintx new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_uintx(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_uintx(new_value, verbose);
}
@@ -1217,47 +1171,39 @@
}
JVMFlag::Error JVMFlag::uintxAtPut(JVMFlag* flag, uintx* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_uintx()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_uintx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_uintx(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
uintx old_value = flag->get_uintx();
- trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
+ trace_flag_changed<EventUnsignedLongFlagChanged, u8>(flag, old_value, *value, origin);
check = flag->set_uintx(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::uintxAtPut(const char* name, size_t len, uintx* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return uintxAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::uintxAtPut(JVMFlagsEnum flag, uintx value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
return JVMFlag::uintxAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_uint64_t();
+JVMFlag::Error JVMFlag::uint64_tAt(const JVMFlag* flag, uint64_t* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_uint64_t();
return JVMFlag::SUCCESS;
}
-static JVMFlag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_uint64_t(const JVMFlag* flag, uint64_t new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_uint64_t(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_uint64_t(new_value, verbose);
}
@@ -1266,47 +1212,39 @@
}
JVMFlag::Error JVMFlag::uint64_tAtPut(JVMFlag* flag, uint64_t* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_uint64_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_uint64_t(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
uint64_t old_value = flag->get_uint64_t();
- trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
+ trace_flag_changed<EventUnsignedLongFlagChanged, u8>(flag, old_value, *value, origin);
check = flag->set_uint64_t(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::uint64_tAtPut(const char* name, size_t len, uint64_t* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return uint64_tAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::uint64_tAtPut(JVMFlagsEnum flag, uint64_t value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
return JVMFlag::uint64_tAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_size_t()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_size_t();
+JVMFlag::Error JVMFlag::size_tAt(const JVMFlag* flag, size_t* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_size_t()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_size_t();
return JVMFlag::SUCCESS;
}
-static JVMFlag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_size_t(const JVMFlag* flag, size_t new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_size_t(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_size_t(new_value, verbose);
}
@@ -1316,47 +1254,39 @@
JVMFlag::Error JVMFlag::size_tAtPut(JVMFlag* flag, size_t* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_size_t()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_size_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_size_t(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
size_t old_value = flag->get_size_t();
- trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
+ trace_flag_changed<EventUnsignedLongFlagChanged, u8>(flag, old_value, *value, origin);
check = flag->set_size_t(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::size_tAtPut(const char* name, size_t len, size_t* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return size_tAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::size_tAtPut(JVMFlagsEnum flag, size_t value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
return JVMFlag::size_tAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_double()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_double();
+JVMFlag::Error JVMFlag::doubleAt(const JVMFlag* flag, double* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_double()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_double();
return JVMFlag::SUCCESS;
}
-static JVMFlag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose) {
+static JVMFlag::Error apply_constraint_and_check_range_double(const JVMFlag* flag, double new_value, bool verbose) {
JVMFlag::Error status = JVMFlag::SUCCESS;
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
status = range->check_double(new_value, verbose);
}
if (status == JVMFlag::SUCCESS) {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(flag);
if (constraint != NULL) {
status = constraint->apply_double(new_value, verbose);
}
@@ -1365,64 +1295,55 @@
}
JVMFlag::Error JVMFlag::doubleAtPut(JVMFlag* flag, double* value, JVMFlag::Flags origin) {
- const char* name;
if (flag == NULL) return JVMFlag::INVALID_FLAG;
if (!flag->is_double()) return JVMFlag::WRONG_FORMAT;
- name = flag->_name;
- JVMFlag::Error check = apply_constraint_and_check_range_double(name, *value, !JVMFlagConstraintList::validated_after_ergo());
+ JVMFlag::Error check = apply_constraint_and_check_range_double(flag, *value, !JVMFlagConstraintList::validated_after_ergo());
if (check != JVMFlag::SUCCESS) return check;
double old_value = flag->get_double();
- trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
+ trace_flag_changed<EventDoubleFlagChanged, double>(flag, old_value, *value, origin);
check = flag->set_double(*value);
*value = old_value;
flag->set_origin(origin);
return check;
}
-JVMFlag::Error JVMFlag::doubleAtPut(const char* name, size_t len, double* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- return doubleAtPut(result, value, origin);
-}
-
JVMFlag::Error JVMFlagEx::doubleAtPut(JVMFlagsEnum flag, double value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
return JVMFlag::doubleAtPut(faddr, &value, origin);
}
-JVMFlag::Error JVMFlag::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
- JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
- *value = result->get_ccstr();
+JVMFlag::Error JVMFlag::ccstrAt(const JVMFlag* flag, ccstr* value) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_ccstr()) return JVMFlag::WRONG_FORMAT;
+ *value = flag->get_ccstr();
return JVMFlag::SUCCESS;
}
-JVMFlag::Error JVMFlag::ccstrAtPut(const char* name, size_t len, ccstr* value, JVMFlag::Flags origin) {
- JVMFlag* result = JVMFlag::find_flag(name, len);
- if (result == NULL) return JVMFlag::INVALID_FLAG;
- if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
- ccstr old_value = result->get_ccstr();
- trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
+JVMFlag::Error JVMFlag::ccstrAtPut(JVMFlag* flag, ccstr* value, JVMFlag::Flags origin) {
+ if (flag == NULL) return JVMFlag::INVALID_FLAG;
+ if (!flag->is_ccstr()) return JVMFlag::WRONG_FORMAT;
+ ccstr old_value = flag->get_ccstr();
+ trace_flag_changed<EventStringFlagChanged, const char*>(flag, old_value, *value, origin);
char* new_value = NULL;
if (*value != NULL) {
new_value = os::strdup_check_oom(*value);
}
- JVMFlag::Error check = result->set_ccstr(new_value);
- if (result->is_default() && old_value != NULL) {
+ JVMFlag::Error check = flag->set_ccstr(new_value);
+ if (flag->is_default() && old_value != NULL) {
// Prior value is NOT heap allocated, but was a literal constant.
old_value = os::strdup_check_oom(old_value);
}
*value = old_value;
- result->set_origin(origin);
+ flag->set_origin(origin);
return check;
}
JVMFlag::Error JVMFlagEx::ccstrAtPut(JVMFlagsEnum flag, ccstr value, JVMFlag::Flags origin) {
- JVMFlag* faddr = address_of_flag(flag);
+ JVMFlag* faddr = flag_from_enum(flag);
guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
ccstr old_value = faddr->get_ccstr();
- trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
+ trace_flag_changed<EventStringFlagChanged, const char*>(faddr, old_value, value, origin);
char* new_value = os::strdup_check_oom(value);
JVMFlag::Error check = faddr->set_ccstr(new_value);
if (!faddr->is_default() && old_value != NULL) {
--- a/src/hotspot/share/runtime/flags/jvmFlag.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlag.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -118,8 +118,20 @@
// number of flags
static size_t numFlags;
- static JVMFlag* find_flag(const char* name) { return find_flag(name, strlen(name), true, true); };
- static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked = false, bool return_flag = false);
+private:
+ static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked, bool return_flag);
+
+public:
+ static JVMFlag* find_flag(const char* name) {
+ return find_flag(name, strlen(name), false, false);
+ }
+ static const JVMFlag* find_declared_flag(const char* name, size_t length) {
+ return find_flag(name, length, true, true);
+ }
+ static const JVMFlag* find_declared_flag(const char* name) {
+ return find_declared_flag(name, strlen(name));
+ }
+
static JVMFlag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);
static const char* get_int_default_range_str();
@@ -213,63 +225,35 @@
static const char* flag_error_str(JVMFlag::Error error);
public:
- static JVMFlag::Error boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::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); }
+ static JVMFlag::Error boolAt(const JVMFlag* flag, bool* value);
static JVMFlag::Error boolAtPut(JVMFlag* flag, bool* value, JVMFlag::Flags origin);
- static JVMFlag::Error boolAtPut(const char* name, size_t len, bool* value, JVMFlag::Flags origin);
- static JVMFlag::Error boolAtPut(const char* name, bool* value, JVMFlag::Flags origin) { return boolAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error intAt(const char* name, size_t len, int* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error intAt(const char* name, int* value, bool allow_locked = false, bool return_flag = false) { return intAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error intAt(const JVMFlag* flag, int* value);
static JVMFlag::Error intAtPut(JVMFlag* flag, int* value, JVMFlag::Flags origin);
- static JVMFlag::Error intAtPut(const char* name, size_t len, int* value, JVMFlag::Flags origin);
- static JVMFlag::Error intAtPut(const char* name, int* value, JVMFlag::Flags origin) { return intAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error uintAt(const char* name, size_t len, uint* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error uintAt(const char* name, uint* value, bool allow_locked = false, bool return_flag = false) { return uintAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error uintAt(const JVMFlag* flag, uint* value);
static JVMFlag::Error uintAtPut(JVMFlag* flag, uint* value, JVMFlag::Flags origin);
- static JVMFlag::Error uintAtPut(const char* name, size_t len, uint* value, JVMFlag::Flags origin);
- static JVMFlag::Error uintAtPut(const char* name, uint* value, JVMFlag::Flags origin) { return uintAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false) { return intxAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error intxAt(const JVMFlag* flag, intx* value);
static JVMFlag::Error intxAtPut(JVMFlag* flag, intx* value, JVMFlag::Flags origin);
- static JVMFlag::Error intxAtPut(const char* name, size_t len, intx* value, JVMFlag::Flags origin);
- static JVMFlag::Error intxAtPut(const char* name, intx* value, JVMFlag::Flags origin) { return intxAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false) { return uintxAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error uintxAt(const JVMFlag* flag, uintx* value);
static JVMFlag::Error uintxAtPut(JVMFlag* flag, uintx* value, JVMFlag::Flags origin);
- static JVMFlag::Error uintxAtPut(const char* name, size_t len, uintx* value, JVMFlag::Flags origin);
- static JVMFlag::Error uintxAtPut(const char* name, uintx* value, JVMFlag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false) { return size_tAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error size_tAt(const JVMFlag* flag, size_t* value);
static JVMFlag::Error size_tAtPut(JVMFlag* flag, size_t* value, JVMFlag::Flags origin);
- static JVMFlag::Error size_tAtPut(const char* name, size_t len, size_t* value, JVMFlag::Flags origin);
- static JVMFlag::Error size_tAtPut(const char* name, size_t* value, JVMFlag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error uint64_tAt(const JVMFlag* flag, uint64_t* value);
static JVMFlag::Error uint64_tAtPut(JVMFlag* flag, uint64_t* value, JVMFlag::Flags origin);
- static JVMFlag::Error uint64_tAtPut(const char* name, size_t len, uint64_t* value, JVMFlag::Flags origin);
- static JVMFlag::Error uint64_tAtPut(const char* name, uint64_t* value, JVMFlag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false) { return doubleAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error doubleAt(const JVMFlag* flag, double* value);
static JVMFlag::Error doubleAtPut(JVMFlag* flag, double* value, JVMFlag::Flags origin);
- static JVMFlag::Error doubleAtPut(const char* name, size_t len, double* value, JVMFlag::Flags origin);
- static JVMFlag::Error doubleAtPut(const char* name, double* value, JVMFlag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
- static JVMFlag::Error ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false);
- static JVMFlag::Error ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false) { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); }
+ static JVMFlag::Error ccstrAt(const JVMFlag* flag, ccstr* value);
// Contract: JVMFlag will make private copy of the incoming value.
// Outgoing value is always malloc-ed, and caller MUST call free.
- static JVMFlag::Error ccstrAtPut(const char* name, size_t len, ccstr* value, JVMFlag::Flags origin);
- static JVMFlag::Error ccstrAtPut(const char* name, ccstr* value, JVMFlag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); }
+ static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr* value, JVMFlag::Flags origin);
- // Returns false if name is not a command line flag.
- static bool wasSetOnCmdline(const char* name, bool* value);
static void printSetFlags(outputStream* out);
// printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
--- a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -32,22 +32,20 @@
#include "runtime/flags/jvmFlagConstraintsCompiler.hpp"
#include "runtime/flags/jvmFlagConstraintsRuntime.hpp"
#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
class JVMFlagConstraint_bool : public JVMFlagConstraint {
JVMFlagConstraintFunc_bool _constraint;
- const bool* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_bool(const char* name, const bool* ptr,
- JVMFlagConstraintFunc_bool func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_bool(const JVMFlag* flag,
+ JVMFlagConstraintFunc_bool func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- bool value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_bool(), verbose);
}
JVMFlag::Error apply_bool(bool value, bool verbose) {
@@ -57,17 +55,14 @@
class JVMFlagConstraint_int : public JVMFlagConstraint {
JVMFlagConstraintFunc_int _constraint;
- const int* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_int(const char* name, const int* ptr,
- JVMFlagConstraintFunc_int func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_int(const JVMFlag* flag,
+ JVMFlagConstraintFunc_int func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- int value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_int(), verbose);
}
JVMFlag::Error apply_int(int value, bool verbose) {
@@ -77,17 +72,14 @@
class JVMFlagConstraint_intx : public JVMFlagConstraint {
JVMFlagConstraintFunc_intx _constraint;
- const intx* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_intx(const char* name, const intx* ptr,
- JVMFlagConstraintFunc_intx func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_intx(const JVMFlag* flag,
+ JVMFlagConstraintFunc_intx func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- intx value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_intx(), verbose);
}
JVMFlag::Error apply_intx(intx value, bool verbose) {
@@ -97,17 +89,14 @@
class JVMFlagConstraint_uint : public JVMFlagConstraint {
JVMFlagConstraintFunc_uint _constraint;
- const uint* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_uint(const char* name, const uint* ptr,
- JVMFlagConstraintFunc_uint func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_uint(const JVMFlag* flag,
+ JVMFlagConstraintFunc_uint func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- uint value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_uint(), verbose);
}
JVMFlag::Error apply_uint(uint value, bool verbose) {
@@ -117,17 +106,14 @@
class JVMFlagConstraint_uintx : public JVMFlagConstraint {
JVMFlagConstraintFunc_uintx _constraint;
- const uintx* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_uintx(const char* name, const uintx* ptr,
- JVMFlagConstraintFunc_uintx func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_uintx(const JVMFlag* flag,
+ JVMFlagConstraintFunc_uintx func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- uintx value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_uintx(), verbose);
}
JVMFlag::Error apply_uintx(uintx value, bool verbose) {
@@ -137,17 +123,14 @@
class JVMFlagConstraint_uint64_t : public JVMFlagConstraint {
JVMFlagConstraintFunc_uint64_t _constraint;
- const uint64_t* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_uint64_t(const char* name, const uint64_t* ptr,
- JVMFlagConstraintFunc_uint64_t func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_uint64_t(const JVMFlag* flag,
+ JVMFlagConstraintFunc_uint64_t func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- uint64_t value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_uint64_t(), verbose);
}
JVMFlag::Error apply_uint64_t(uint64_t value, bool verbose) {
@@ -157,16 +140,14 @@
class JVMFlagConstraint_size_t : public JVMFlagConstraint {
JVMFlagConstraintFunc_size_t _constraint;
- const size_t* _ptr;
+
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_size_t(const char* name, const size_t* ptr,
- JVMFlagConstraintFunc_size_t func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_size_t(const JVMFlag* flag,
+ JVMFlagConstraintFunc_size_t func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- size_t value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_size_t(), verbose);
}
JVMFlag::Error apply_size_t(size_t value, bool verbose) {
@@ -176,17 +157,14 @@
class JVMFlagConstraint_double : public JVMFlagConstraint {
JVMFlagConstraintFunc_double _constraint;
- const double* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagConstraint_double(const char* name, const double* ptr,
- JVMFlagConstraintFunc_double func,
- ConstraintType type) : JVMFlagConstraint(name, type), _constraint(func), _ptr(ptr) {}
+ JVMFlagConstraint_double(const JVMFlag* flag,
+ JVMFlagConstraintFunc_double func,
+ ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
JVMFlag::Error apply(bool verbose) {
- double value = *_ptr;
- return _constraint(value, verbose);
+ return _constraint(_flag->get_double(), verbose);
}
JVMFlag::Error apply_double(double value, bool verbose) {
@@ -195,49 +173,49 @@
};
// No constraint emitting
-void emit_constraint_no(...) { /* NOP */ }
+void emit_constraint_no(...) { /* NOP */ }
// No constraint emitting if function argument is NOT provided
-void emit_constraint_bool(const char* /*name*/, const bool* /*value*/) { /* NOP */ }
-void emit_constraint_ccstr(const char* /*name*/, const ccstr* /*value*/) { /* NOP */ }
-void emit_constraint_ccstrlist(const char* /*name*/, const ccstrlist* /*value*/) { /* NOP */ }
-void emit_constraint_int(const char* /*name*/, const int* /*value*/) { /* NOP */ }
-void emit_constraint_intx(const char* /*name*/, const intx* /*value*/) { /* NOP */ }
-void emit_constraint_uint(const char* /*name*/, const uint* /*value*/) { /* NOP */ }
-void emit_constraint_uintx(const char* /*name*/, const uintx* /*value*/) { /* NOP */ }
-void emit_constraint_uint64_t(const char* /*name*/, const uint64_t* /*value*/) { /* NOP */ }
-void emit_constraint_size_t(const char* /*name*/, const size_t* /*value*/) { /* NOP */ }
-void emit_constraint_double(const char* /*name*/, const double* /*value*/) { /* NOP */ }
+void emit_constraint_bool(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_ccstr(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_int(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_intx(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_uint(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_uintx(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_uint64_t(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_size_t(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_constraint_double(const JVMFlag* /*flag*/) { /* NOP */ }
// JVMFlagConstraint emitting code functions if function argument is provided
-void emit_constraint_bool(const char* name, const bool* ptr, JVMFlagConstraintFunc_bool func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_bool(name, ptr, func, type));
+void emit_constraint_bool(const JVMFlag* flag, JVMFlagConstraintFunc_bool func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_bool(flag, func, type));
}
-void emit_constraint_int(const char* name, const int* ptr, JVMFlagConstraintFunc_int func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_int(name, ptr, func, type));
+void emit_constraint_int(const JVMFlag* flag, JVMFlagConstraintFunc_int func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_int(flag, func, type));
}
-void emit_constraint_intx(const char* name, const intx* ptr, JVMFlagConstraintFunc_intx func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_intx(name, ptr, func, type));
+void emit_constraint_intx(const JVMFlag* flag, JVMFlagConstraintFunc_intx func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_intx(flag, func, type));
}
-void emit_constraint_uint(const char* name, const uint* ptr, JVMFlagConstraintFunc_uint func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_uint(name, ptr, func, type));
+void emit_constraint_uint(const JVMFlag* flag, JVMFlagConstraintFunc_uint func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_uint(flag, func, type));
}
-void emit_constraint_uintx(const char* name, const uintx* ptr, JVMFlagConstraintFunc_uintx func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_uintx(name, ptr, func, type));
+void emit_constraint_uintx(const JVMFlag* flag, JVMFlagConstraintFunc_uintx func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_uintx(flag, func, type));
}
-void emit_constraint_uint64_t(const char* name, const uint64_t* ptr, JVMFlagConstraintFunc_uint64_t func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_uint64_t(name, ptr, func, type));
+void emit_constraint_uint64_t(const JVMFlag* flag, JVMFlagConstraintFunc_uint64_t func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_uint64_t(flag, func, type));
}
-void emit_constraint_size_t(const char* name, const size_t* ptr, JVMFlagConstraintFunc_size_t func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_size_t(name, ptr, func, type));
+void emit_constraint_size_t(const JVMFlag* flag, JVMFlagConstraintFunc_size_t func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_size_t(flag, func, type));
}
-void emit_constraint_double(const char* name, const double* ptr, JVMFlagConstraintFunc_double func, JVMFlagConstraint::ConstraintType type) {
- JVMFlagConstraintList::add(new JVMFlagConstraint_double(name, ptr, func, type));
+void emit_constraint_double(const JVMFlag* flag, JVMFlagConstraintFunc_double func, JVMFlagConstraint::ConstraintType type) {
+ JVMFlagConstraintList::add(new JVMFlagConstraint_double(flag, func, type));
}
// Generate code to call emit_constraint_xxx function
#define EMIT_CONSTRAINT_START (void)(0
-#define EMIT_CONSTRAINT(type, name) ); emit_constraint_##type(#name, &name
+#define EMIT_CONSTRAINT(type, name) ); emit_constraint_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name))
#define EMIT_CONSTRAINT_NO ); emit_constraint_no(0
#define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
#define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
@@ -296,11 +274,11 @@
EMIT_CONSTRAINT_END
}
-JVMFlagConstraint* JVMFlagConstraintList::find(const char* name) {
+JVMFlagConstraint* JVMFlagConstraintList::find(const JVMFlag* flag) {
JVMFlagConstraint* found = NULL;
for (int i=0; i<length(); i++) {
JVMFlagConstraint* constraint = at(i);
- if (strcmp(constraint->name(), name) == 0) {
+ if (constraint->flag() == flag) {
found = constraint;
break;
}
@@ -308,11 +286,11 @@
return found;
}
-// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
-JVMFlagConstraint* JVMFlagConstraintList::find_if_needs_check(const char* name) {
+// Find constraints and return only if found constraint's type is equal or lower than current validating type.
+JVMFlagConstraint* JVMFlagConstraintList::find_if_needs_check(const JVMFlag* flag) {
JVMFlagConstraint* found = NULL;
- JVMFlagConstraint* constraint = find(name);
- if (constraint && (constraint->type() <= _validating_type)) {
+ JVMFlagConstraint* constraint = find(flag);
+ if (constraint != NULL && (constraint->type() <= _validating_type)) {
found = constraint;
}
return found;
--- a/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -60,15 +60,17 @@
AfterMemoryInit = 2
};
+protected:
+ const JVMFlag* const _flag;
+
private:
- const char* _name;
ConstraintType _validate_type;
public:
// the "name" argument must be a string literal
- JVMFlagConstraint(const char* name, ConstraintType type) { _name=name; _validate_type=type; };
- ~JVMFlagConstraint() {};
- const char* name() const { return _name; }
+ JVMFlagConstraint(const JVMFlag* flag, ConstraintType type) : _flag(flag), _validate_type(type) {}
+ ~JVMFlagConstraint() {}
+ const JVMFlag* flag() const { return _flag; }
ConstraintType type() const { return _validate_type; }
virtual JVMFlag::Error apply(bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; };
virtual JVMFlag::Error apply_bool(bool value, bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; };
@@ -90,8 +92,8 @@
static void init();
static int length() { return (_constraints != NULL) ? _constraints->length() : 0; }
static JVMFlagConstraint* at(int i) { return (_constraints != NULL) ? _constraints->at(i) : NULL; }
- static JVMFlagConstraint* find(const char* name);
- static JVMFlagConstraint* find_if_needs_check(const char* name);
+ static JVMFlagConstraint* find(const JVMFlag* flag);
+ static JVMFlagConstraint* find_if_needs_check(const JVMFlag* flag);
static void add(JVMFlagConstraint* constraint) { _constraints->append(constraint); }
// True if 'AfterErgo' or later constraint functions are validated.
static bool validated_after_ergo() { return _validating_type >= JVMFlagConstraint::AfterErgo; };
--- a/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -33,6 +33,7 @@
#include "runtime/flags/jvmFlagConstraintList.hpp"
#include "runtime/flags/jvmFlagRangeList.hpp"
#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
#include "runtime/os.hpp"
#include "runtime/task.hpp"
#include "utilities/macros.hpp"
@@ -40,15 +41,13 @@
class JVMFlagRange_int : public JVMFlagRange {
int _min;
int _max;
- const int* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_int(const char* name, const int* ptr, int min, int max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_int(const JVMFlag* flag, int min, int max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_int(*_ptr, verbose);
+ return check_int(_flag->get_int(), verbose);
}
JVMFlag::Error check_int(int value, bool verbose = true) {
@@ -71,14 +70,13 @@
class JVMFlagRange_intx : public JVMFlagRange {
intx _min;
intx _max;
- const intx* _ptr;
+
public:
- // the "name" argument must be a string literal
- JVMFlagRange_intx(const char* name, const intx* ptr, intx min, intx max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_intx(const JVMFlag* flag, intx min, intx max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_intx(*_ptr, verbose);
+ return check_intx(_flag->get_intx(), verbose);
}
JVMFlag::Error check_intx(intx value, bool verbose = true) {
@@ -101,15 +99,13 @@
class JVMFlagRange_uint : public JVMFlagRange {
uint _min;
uint _max;
- const uint* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_uint(const char* name, const uint* ptr, uint min, uint max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_uint(const JVMFlag* flag, uint min, uint max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_uint(*_ptr, verbose);
+ return check_uint(_flag->get_uint(), verbose);
}
JVMFlag::Error check_uint(uint value, bool verbose = true) {
@@ -132,15 +128,13 @@
class JVMFlagRange_uintx : public JVMFlagRange {
uintx _min;
uintx _max;
- const uintx* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_uintx(const char* name, const uintx* ptr, uintx min, uintx max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_uintx(const JVMFlag* flag, uintx min, uintx max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_uintx(*_ptr, verbose);
+ return check_uintx(_flag->get_uintx(), verbose);
}
JVMFlag::Error check_uintx(uintx value, bool verbose = true) {
@@ -163,15 +157,13 @@
class JVMFlagRange_uint64_t : public JVMFlagRange {
uint64_t _min;
uint64_t _max;
- const uint64_t* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_uint64_t(const JVMFlag* flag, uint64_t min, uint64_t max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_uint64_t(*_ptr, verbose);
+ return check_uint64_t(_flag->get_uintx(), verbose);
}
JVMFlag::Error check_uint64_t(uint64_t value, bool verbose = true) {
@@ -194,15 +186,13 @@
class JVMFlagRange_size_t : public JVMFlagRange {
size_t _min;
size_t _max;
- const size_t* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_size_t(const char* name, const size_t* ptr, size_t min, size_t max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_size_t(const JVMFlag* flag, size_t min, size_t max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_size_t(*_ptr, verbose);
+ return check_size_t(_flag->get_size_t(), verbose);
}
JVMFlag::Error check_size_t(size_t value, bool verbose = true) {
@@ -225,15 +215,13 @@
class JVMFlagRange_double : public JVMFlagRange {
double _min;
double _max;
- const double* _ptr;
public:
- // the "name" argument must be a string literal
- JVMFlagRange_double(const char* name, const double* ptr, double min, double max)
- : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
+ JVMFlagRange_double(const JVMFlag* flag, double min, double max)
+ : JVMFlagRange(flag), _min(min), _max(max) {}
JVMFlag::Error check(bool verbose = true) {
- return check_double(*_ptr, verbose);
+ return check_double(_flag->get_double(), verbose);
}
JVMFlag::Error check_double(double value, bool verbose = true) {
@@ -257,43 +245,43 @@
void emit_range_no(...) { /* NOP */ }
// No constraint emitting if function argument is NOT provided
-void emit_range_bool(const char* /*name*/, const bool* /*value*/) { /* NOP */ }
-void emit_range_ccstr(const char* /*name*/, const ccstr* /*value*/) { /* NOP */ }
-void emit_range_ccstrlist(const char* /*name*/, const ccstrlist* /*value*/) { /* NOP */ }
-void emit_range_int(const char* /*name*/, const int* /*value*/) { /* NOP */ }
-void emit_range_intx(const char* /*name*/, const intx* /*value*/) { /* NOP */ }
-void emit_range_uint(const char* /*name*/, const uint* /*value*/) { /* NOP */ }
-void emit_range_uintx(const char* /*name*/, const uintx* /*value*/) { /* NOP */ }
-void emit_range_uint64_t(const char* /*name*/, const uint64_t* /*value*/) { /* NOP */ }
-void emit_range_size_t(const char* /*name*/, const size_t* /*value*/) { /* NOP */ }
-void emit_range_double(const char* /*name*/, const double* /*value*/) { /* NOP */ }
+void emit_range_bool(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_ccstr(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_int(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_intx(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_uint(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_uintx(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_uint64_t(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_size_t(const JVMFlag* /*flag*/) { /* NOP */ }
+void emit_range_double(const JVMFlag* /*flag*/) { /* NOP */ }
// JVMFlagRange emitting code functions if range arguments are provided
-void emit_range_int(const char* name, const int* ptr, int min, int max) {
- JVMFlagRangeList::add(new JVMFlagRange_int(name, ptr, min, max));
+void emit_range_int(const JVMFlag* flag, int min, int max) {
+ JVMFlagRangeList::add(new JVMFlagRange_int(flag, min, max));
}
-void emit_range_intx(const char* name, const intx* ptr, intx min, intx max) {
- JVMFlagRangeList::add(new JVMFlagRange_intx(name, ptr, min, max));
+void emit_range_intx(const JVMFlag* flag, intx min, intx max) {
+ JVMFlagRangeList::add(new JVMFlagRange_intx(flag, min, max));
}
-void emit_range_uint(const char* name, const uint* ptr, uint min, uint max) {
- JVMFlagRangeList::add(new JVMFlagRange_uint(name, ptr, min, max));
+void emit_range_uint(const JVMFlag* flag, uint min, uint max) {
+ JVMFlagRangeList::add(new JVMFlagRange_uint(flag, min, max));
}
-void emit_range_uintx(const char* name, const uintx* ptr, uintx min, uintx max) {
- JVMFlagRangeList::add(new JVMFlagRange_uintx(name, ptr, min, max));
+void emit_range_uintx(const JVMFlag* flag, uintx min, uintx max) {
+ JVMFlagRangeList::add(new JVMFlagRange_uintx(flag, min, max));
}
-void emit_range_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max) {
- JVMFlagRangeList::add(new JVMFlagRange_uint64_t(name, ptr, min, max));
+void emit_range_uint64_t(const JVMFlag* flag, uint64_t min, uint64_t max) {
+ JVMFlagRangeList::add(new JVMFlagRange_uint64_t(flag, min, max));
}
-void emit_range_size_t(const char* name, const size_t* ptr, size_t min, size_t max) {
- JVMFlagRangeList::add(new JVMFlagRange_size_t(name, ptr, min, max));
+void emit_range_size_t(const JVMFlag* flag, size_t min, size_t max) {
+ JVMFlagRangeList::add(new JVMFlagRange_size_t(flag, min, max));
}
-void emit_range_double(const char* name, const double* ptr, double min, double max) {
- JVMFlagRangeList::add(new JVMFlagRange_double(name, ptr, min, max));
+void emit_range_double(const JVMFlag* flag, double min, double max) {
+ JVMFlagRangeList::add(new JVMFlagRange_double(flag, min, max));
}
// Generate code to call emit_range_xxx function
#define EMIT_RANGE_START (void)(0
-#define EMIT_RANGE(type, name) ); emit_range_##type(#name, &name
+#define EMIT_RANGE(type, name) ); emit_range_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name))
#define EMIT_RANGE_NO ); emit_range_no(0
#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
@@ -351,11 +339,11 @@
EMIT_RANGE_END
}
-JVMFlagRange* JVMFlagRangeList::find(const char* name) {
+JVMFlagRange* JVMFlagRangeList::find(const JVMFlag* flag) {
JVMFlagRange* found = NULL;
for (int i=0; i<length(); i++) {
JVMFlagRange* range = at(i);
- if (strcmp(range->name(), name) == 0) {
+ if (range->flag() == flag) {
found = range;
break;
}
@@ -363,12 +351,12 @@
return found;
}
-void JVMFlagRangeList::print(outputStream* st, const char* name, RangeStrFunc default_range_str_func) {
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+void JVMFlagRangeList::print(outputStream* st, const JVMFlag* flag, RangeStrFunc default_range_str_func) {
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
range->print(st);
} else {
- JVMFlagConstraint* constraint = JVMFlagConstraintList::find(name);
+ JVMFlagConstraint* constraint = JVMFlagConstraintList::find(flag);
if (constraint != NULL) {
assert(default_range_str_func!=NULL, "default_range_str_func must be provided");
st->print("%s", default_range_str_func());
--- a/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -39,13 +39,14 @@
*/
class JVMFlagRange : public CHeapObj<mtArguments> {
-private:
- const char* _name;
+protected:
+ const JVMFlag* const _flag;
public:
// the "name" argument must be a string literal
- JVMFlagRange(const char* name) { _name=name; }
+ JVMFlagRange(const JVMFlag* flag) : _flag(flag) {}
~JVMFlagRange() {}
- const char* name() { return _name; }
+ const JVMFlag* flag() const { return _flag; }
+ const char* name() const { return _flag->_name; }
virtual JVMFlag::Error check(bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; }
virtual JVMFlag::Error check_int(int value, bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; }
virtual JVMFlag::Error check_intx(intx value, bool verbose = true) { ShouldNotReachHere(); return JVMFlag::ERR_OTHER; }
@@ -63,9 +64,9 @@
static void init();
static int length() { return (_ranges != NULL) ? _ranges->length() : 0; }
static JVMFlagRange* at(int i) { return (_ranges != NULL) ? _ranges->at(i) : NULL; }
- static JVMFlagRange* find(const char* name);
+ static JVMFlagRange* find(const JVMFlag* flag);
static void add(JVMFlagRange* range) { _ranges->append(range); }
- static void print(outputStream* st, const char* name, RangeStrFunc default_range_str_func);
+ static void print(outputStream* st, const JVMFlag* flag, RangeStrFunc default_range_str_func);
// Check the final values of all flags for ranges.
static bool check_ranges();
};
--- a/src/hotspot/share/runtime/globals_extension.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/globals_extension.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -91,6 +91,8 @@
static bool is_cmdline(JVMFlagsEnum flag);
static void setOnCmdLine(JVMFlagsEnum flag);
+
+ static JVMFlag* flag_from_enum(JVMFlagsEnum flag);
};
// Construct set functions for all flags
--- a/src/hotspot/share/runtime/objectMonitor.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -44,8 +44,8 @@
public:
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ };
enum Sorted { PREPEND, APPEND, SORTED };
- ObjectWaiter * volatile _next;
- ObjectWaiter * volatile _prev;
+ ObjectWaiter* volatile _next;
+ ObjectWaiter* volatile _prev;
Thread* _thread;
jlong _notifier_tid;
ParkEvent * _event;
@@ -142,25 +142,35 @@
friend class VMStructs;
JVMCI_ONLY(friend class JVMCIVMStructs;)
- volatile markWord _header; // displaced object header word - mark
- void* volatile _object; // backward object pointer - strong root
+ // The sync code expects the header field to be at offset zero (0).
+ // Enforced by the assert() in header_addr().
+ volatile markWord _header; // displaced object header word - mark
+ void* volatile _object; // backward object pointer - strong root
public:
- ObjectMonitor* FreeNext; // Free list linkage
+ ObjectMonitor* _next_om; // Next ObjectMonitor* linkage
private:
+ // Separate _header and _owner on different cache lines since both can
+ // have busy multi-threaded access. _header and _object are set at
+ // initial inflation and _object doesn't change until deflation so
+ // _object is a good choice to share the cache line with _header.
+ // _next_om shares _header's cache line for pre-monitor list historical
+ // reasons. _next_om only changes if the next ObjectMonitor is deflated.
DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE,
- sizeof(volatile markWord) + sizeof(void * volatile) +
+ sizeof(volatile markWord) + sizeof(void* volatile) +
sizeof(ObjectMonitor *));
protected: // protected for JvmtiRawMonitor
- void * volatile _owner; // pointer to owning thread OR BasicLock
+ void* volatile _owner; // pointer to owning thread OR BasicLock
+ private:
volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor
- volatile intptr_t _recursions; // recursion count, 0 for first entry
- ObjectWaiter * volatile _EntryList; // Threads blocked on entry or reentry.
+ protected: // protected for JvmtiRawMonitor
+ volatile intptr_t _recursions; // recursion count, 0 for first entry
+ ObjectWaiter* volatile _EntryList; // Threads blocked on entry or reentry.
// The list is actually composed of WaitNodes,
// acting as proxies for Threads.
private:
- ObjectWaiter * volatile _cxq; // LL of recently-arrived threads blocked on entry.
- Thread * volatile _succ; // Heir presumptive thread - used for futile wakeup throttling
- Thread * volatile _Responsible;
+ ObjectWaiter* volatile _cxq; // LL of recently-arrived threads blocked on entry.
+ Thread* volatile _succ; // Heir presumptive thread - used for futile wakeup throttling
+ Thread* volatile _Responsible;
volatile int _Spinner; // for exit->spinner handoff optimization
volatile int _SpinDuration;
@@ -169,7 +179,7 @@
// along with other fields to determine if an ObjectMonitor can be
// deflated. See ObjectSynchronizer::deflate_monitor().
protected:
- ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
+ ObjectWaiter* volatile _WaitSet; // LL of threads wait()ing on the monitor
volatile jint _waiters; // number of waiting threads
private:
volatile int _WaitSetLock; // protects Wait Queue - simple spinlock
@@ -202,7 +212,7 @@
void* operator new (size_t size) throw();
void* operator new[] (size_t size) throw();
void operator delete(void* p);
- void operator delete[] (void *p);
+ void operator delete[] (void* p);
// TODO-FIXME: the "offset" routines should return a type of off_t instead of int ...
// ByteSize would also be an appropriate type.
@@ -256,7 +266,7 @@
protected:
// We don't typically expect or want the ctors or dtors to run.
// normal ObjectMonitors are type-stable and immortal.
- ObjectMonitor() { ::memset((void *)this, 0, sizeof(*this)); }
+ ObjectMonitor() { ::memset((void*)this, 0, sizeof(*this)); }
~ObjectMonitor() {
// TODO: Add asserts ...
@@ -305,18 +315,18 @@
void reenter(intptr_t recursions, TRAPS);
private:
- void AddWaiter(ObjectWaiter * waiter);
- void INotify(Thread * Self);
- ObjectWaiter * DequeueWaiter();
- void DequeueSpecificWaiter(ObjectWaiter * waiter);
+ void AddWaiter(ObjectWaiter* waiter);
+ void INotify(Thread* self);
+ ObjectWaiter* DequeueWaiter();
+ void DequeueSpecificWaiter(ObjectWaiter* waiter);
void EnterI(TRAPS);
- void ReenterI(Thread * Self, ObjectWaiter * SelfNode);
- void UnlinkAfterAcquire(Thread * Self, ObjectWaiter * SelfNode);
- int TryLock(Thread * Self);
- int NotRunnable(Thread * Self, Thread * Owner);
- int TrySpin(Thread * Self);
- void ExitEpilog(Thread * Self, ObjectWaiter * Wakee);
- bool ExitSuspendEquivalent(JavaThread * Self);
+ void ReenterI(Thread* self, ObjectWaiter* self_node);
+ void UnlinkAfterAcquire(Thread* self, ObjectWaiter* self_node);
+ int TryLock(Thread* self);
+ int NotRunnable(Thread* self, Thread * Owner);
+ int TrySpin(Thread* self);
+ void ExitEpilog(Thread* self, ObjectWaiter* Wakee);
+ bool ExitSuspendEquivalent(JavaThread* self);
};
#endif // SHARE_RUNTIME_OBJECTMONITOR_HPP
--- a/src/hotspot/share/runtime/os.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/os.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1082,37 +1082,10 @@
}
// Check if addr points into Java heap.
- if (Universe::heap()->is_in(addr)) {
- oop o = oopDesc::oop_or_null(addr);
- if (o != NULL) {
- if ((HeapWord*)o == (HeapWord*)addr) {
- st->print(INTPTR_FORMAT " is an oop: ", p2i(addr));
- } else {
- st->print(INTPTR_FORMAT " is pointing into object: " , p2i(addr));
- }
- ResourceMark rm;
- o->print_on(st);
- return;
- }
- } else if (Universe::heap()->is_in_reserved(addr)) {
- st->print_cr(INTPTR_FORMAT " is an unallocated location in the heap", p2i(addr));
+ if (Universe::heap()->print_location(st, addr)) {
return;
}
- // Compressed oop needs to be decoded first.
-#ifdef _LP64
- if (UseCompressedOops && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) {
- narrowOop narrow_oop = (narrowOop)(uintptr_t)addr;
- oop o = CompressedOops::decode_raw(narrow_oop);
-
- if (oopDesc::is_valid(o)) {
- st->print(UINT32_FORMAT " is a compressed pointer to object: ", narrow_oop);
- o->print_on(st);
- return;
- }
- }
-#endif
-
bool accessible = is_readable_pointer(addr);
// Check if addr is a JNI handle.
--- a/src/hotspot/share/runtime/perfMemory.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/perfMemory.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -25,6 +25,7 @@
#ifndef SHARE_RUNTIME_PERFMEMORY_HPP
#define SHARE_RUNTIME_PERFMEMORY_HPP
+#include "runtime/globals.hpp"
#include "utilities/exceptions.hpp"
/*
--- a/src/hotspot/share/runtime/serviceThread.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/serviceThread.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -128,8 +128,8 @@
(symboltable_work = SymbolTable::has_work()) |
(resolved_method_table_work = ResolvedMethodTable::has_work()) |
(protection_domain_table_work = SystemDictionary::pd_cache_table()->has_work()) |
- (oopstorage_work = OopStorage::has_cleanup_work_and_reset()))
- == 0) {
+ (oopstorage_work = OopStorage::has_cleanup_work_and_reset())
+ ) == 0) {
// Wait until notified that there is some work to do.
ml.wait();
}
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -2091,12 +2091,7 @@
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(THREAD, obj);
- if (UseBiasedLocking) {
- // Retry fast entry if bias is revoked to avoid unnecessary inflation
- ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
- } else {
- ObjectSynchronizer::slow_enter(h_obj, lock, CHECK);
- }
+ ObjectSynchronizer::enter(h_obj, lock, CHECK);
assert(!HAS_PENDING_EXCEPTION, "Should have no exception here");
JRT_BLOCK_END
JRT_END
@@ -2127,7 +2122,7 @@
{
// Exit must be non-blocking, and therefore no exceptions can be thrown.
EXCEPTION_MARK;
- ObjectSynchronizer::slow_exit(obj, lock, THREAD);
+ ObjectSynchronizer::exit(obj, lock, THREAD);
}
#ifdef MIGHT_HAVE_PENDING
--- a/src/hotspot/share/runtime/sweeper.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/sweeper.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -699,22 +699,9 @@
// Code cache state change is tracked in make_zombie()
cm->make_zombie();
SWEEP(cm);
- // The nmethod may have been locked by JVMTI after being made zombie (see
- // JvmtiDeferredEvent::compiled_method_unload_event()). If so, we cannot
- // flush the osr nmethod directly but have to wait for a later sweeper cycle.
- if (cm->is_osr_method() && !cm->is_locked_by_vm()) {
- // No inline caches will ever point to osr methods, so we can just remove it.
- // Make sure that we unregistered the nmethod with the heap and flushed all
- // dependencies before removing the nmethod (done in make_zombie()).
- assert(cm->is_zombie(), "nmethod must be unregistered");
- cm->flush();
- assert(result == None, "sanity");
- result = Flushed;
- } else {
- assert(result == None, "sanity");
- result = MadeZombie;
- assert(cm->is_zombie(), "nmethod must be zombie");
- }
+ assert(result == None, "sanity");
+ result = MadeZombie;
+ assert(cm->is_zombie(), "nmethod must be zombie");
} else {
// Still alive, clean up its inline caches
cm->cleanup_inline_caches(false);
@@ -722,20 +709,12 @@
}
} else if (cm->is_unloaded()) {
// Code is unloaded, so there are no activations on the stack.
- // Convert the nmethod to zombie or flush it directly in the OSR case.
- if (cm->is_osr_method()) {
- SWEEP(cm);
- // No inline caches will ever point to osr methods, so we can just remove it
- cm->flush();
- assert(result == None, "sanity");
- result = Flushed;
- } else {
- // Code cache state change is tracked in make_zombie()
- cm->make_zombie();
- SWEEP(cm);
- assert(result == None, "sanity");
- result = MadeZombie;
- }
+ // Convert the nmethod to zombie.
+ // Code cache state change is tracked in make_zombie()
+ cm->make_zombie();
+ SWEEP(cm);
+ assert(result == None, "sanity");
+ result = MadeZombie;
} else {
if (cm->is_nmethod()) {
possibly_flush((nmethod*)cm);
--- a/src/hotspot/share/runtime/synchronizer.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/synchronizer.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -117,18 +117,18 @@
static volatile intptr_t gInflationLocks[NINFLATIONLOCKS];
// global list of blocks of monitors
-PaddedEnd<ObjectMonitor> * volatile ObjectSynchronizer::gBlockList = NULL;
-// global monitor free list
-ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL;
-// global monitor in-use list, for moribund threads,
-// monitors they inflated need to be scanned for deflation
-ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL;
-// count of entries in gOmInUseList
-int ObjectSynchronizer::gOmInUseCount = 0;
+PaddedObjectMonitor* volatile ObjectSynchronizer::g_block_list = NULL;
+// Global ObjectMonitor free list. Newly allocated and deflated
+// ObjectMonitors are prepended here.
+ObjectMonitor* volatile ObjectSynchronizer::g_free_list = NULL;
+// Global ObjectMonitor in-use list. When a JavaThread is exiting,
+// ObjectMonitors on its per-thread in-use list are prepended here.
+ObjectMonitor* volatile ObjectSynchronizer::g_om_in_use_list = NULL;
+int ObjectSynchronizer::g_om_in_use_count = 0; // # on g_om_in_use_list
-static volatile intptr_t gListLock = 0; // protects global monitor lists
-static volatile int gMonitorFreeCount = 0; // # on gFreeList
-static volatile int gMonitorPopulation = 0; // # Extant -- in circulation
+static volatile intptr_t gListLock = 0; // protects global monitor lists
+static volatile int g_om_free_count = 0; // # on g_free_list
+static volatile int g_om_population = 0; // # Extant -- in circulation
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
@@ -155,7 +155,7 @@
// the monitorexit operation. In that case the JIT could fuse the operations
// into a single notifyAndExit() runtime primitive.
-bool ObjectSynchronizer::quick_notify(oopDesc * obj, Thread * self, bool all) {
+bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(self->is_Java_thread(), "invariant");
assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
@@ -170,7 +170,7 @@
}
if (mark.has_monitor()) {
- ObjectMonitor * const mon = mark.monitor();
+ ObjectMonitor* const mon = mark.monitor();
assert(oopDesc::equals((oop) mon->object(), obj), "invariant");
if (mon->owner() != self) return false; // slow-path for IMS exception
@@ -183,12 +183,12 @@
} else {
DTRACE_MONITOR_PROBE(notify, mon, obj, self);
}
- int tally = 0;
+ int free_count = 0;
do {
mon->INotify(self);
- ++tally;
+ ++free_count;
} while (mon->first_waiter() != NULL && all);
- OM_PERFDATA_OP(Notifications, inc(tally));
+ OM_PERFDATA_OP(Notifications, inc(free_count));
}
return true;
}
@@ -204,26 +204,26 @@
// Note that we can't safely call AsyncPrintJavaStack() from within
// quick_enter() as our thread state remains _in_Java.
-bool ObjectSynchronizer::quick_enter(oop obj, Thread * Self,
+bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
BasicLock * lock) {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
- assert(Self->is_Java_thread(), "invariant");
- assert(((JavaThread *) Self)->thread_state() == _thread_in_Java, "invariant");
+ assert(self->is_Java_thread(), "invariant");
+ assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
NoSafepointVerifier nsv;
if (obj == NULL) return false; // Need to throw NPE
const markWord mark = obj->mark();
if (mark.has_monitor()) {
- ObjectMonitor * const m = mark.monitor();
+ ObjectMonitor* const m = mark.monitor();
assert(oopDesc::equals((oop) m->object(), obj), "invariant");
- Thread * const owner = (Thread *) m->_owner;
+ Thread* const owner = (Thread *) m->_owner;
// Lock contention and Transactional Lock Elision (TLE) diagnostics
// and observability
// Case: light contention possibly amenable to TLE
// Case: TLE inimical operations such as nested/recursive synchronization
- if (owner == Self) {
+ if (owner == self) {
m->_recursions++;
return true;
}
@@ -240,7 +240,7 @@
// and last are the inflated Java Monitor (ObjectMonitor) checks.
lock->set_displaced_header(markWord::unused_mark());
- if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
+ if (owner == NULL && Atomic::replace_if_null(self, &(m->_owner))) {
assert(m->_recursions == 0, "invariant");
return true;
}
@@ -257,85 +257,20 @@
}
// -----------------------------------------------------------------------------
-// Fast Monitor Enter/Exit
-// This the fast monitor enter. The interpreter and compiler use
-// some assembly copies of this code. Make sure update those code
-// if the following function is changed. The implementation is
-// extremely sensitive to race condition. Be careful.
+// Monitor Enter/Exit
+// The interpreter and compiler assembly code tries to lock using the fast path
+// of this algorithm. Make sure to update that code if the following function is
+// changed. The implementation is extremely sensitive to race condition. Be careful.
-void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,
- bool attempt_rebias, TRAPS) {
+void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
if (UseBiasedLocking) {
if (!SafepointSynchronize::is_at_safepoint()) {
- BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
- if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
- return;
- }
+ BiasedLocking::revoke(obj, THREAD);
} else {
- assert(!attempt_rebias, "can not rebias toward VM thread");
BiasedLocking::revoke_at_safepoint(obj);
}
- assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
- }
-
- slow_enter(obj, lock, THREAD);
-}
-
-void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
- markWord mark = object->mark();
- // We cannot check for Biased Locking if we are racing an inflation.
- assert(mark == markWord::INFLATING() ||
- !mark.has_bias_pattern(), "should not see bias pattern here");
-
- markWord dhw = lock->displaced_header();
- if (dhw.value() == 0) {
- // If the displaced header is NULL, then this exit matches up with
- // a recursive enter. No real work to do here except for diagnostics.
-#ifndef PRODUCT
- if (mark != markWord::INFLATING()) {
- // Only do diagnostics if we are not racing an inflation. Simply
- // exiting a recursive enter of a Java Monitor that is being
- // inflated is safe; see the has_monitor() comment below.
- assert(!mark.is_neutral(), "invariant");
- assert(!mark.has_locker() ||
- THREAD->is_lock_owned((address)mark.locker()), "invariant");
- if (mark.has_monitor()) {
- // The BasicLock's displaced_header is marked as a recursive
- // enter and we have an inflated Java Monitor (ObjectMonitor).
- // This is a special case where the Java Monitor was inflated
- // after this thread entered the stack-lock recursively. When a
- // Java Monitor is inflated, we cannot safely walk the Java
- // Monitor owner's stack and update the BasicLocks because a
- // Java Monitor can be asynchronously inflated by a thread that
- // does not own the Java Monitor.
- ObjectMonitor * m = mark.monitor();
- assert(((oop)(m->object()))->mark() == mark, "invariant");
- assert(m->is_entered(THREAD), "invariant");
- }
- }
-#endif
- return;
- }
-
- if (mark == markWord::from_pointer(lock)) {
- // If the object is stack-locked by the current thread, try to
- // swing the displaced header from the BasicLock back to the mark.
- assert(dhw.is_neutral(), "invariant");
- if (object->cas_set_mark(dhw, mark) == mark) {
- return;
- }
}
- // We have to take the slow-path of possible inflation and then exit.
- inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD);
-}
-
-// -----------------------------------------------------------------------------
-// Interpreter/Compiler Slow Case
-// This routine is used to handle interpreter/compiler slow case
-// We don't need to use fast path here, because it must have been
-// failed in the interpreter/compiler code.
-void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
markWord mark = obj->mark();
assert(!mark.has_bias_pattern(), "should not see bias pattern here");
@@ -363,12 +298,53 @@
inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);
}
-// This routine is used to handle interpreter/compiler slow case
-// We don't need to use fast path here, because it must have
-// failed in the interpreter/compiler code. Simply use the heavy
-// weight monitor should be ok, unless someone find otherwise.
-void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
- fast_exit(object, lock, THREAD);
+void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
+ markWord mark = object->mark();
+ // We cannot check for Biased Locking if we are racing an inflation.
+ assert(mark == markWord::INFLATING() ||
+ !mark.has_bias_pattern(), "should not see bias pattern here");
+
+ markWord dhw = lock->displaced_header();
+ if (dhw.value() == 0) {
+ // If the displaced header is NULL, then this exit matches up with
+ // a recursive enter. No real work to do here except for diagnostics.
+#ifndef PRODUCT
+ if (mark != markWord::INFLATING()) {
+ // Only do diagnostics if we are not racing an inflation. Simply
+ // exiting a recursive enter of a Java Monitor that is being
+ // inflated is safe; see the has_monitor() comment below.
+ assert(!mark.is_neutral(), "invariant");
+ assert(!mark.has_locker() ||
+ THREAD->is_lock_owned((address)mark.locker()), "invariant");
+ if (mark.has_monitor()) {
+ // The BasicLock's displaced_header is marked as a recursive
+ // enter and we have an inflated Java Monitor (ObjectMonitor).
+ // This is a special case where the Java Monitor was inflated
+ // after this thread entered the stack-lock recursively. When a
+ // Java Monitor is inflated, we cannot safely walk the Java
+ // Monitor owner's stack and update the BasicLocks because a
+ // Java Monitor can be asynchronously inflated by a thread that
+ // does not own the Java Monitor.
+ ObjectMonitor* m = mark.monitor();
+ assert(((oop)(m->object()))->mark() == mark, "invariant");
+ assert(m->is_entered(THREAD), "invariant");
+ }
+ }
+#endif
+ return;
+ }
+
+ if (mark == markWord::from_pointer(lock)) {
+ // If the object is stack-locked by the current thread, try to
+ // swing the displaced header from the BasicLock back to the mark.
+ assert(dhw.is_neutral(), "invariant");
+ if (object->cas_set_mark(dhw, mark) == mark) {
+ return;
+ }
+ }
+
+ // We have to take the slow-path of possible inflation and then exit.
+ inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD);
}
// -----------------------------------------------------------------------------
@@ -385,7 +361,7 @@
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -397,7 +373,7 @@
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -411,7 +387,7 @@
void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
// the current locking is from JNI instead of Java code
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
THREAD->set_current_pending_monitor_is_from_java(false);
@@ -423,7 +399,7 @@
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
if (UseBiasedLocking) {
Handle h_obj(THREAD, obj);
- BiasedLocking::revoke_and_rebias(h_obj, false, THREAD);
+ BiasedLocking::revoke(h_obj, THREAD);
obj = h_obj();
}
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
@@ -440,20 +416,20 @@
// -----------------------------------------------------------------------------
// Internal VM locks on java objects
// standard constructor, allows locking failures
-ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool doLock) {
- _dolock = doLock;
+ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool do_lock) {
+ _dolock = do_lock;
_thread = thread;
_thread->check_for_valid_safepoint_state(false);
_obj = obj;
if (_dolock) {
- ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);
+ ObjectSynchronizer::enter(_obj, &_lock, _thread);
}
}
ObjectLocker::~ObjectLocker() {
if (_dolock) {
- ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
+ ObjectSynchronizer::exit(_obj(), &_lock, _thread);
}
}
@@ -463,7 +439,7 @@
// NOTE: must use heavy weight monitor to handle wait()
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
@@ -481,9 +457,9 @@
return dtrace_waited_probe(monitor, obj, THREAD);
}
-void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
+void ObjectSynchronizer::wait_uninterruptibly(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
@@ -494,7 +470,7 @@
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -508,7 +484,7 @@
// NOTE: see comment of notify()
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+ BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -544,11 +520,11 @@
char _pad_prefix[DEFAULT_CACHE_LINE_SIZE];
// These are highly shared mostly-read variables.
// To avoid false-sharing they need to be the sole occupants of a cache line.
- volatile int stwRandom;
- volatile int stwCycle;
+ volatile int stw_random;
+ volatile int stw_cycle;
DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile int) * 2);
// Hot RW variable -- Sequester to avoid false-sharing
- volatile int hcSequence;
+ volatile int hc_sequence;
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile int));
};
@@ -556,7 +532,7 @@
static int MonitorScavengeThreshold = 1000000;
static volatile int ForceMonitorScavenge = 0; // Scavenge required and pending
-static markWord ReadStableMark(oop obj) {
+static markWord read_stable_mark(oop obj) {
markWord mark = obj->mark();
if (!mark.is_being_inflated()) {
return mark; // normal fast-path return
@@ -570,7 +546,7 @@
}
// The object is being inflated by some other thread.
- // The caller of ReadStableMark() must wait for inflation to complete.
+ // The caller of read_stable_mark() must wait for inflation to complete.
// Avoid live-lock
// TODO: consider calling SafepointSynchronize::do_call_back() while
// spinning to see if there's a safepoint pending. If so, immediately
@@ -606,7 +582,7 @@
Thread::muxAcquire(gInflationLocks + ix, "gInflationLock");
while (obj->mark() == markWord::INFLATING()) {
// Beware: NakedYield() is advisory and has almost no effect on some platforms
- // so we periodically call Self->_ParkEvent->park(1).
+ // so we periodically call self->_ParkEvent->park(1).
// We use a mixed spin/yield/block mechanism.
if ((YieldThenBlock++) >= 16) {
Thread::current()->_ParkEvent->park(1);
@@ -625,21 +601,21 @@
// hashCode() generation :
//
// Possibilities:
-// * MD5Digest of {obj,stwRandom}
-// * CRC32 of {obj,stwRandom} or any linear-feedback shift register function.
+// * MD5Digest of {obj,stw_random}
+// * CRC32 of {obj,stw_random} or any linear-feedback shift register function.
// * A DES- or AES-style SBox[] mechanism
// * One of the Phi-based schemes, such as:
// 2654435761 = 2^32 * Phi (golden ratio)
-// HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ;
+// HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stw_random ;
// * A variation of Marsaglia's shift-xor RNG scheme.
-// * (obj ^ stwRandom) is appealing, but can result
+// * (obj ^ stw_random) is appealing, but can result
// in undesirable regularity in the hashCode values of adjacent objects
// (objects allocated back-to-back, in particular). This could potentially
// result in hashtable collisions and reduced hashtable efficiency.
// There are simple ways to "diffuse" the middle address bits over the
// generated hashCode values:
-static inline intptr_t get_next_hash(Thread * Self, oop obj) {
+static inline intptr_t get_next_hash(Thread* self, oop obj) {
intptr_t value = 0;
if (hashCode == 0) {
// This form uses global Park-Miller RNG.
@@ -650,26 +626,26 @@
// This variation has the property of being stable (idempotent)
// between STW operations. This can be useful in some of the 1-0
// synchronization schemes.
- intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3;
- value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom;
+ intptr_t addr_bits = cast_from_oop<intptr_t>(obj) >> 3;
+ value = addr_bits ^ (addr_bits >> 5) ^ GVars.stw_random;
} else if (hashCode == 2) {
value = 1; // for sensitivity testing
} else if (hashCode == 3) {
- value = ++GVars.hcSequence;
+ value = ++GVars.hc_sequence;
} else if (hashCode == 4) {
value = cast_from_oop<intptr_t>(obj);
} else {
// Marsaglia's xor-shift scheme with thread-specific state
// This is probably the best overall implementation -- we'll
// likely make this the default in future releases.
- unsigned t = Self->_hashStateX;
+ unsigned t = self->_hashStateX;
t ^= (t << 11);
- Self->_hashStateX = Self->_hashStateY;
- Self->_hashStateY = Self->_hashStateZ;
- Self->_hashStateZ = Self->_hashStateW;
- unsigned v = Self->_hashStateW;
+ self->_hashStateX = self->_hashStateY;
+ self->_hashStateY = self->_hashStateZ;
+ self->_hashStateZ = self->_hashStateW;
+ unsigned v = self->_hashStateW;
v = (v ^ (v >> 19)) ^ (t ^ (t >> 8));
- Self->_hashStateW = v;
+ self->_hashStateW = v;
value = v;
}
@@ -679,7 +655,7 @@
return value;
}
-intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
+intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
if (UseBiasedLocking) {
// NOTE: many places throughout the JVM do not expect a safepoint
// to be taken here, in particular most operations on perm gen
@@ -690,12 +666,12 @@
// thread-local storage.
if (obj->mark().has_bias_pattern()) {
// Handle for oop obj in case of STW safepoint
- Handle hobj(Self, obj);
+ Handle hobj(self, obj);
// Relaxing assertion for bug 6320749.
assert(Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(),
"biases should not be seen by VM thread here");
- BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
+ BiasedLocking::revoke(hobj, JavaThread::current());
obj = hobj();
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -706,14 +682,14 @@
assert(Universe::verify_in_progress() || DumpSharedSpaces ||
!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(Universe::verify_in_progress() || DumpSharedSpaces ||
- Self->is_Java_thread() , "invariant");
+ self->is_Java_thread() , "invariant");
assert(Universe::verify_in_progress() || DumpSharedSpaces ||
- ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant");
+ ((JavaThread *)self)->thread_state() != _thread_blocked, "invariant");
ObjectMonitor* monitor = NULL;
markWord temp, test;
intptr_t hash;
- markWord mark = ReadStableMark(obj);
+ markWord mark = read_stable_mark(obj);
// object should remain ineligible for biased locking
assert(!mark.has_bias_pattern(), "invariant");
@@ -723,7 +699,7 @@
if (hash != 0) { // if it has hash, just return it
return hash;
}
- hash = get_next_hash(Self, obj); // allocate a new hash code
+ hash = get_next_hash(self, obj); // allocate a new hash code
temp = mark.copy_set_hash(hash); // merge the hash code into header
// use (machine word version) atomic operation to install the hash
test = obj->cas_set_mark(temp, mark);
@@ -742,7 +718,7 @@
return hash;
}
// Skip to the following code to reduce code size
- } else if (Self->is_lock_owned((address)mark.locker())) {
+ } else if (self->is_lock_owned((address)mark.locker())) {
temp = mark.displaced_mark_helper(); // this is a lightweight monitor owned
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
hash = temp.hash(); // by current thread, check if the displaced
@@ -760,21 +736,22 @@
}
// Inflate the monitor to set hash code
- monitor = inflate(Self, obj, inflate_cause_hash_code);
+ monitor = inflate(self, obj, inflate_cause_hash_code);
// Load displaced header and check it has hash code
mark = monitor->header();
assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
hash = mark.hash();
if (hash == 0) {
- hash = get_next_hash(Self, obj);
+ hash = get_next_hash(self, obj);
temp = mark.copy_set_hash(hash); // merge hash code into header
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
uintptr_t v = Atomic::cmpxchg(temp.value(), (volatile uintptr_t*)monitor->header_addr(), mark.value());
test = markWord(v);
if (test != mark) {
- // The only update to the ObjectMonitor's header/dmw field
- // is to merge in the hash code. If someone adds a new usage
- // of the header/dmw field, please update this code.
+ // The only non-deflation update to the ObjectMonitor's
+ // header/dmw field is to merge in the hash code. If someone
+ // adds a new usage of the header/dmw field, please update
+ // this code.
hash = test.hash();
assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value());
assert(hash != 0, "Trivial unexpected object/monitor header usage.");
@@ -794,14 +771,14 @@
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
Handle h_obj) {
if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(h_obj, false, thread);
+ BiasedLocking::revoke(h_obj, thread);
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
assert(thread == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
- markWord mark = ReadStableMark(obj);
+ markWord mark = read_stable_mark(obj);
// Uncontended case, header points to stack
if (mark.has_locker()) {
@@ -833,14 +810,14 @@
if (UseBiasedLocking && h_obj()->mark().has_bias_pattern()) {
// CASE: biased
- BiasedLocking::revoke_and_rebias(h_obj, false, self);
+ BiasedLocking::revoke(h_obj, self);
assert(!h_obj->mark().has_bias_pattern(),
"biases should be revoked by now");
}
assert(self == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
- markWord mark = ReadStableMark(obj);
+ markWord mark = read_stable_mark(obj);
// CASE: stack-locked. Mark points to a BasicLock on the owner's stack.
if (mark.has_locker()) {
@@ -852,7 +829,7 @@
// The Object:ObjectMonitor relationship is stable as long as we're
// not at a safepoint.
if (mark.has_monitor()) {
- void * owner = mark.monitor()->_owner;
+ void* owner = mark.monitor()->_owner;
if (owner == NULL) return owner_none;
return (owner == self ||
self->is_lock_owned((address)owner)) ? owner_self : owner_other;
@@ -869,7 +846,7 @@
if (SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke_at_safepoint(h_obj);
} else {
- BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
+ BiasedLocking::revoke(h_obj, JavaThread::current());
}
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
@@ -877,7 +854,7 @@
oop obj = h_obj();
address owner = NULL;
- markWord mark = ReadStableMark(obj);
+ markWord mark = read_stable_mark(obj);
// Uncontended case, header points to stack
if (mark.has_locker()) {
@@ -907,34 +884,27 @@
// Visitors ...
void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
- PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
+ PaddedObjectMonitor* block = OrderAccess::load_acquire(&g_block_list);
while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header");
for (int i = _BLOCKSIZE - 1; i > 0; i--) {
ObjectMonitor* mid = (ObjectMonitor *)(block + i);
oop object = (oop)mid->object();
if (object != NULL) {
+ // Only process with closure if the object is set.
closure->do_monitor(mid);
}
}
- block = (PaddedEnd<ObjectMonitor> *)block->FreeNext;
+ block = (PaddedObjectMonitor*)block->_next_om;
}
}
-// Get the next block in the block list.
-static inline PaddedEnd<ObjectMonitor>* next(PaddedEnd<ObjectMonitor>* block) {
- assert(block->object() == CHAINMARKER, "must be a block header");
- block = (PaddedEnd<ObjectMonitor>*) block->FreeNext;
- assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
- return block;
-}
-
static bool monitors_used_above_threshold() {
- if (gMonitorPopulation == 0) {
+ if (g_om_population == 0) {
return false;
}
- int monitors_used = gMonitorPopulation - gMonitorFreeCount;
- int monitor_usage = (monitors_used * 100LL) / gMonitorPopulation;
+ int monitors_used = g_om_population - g_om_free_count;
+ int monitor_usage = (monitors_used * 100LL) / g_om_population;
return monitor_usage > MonitorUsedDeflationThreshold;
}
@@ -953,18 +923,18 @@
void ObjectSynchronizer::global_used_oops_do(OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- list_oops_do(gOmInUseList, f);
+ list_oops_do(g_om_in_use_list, f);
}
void ObjectSynchronizer::thread_local_used_oops_do(Thread* thread, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- list_oops_do(thread->omInUseList, f);
+ list_oops_do(thread->om_in_use_list, f);
}
void ObjectSynchronizer::list_oops_do(ObjectMonitor* list, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
ObjectMonitor* mid;
- for (mid = list; mid != NULL; mid = mid->FreeNext) {
+ for (mid = list; mid != NULL; mid = mid->_next_om) {
if (mid->object() != NULL) {
f->do_oop((oop*)mid->object_addr());
}
@@ -975,10 +945,10 @@
// -----------------------------------------------------------------------------
// ObjectMonitor Lifecycle
// -----------------------
-// Inflation unlinks monitors from the global gFreeList and
+// Inflation unlinks monitors from the global g_free_list and
// associates them with objects. Deflation -- which occurs at
// STW-time -- disassociates idle monitors from objects. Such
-// scavenged monitors are returned to the gFreeList.
+// scavenged monitors are returned to the g_free_list.
//
// The global list is protected by gListLock. All the critical sections
// are short and operate in constant-time.
@@ -987,13 +957,15 @@
//
// Lifecycle:
// -- unassigned and on the global free list
-// -- unassigned and on a thread's private omFreeList
+// -- unassigned and on a thread's private om_free_list
// -- assigned to an object. The object is inflated and the mark refers
// to the objectmonitor.
// Constraining monitor pool growth via MonitorBound ...
//
+// If MonitorBound is not set (<= 0), MonitorBound checks are disabled.
+//
// The monitor pool is grow-only. We scavenge at STW safepoint-time, but the
// the rate of scavenging is driven primarily by GC. As such, we can find
// an inordinate number of monitors in circulation.
@@ -1007,8 +979,14 @@
// See also: GuaranteedSafepointInterval
//
// The current implementation uses asynchronous VM operations.
+//
+// If MonitorBound is set, the boundry applies to
+// (g_om_population - g_om_free_count)
+// i.e., if there are not enough ObjectMonitors on the global free list,
+// then a safepoint deflation is induced. Picking a good MonitorBound value
+// is non-trivial.
-static void InduceScavenge(Thread * Self, const char * Whence) {
+static void InduceScavenge(Thread* self, const char * Whence) {
// Induce STW safepoint to trim monitors
// Ultimately, this results in a call to deflate_idle_monitors() in the near future.
// More precisely, trigger an asynchronous STW safepoint as the number
@@ -1024,86 +1002,86 @@
}
}
-ObjectMonitor* ObjectSynchronizer::omAlloc(Thread * Self) {
+ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
// A large MAXPRIVATE value reduces both list lock contention
// and list coherency traffic, but also tends to increase the
- // number of objectMonitors in circulation as well as the STW
+ // number of ObjectMonitors in circulation as well as the STW
// scavenge costs. As usual, we lean toward time in space-time
// tradeoffs.
const int MAXPRIVATE = 1024;
stringStream ss;
for (;;) {
- ObjectMonitor * m;
+ ObjectMonitor* m;
- // 1: try to allocate from the thread's local omFreeList.
+ // 1: try to allocate from the thread's local om_free_list.
// Threads will attempt to allocate first from their local list, then
// from the global list, and only after those attempts fail will the thread
// attempt to instantiate new monitors. Thread-local free lists take
// heat off the gListLock and improve allocation latency, as well as reducing
// coherency traffic on the shared global list.
- m = Self->omFreeList;
+ m = self->om_free_list;
if (m != NULL) {
- Self->omFreeList = m->FreeNext;
- Self->omFreeCount--;
+ self->om_free_list = m->_next_om;
+ self->om_free_count--;
guarantee(m->object() == NULL, "invariant");
- m->FreeNext = Self->omInUseList;
- Self->omInUseList = m;
- Self->omInUseCount++;
+ m->_next_om = self->om_in_use_list;
+ self->om_in_use_list = m;
+ self->om_in_use_count++;
return m;
}
- // 2: try to allocate from the global gFreeList
+ // 2: try to allocate from the global g_free_list
// CONSIDER: use muxTry() instead of muxAcquire().
// If the muxTry() fails then drop immediately into case 3.
// If we're using thread-local free lists then try
// to reprovision the caller's free list.
- if (gFreeList != NULL) {
- // Reprovision the thread's omFreeList.
+ if (g_free_list != NULL) {
+ // Reprovision the thread's om_free_list.
// Use bulk transfers to reduce the allocation rate and heat
// on various locks.
- Thread::muxAcquire(&gListLock, "omAlloc(1)");
- for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) {
- gMonitorFreeCount--;
- ObjectMonitor * take = gFreeList;
- gFreeList = take->FreeNext;
+ Thread::muxAcquire(&gListLock, "om_alloc(1)");
+ for (int i = self->om_free_provision; --i >= 0 && g_free_list != NULL;) {
+ g_om_free_count--;
+ ObjectMonitor* take = g_free_list;
+ g_free_list = take->_next_om;
guarantee(take->object() == NULL, "invariant");
take->Recycle();
- omRelease(Self, take, false);
+ om_release(self, take, false);
}
Thread::muxRelease(&gListLock);
- Self->omFreeProvision += 1 + (Self->omFreeProvision/2);
- if (Self->omFreeProvision > MAXPRIVATE) Self->omFreeProvision = MAXPRIVATE;
+ self->om_free_provision += 1 + (self->om_free_provision/2);
+ if (self->om_free_provision > MAXPRIVATE) self->om_free_provision = MAXPRIVATE;
const int mx = MonitorBound;
- if (mx > 0 && (gMonitorPopulation-gMonitorFreeCount) > mx) {
- // We can't safely induce a STW safepoint from omAlloc() as our thread
+ if (mx > 0 && (g_om_population-g_om_free_count) > mx) {
+ // Not enough ObjectMonitors on the global free list.
+ // We can't safely induce a STW safepoint from om_alloc() as our thread
// state may not be appropriate for such activities and callers may hold
// naked oops, so instead we defer the action.
- InduceScavenge(Self, "omAlloc");
+ InduceScavenge(self, "om_alloc");
}
continue;
}
// 3: allocate a block of new ObjectMonitors
// Both the local and global free lists are empty -- resort to malloc().
- // In the current implementation objectMonitors are TSM - immortal.
+ // In the current implementation ObjectMonitors are TSM - immortal.
// Ideally, we'd write "new ObjectMonitor[_BLOCKSIZE], but we want
// each ObjectMonitor to start at the beginning of a cache line,
// so we use align_up().
// A better solution would be to use C++ placement-new.
// BEWARE: As it stands currently, we don't run the ctors!
assert(_BLOCKSIZE > 1, "invariant");
- size_t neededsize = sizeof(PaddedEnd<ObjectMonitor>) * _BLOCKSIZE;
- PaddedEnd<ObjectMonitor> * temp;
+ size_t neededsize = sizeof(PaddedObjectMonitor) * _BLOCKSIZE;
+ PaddedObjectMonitor* temp;
size_t aligned_size = neededsize + (DEFAULT_CACHE_LINE_SIZE - 1);
- void* real_malloc_addr = (void *)NEW_C_HEAP_ARRAY(char, aligned_size,
- mtInternal);
- temp = (PaddedEnd<ObjectMonitor> *)
- align_up(real_malloc_addr, DEFAULT_CACHE_LINE_SIZE);
+ void* real_malloc_addr = (void*)NEW_C_HEAP_ARRAY(char, aligned_size,
+ mtInternal);
+ temp = (PaddedObjectMonitor*)align_up(real_malloc_addr, DEFAULT_CACHE_LINE_SIZE);
// NOTE: (almost) no way to recover if allocation failed.
// We might be able to induce a STW safepoint and scavenge enough
- // objectMonitors to permit progress.
+ // ObjectMonitors to permit progress.
if (temp == NULL) {
vm_exit_out_of_memory(neededsize, OOM_MALLOC_ERROR,
"Allocate ObjectMonitors");
@@ -1114,16 +1092,16 @@
// initialize the linked list, each monitor points to its next
// forming the single linked free list, the very first monitor
// will points to next block, which forms the block list.
- // The trick of using the 1st element in the block as gBlockList
+ // The trick of using the 1st element in the block as g_block_list
// linkage should be reconsidered. A better implementation would
// look like: class Block { Block * next; int N; ObjectMonitor Body [N] ; }
for (int i = 1; i < _BLOCKSIZE; i++) {
- temp[i].FreeNext = (ObjectMonitor *)&temp[i+1];
+ temp[i]._next_om = (ObjectMonitor *)&temp[i+1];
}
// terminate the last monitor as the end of list
- temp[_BLOCKSIZE - 1].FreeNext = NULL;
+ temp[_BLOCKSIZE - 1]._next_om = NULL;
// Element [0] is reserved for global list linkage
temp[0].set_object(CHAINMARKER);
@@ -1132,160 +1110,155 @@
// block in hand. This avoids some lock traffic and redundant
// list activity.
- // Acquire the gListLock to manipulate gBlockList and gFreeList.
+ // Acquire the gListLock to manipulate g_block_list and g_free_list.
// An Oyama-Taura-Yonezawa scheme might be more efficient.
- Thread::muxAcquire(&gListLock, "omAlloc(2)");
- gMonitorPopulation += _BLOCKSIZE-1;
- gMonitorFreeCount += _BLOCKSIZE-1;
+ Thread::muxAcquire(&gListLock, "om_alloc(2)");
+ g_om_population += _BLOCKSIZE-1;
+ g_om_free_count += _BLOCKSIZE-1;
- // Add the new block to the list of extant blocks (gBlockList).
- // The very first objectMonitor in a block is reserved and dedicated.
+ // Add the new block to the list of extant blocks (g_block_list).
+ // The very first ObjectMonitor in a block is reserved and dedicated.
// It serves as blocklist "next" linkage.
- temp[0].FreeNext = gBlockList;
- // There are lock-free uses of gBlockList so make sure that
- // the previous stores happen before we update gBlockList.
- OrderAccess::release_store(&gBlockList, temp);
+ temp[0]._next_om = g_block_list;
+ // There are lock-free uses of g_block_list so make sure that
+ // the previous stores happen before we update g_block_list.
+ OrderAccess::release_store(&g_block_list, temp);
- // Add the new string of objectMonitors to the global free list
- temp[_BLOCKSIZE - 1].FreeNext = gFreeList;
- gFreeList = temp + 1;
+ // Add the new string of ObjectMonitors to the global free list
+ temp[_BLOCKSIZE - 1]._next_om = g_free_list;
+ g_free_list = temp + 1;
Thread::muxRelease(&gListLock);
}
}
-// Place "m" on the caller's private per-thread omFreeList.
+// Place "m" on the caller's private per-thread om_free_list.
// In practice there's no need to clamp or limit the number of
-// monitors on a thread's omFreeList as the only time we'll call
-// omRelease is to return a monitor to the free list after a CAS
-// attempt failed. This doesn't allow unbounded #s of monitors to
+// monitors on a thread's om_free_list as the only non-allocation time
+// we'll call om_release() is to return a monitor to the free list after
+// a CAS attempt failed. This doesn't allow unbounded #s of monitors to
// accumulate on a thread's free list.
//
// Key constraint: all ObjectMonitors on a thread's free list and the global
// free list must have their object field set to null. This prevents the
-// scavenger -- deflate_monitor_list() -- from reclaiming them.
+// scavenger -- deflate_monitor_list() -- from reclaiming them while we
+// are trying to release them.
-void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
- bool fromPerThreadAlloc) {
+void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m,
+ bool from_per_thread_alloc) {
guarantee(m->header().value() == 0, "invariant");
guarantee(m->object() == NULL, "invariant");
stringStream ss;
guarantee((m->is_busy() | m->_recursions) == 0, "freeing in-use monitor: "
"%s, recursions=" INTPTR_FORMAT, m->is_busy_to_string(&ss),
m->_recursions);
- // Remove from omInUseList
- if (fromPerThreadAlloc) {
+ // _next_om is used for both per-thread in-use and free lists so
+ // we have to remove 'm' from the in-use list first (as needed).
+ if (from_per_thread_alloc) {
+ // Need to remove 'm' from om_in_use_list.
ObjectMonitor* cur_mid_in_use = NULL;
bool extracted = false;
- for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; cur_mid_in_use = mid, mid = mid->FreeNext) {
+ for (ObjectMonitor* mid = self->om_in_use_list; mid != NULL; cur_mid_in_use = mid, mid = mid->_next_om) {
if (m == mid) {
// extract from per-thread in-use list
- if (mid == Self->omInUseList) {
- Self->omInUseList = mid->FreeNext;
+ if (mid == self->om_in_use_list) {
+ self->om_in_use_list = mid->_next_om;
} else if (cur_mid_in_use != NULL) {
- cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list
+ cur_mid_in_use->_next_om = mid->_next_om; // maintain the current thread in-use list
}
extracted = true;
- Self->omInUseCount--;
+ self->om_in_use_count--;
break;
}
}
assert(extracted, "Should have extracted from in-use list");
}
- // FreeNext is used for both omInUseList and omFreeList, so clear old before setting new
- m->FreeNext = Self->omFreeList;
- Self->omFreeList = m;
- Self->omFreeCount++;
+ m->_next_om = self->om_free_list;
+ self->om_free_list = m;
+ self->om_free_count++;
}
-// Return the monitors of a moribund thread's local free list to
-// the global free list. Typically a thread calls omFlush() when
-// it's dying. We could also consider having the VM thread steal
-// monitors from threads that have not run java code over a few
-// consecutive STW safepoints. Relatedly, we might decay
-// omFreeProvision at STW safepoints.
-//
-// Also return the monitors of a moribund thread's omInUseList to
-// a global gOmInUseList under the global list lock so these
-// will continue to be scanned.
+// Return ObjectMonitors on a moribund thread's free and in-use
+// lists to the appropriate global lists. The ObjectMonitors on the
+// per-thread in-use list may still be in use by other threads.
//
-// We currently call omFlush() from Threads::remove() _before the thread
-// has been excised from the thread list and is no longer a mutator.
-// This means that omFlush() cannot run concurrently with a safepoint and
-// interleave with the deflate_idle_monitors scavenge operator. In particular,
-// this ensures that the thread's monitors are scanned by a GC safepoint,
-// either via Thread::oops_do() (if safepoint happens before omFlush()) or via
-// ObjectSynchronizer::oops_do() (if it happens after omFlush() and the thread's
-// monitors have been transferred to the global in-use list).
+// We currently call om_flush() from Threads::remove() before the
+// thread has been excised from the thread list and is no longer a
+// mutator. This means that om_flush() cannot run concurrently with
+// a safepoint and interleave with deflate_idle_monitors(). In
+// particular, this ensures that the thread's in-use monitors are
+// scanned by a GC safepoint, either via Thread::oops_do() (before
+// om_flush() is called) or via ObjectSynchronizer::oops_do() (after
+// om_flush() is called).
-void ObjectSynchronizer::omFlush(Thread * Self) {
- ObjectMonitor * list = Self->omFreeList; // Null-terminated SLL
- ObjectMonitor * tail = NULL;
- int tally = 0;
- if (list != NULL) {
- ObjectMonitor * s;
- // The thread is going away. Set 'tail' to the last per-thread free
- // monitor which will be linked to gFreeList below under the gListLock.
+void ObjectSynchronizer::om_flush(Thread* self) {
+ ObjectMonitor* free_list = self->om_free_list;
+ ObjectMonitor* free_tail = NULL;
+ int free_count = 0;
+ if (free_list != NULL) {
+ ObjectMonitor* s;
+ // The thread is going away. Set 'free_tail' to the last per-thread free
+ // monitor which will be linked to g_free_list below under the gListLock.
stringStream ss;
- for (s = list; s != NULL; s = s->FreeNext) {
- tally++;
- tail = s;
+ for (s = free_list; s != NULL; s = s->_next_om) {
+ free_count++;
+ free_tail = s;
guarantee(s->object() == NULL, "invariant");
guarantee(!s->is_busy(), "must be !is_busy: %s", s->is_busy_to_string(&ss));
}
- guarantee(tail != NULL, "invariant");
- assert(Self->omFreeCount == tally, "free-count off");
- Self->omFreeList = NULL;
- Self->omFreeCount = 0;
+ guarantee(free_tail != NULL, "invariant");
+ assert(self->om_free_count == free_count, "free-count off");
+ self->om_free_list = NULL;
+ self->om_free_count = 0;
}
- ObjectMonitor * inUseList = Self->omInUseList;
- ObjectMonitor * inUseTail = NULL;
- int inUseTally = 0;
- if (inUseList != NULL) {
+ ObjectMonitor* in_use_list = self->om_in_use_list;
+ ObjectMonitor* in_use_tail = NULL;
+ int in_use_count = 0;
+ if (in_use_list != NULL) {
+ // The thread is going away, however the ObjectMonitors on the
+ // om_in_use_list may still be in-use by other threads. Link
+ // them to in_use_tail, which will be linked into the global
+ // in-use list g_om_in_use_list below, under the gListLock.
ObjectMonitor *cur_om;
- // The thread is going away, however the omInUseList inflated
- // monitors may still be in-use by other threads.
- // Link them to inUseTail, which will be linked into the global in-use list
- // gOmInUseList below, under the gListLock
- for (cur_om = inUseList; cur_om != NULL; cur_om = cur_om->FreeNext) {
- inUseTail = cur_om;
- inUseTally++;
+ for (cur_om = in_use_list; cur_om != NULL; cur_om = cur_om->_next_om) {
+ in_use_tail = cur_om;
+ in_use_count++;
}
- guarantee(inUseTail != NULL, "invariant");
- assert(Self->omInUseCount == inUseTally, "in-use count off");
- Self->omInUseList = NULL;
- Self->omInUseCount = 0;
+ guarantee(in_use_tail != NULL, "invariant");
+ assert(self->om_in_use_count == in_use_count, "in-use count off");
+ self->om_in_use_list = NULL;
+ self->om_in_use_count = 0;
}
- Thread::muxAcquire(&gListLock, "omFlush");
- if (tail != NULL) {
- tail->FreeNext = gFreeList;
- gFreeList = list;
- gMonitorFreeCount += tally;
+ Thread::muxAcquire(&gListLock, "om_flush");
+ if (free_tail != NULL) {
+ free_tail->_next_om = g_free_list;
+ g_free_list = free_list;
+ g_om_free_count += free_count;
}
- if (inUseTail != NULL) {
- inUseTail->FreeNext = gOmInUseList;
- gOmInUseList = inUseList;
- gOmInUseCount += inUseTally;
+ if (in_use_tail != NULL) {
+ in_use_tail->_next_om = g_om_in_use_list;
+ g_om_in_use_list = in_use_list;
+ g_om_in_use_count += in_use_count;
}
Thread::muxRelease(&gListLock);
LogStreamHandle(Debug, monitorinflation) lsh_debug;
LogStreamHandle(Info, monitorinflation) lsh_info;
- LogStream * ls = NULL;
+ LogStream* ls = NULL;
if (log_is_enabled(Debug, monitorinflation)) {
ls = &lsh_debug;
- } else if ((tally != 0 || inUseTally != 0) &&
+ } else if ((free_count != 0 || in_use_count != 0) &&
log_is_enabled(Info, monitorinflation)) {
ls = &lsh_info;
}
if (ls != NULL) {
- ls->print_cr("omFlush: jt=" INTPTR_FORMAT ", free_monitor_tally=%d"
- ", in_use_monitor_tally=%d" ", omFreeProvision=%d",
- p2i(Self), tally, inUseTally, Self->omFreeProvision);
+ ls->print_cr("om_flush: jt=" INTPTR_FORMAT ", free_count=%d"
+ ", in_use_count=%d" ", om_free_provision=%d",
+ p2i(self), free_count, in_use_count, self->om_free_provision);
}
}
@@ -1311,7 +1284,7 @@
inflate(Thread::current(), obj, inflate_cause_vm_internal);
}
-ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
+ObjectMonitor* ObjectSynchronizer::inflate(Thread* self,
oop object,
const InflateCause cause) {
// Inflate mutates the heap ...
@@ -1334,7 +1307,7 @@
// CASE: inflated
if (mark.has_monitor()) {
- ObjectMonitor * inf = mark.monitor();
+ ObjectMonitor* inf = mark.monitor();
markWord dmw = inf->header();
assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
assert(oopDesc::equals((oop) inf->object(), object), "invariant");
@@ -1349,7 +1322,7 @@
// Currently, we spin/yield/park and poll the markword, waiting for inflation to finish.
// We could always eliminate polling by parking the thread on some auxiliary list.
if (mark == markWord::INFLATING()) {
- ReadStableMark(object);
+ read_stable_mark(object);
continue;
}
@@ -1368,14 +1341,14 @@
// critical INFLATING...ST interval. A thread can transfer
// multiple objectmonitors en-mass from the global free list to its local free list.
// This reduces coherency traffic and lock contention on the global free list.
- // Using such local free lists, it doesn't matter if the omAlloc() call appears
+ // Using such local free lists, it doesn't matter if the om_alloc() call appears
// before or after the CAS(INFLATING) operation.
- // See the comments in omAlloc().
+ // See the comments in om_alloc().
LogStreamHandle(Trace, monitorinflation) lsh;
if (mark.has_locker()) {
- ObjectMonitor * m = omAlloc(Self);
+ ObjectMonitor* m = om_alloc(self);
// Optimistically prepare the objectmonitor - anticipate successful CAS
// We do this before the CAS in order to minimize the length of time
// in which INFLATING appears in the mark.
@@ -1385,7 +1358,7 @@
markWord cmp = object->cas_set_mark(markWord::INFLATING(), mark);
if (cmp != mark) {
- omRelease(Self, m, true);
+ om_release(self, m, true);
continue; // Interference -- just retry
}
@@ -1398,17 +1371,17 @@
// mark-word from the stack-locked value directly to the new inflated state?
// Consider what happens when a thread unlocks a stack-locked object.
// It attempts to use CAS to swing the displaced header value from the
- // on-stack basiclock back into the object header. Recall also that the
+ // on-stack BasicLock back into the object header. Recall also that the
// header value (hash code, etc) can reside in (a) the object header, or
// (b) a displaced header associated with the stack-lock, or (c) a displaced
- // header in an objectMonitor. The inflate() routine must copy the header
- // value from the basiclock on the owner's stack to the objectMonitor, all
+ // header in an ObjectMonitor. The inflate() routine must copy the header
+ // value from the BasicLock on the owner's stack to the ObjectMonitor, all
// the while preserving the hashCode stability invariants. If the owner
// decides to release the lock while the value is 0, the unlock will fail
// and control will eventually pass from slow_exit() to inflate. The owner
// will then spin, waiting for the 0 value to disappear. Put another way,
// the 0 causes the owner to stall if the owner happens to try to
- // drop the lock (restoring the header from the basiclock to the object)
+ // drop the lock (restoring the header from the BasicLock to the object)
// while inflation is in-progress. This protocol avoids races that might
// would otherwise permit hashCode values to change or "flicker" for an object.
// Critically, while object->mark is 0 mark.displaced_mark_helper() is stable.
@@ -1428,7 +1401,7 @@
m->set_header(dmw);
// Optimization: if the mark.locker stack address is associated
- // with this thread we could simply set m->_owner = Self.
+ // with this thread we could simply set m->_owner = self.
// Note that a thread can inflate an object
// that it has stack-locked -- as might happen in wait() -- directly
// with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
@@ -1445,7 +1418,7 @@
// to avoid false sharing on MP systems ...
OM_PERFDATA_OP(Inflations, inc());
if (log_is_enabled(Trace, monitorinflation)) {
- ResourceMark rm(Self);
+ ResourceMark rm(self);
lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", type='%s'", p2i(object),
object->mark().value(), object->klass()->external_name());
@@ -1459,17 +1432,16 @@
// CASE: neutral
// TODO-FIXME: for entry we currently inflate and then try to CAS _owner.
// If we know we're inflating for entry it's better to inflate by swinging a
- // pre-locked objectMonitor pointer into the object header. A successful
+ // pre-locked ObjectMonitor pointer into the object header. A successful
// CAS inflates the object *and* confers ownership to the inflating thread.
// In the current implementation we use a 2-step mechanism where we CAS()
- // to inflate and then CAS() again to try to swing _owner from NULL to Self.
- // An inflateTry() method that we could call from fast_enter() and slow_enter()
- // would be useful.
+ // to inflate and then CAS() again to try to swing _owner from NULL to self.
+ // An inflateTry() method that we could call from enter() would be useful.
// Catch if the object's header is not neutral (not locked and
// not marked is what we care about here).
assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
- ObjectMonitor * m = omAlloc(Self);
+ ObjectMonitor* m = om_alloc(self);
// prepare m for installation - set monitor to initial state
m->Recycle();
m->set_header(mark);
@@ -1481,7 +1453,7 @@
m->set_header(markWord::zero());
m->set_object(NULL);
m->Recycle();
- omRelease(Self, m, true);
+ om_release(self, m, true);
m = NULL;
continue;
// interference - the markword changed - just retry.
@@ -1493,7 +1465,7 @@
// cache lines to avoid false sharing on MP systems ...
OM_PERFDATA_OP(Inflations, inc());
if (log_is_enabled(Trace, monitorinflation)) {
- ResourceMark rm(Self);
+ ResourceMark rm(self);
lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", type='%s'", p2i(object),
object->mark().value(), object->klass()->external_name());
@@ -1510,7 +1482,7 @@
//
// deflate_thread_local_monitors() scans a single thread's in-use list, while
// deflate_idle_monitors() scans only a global list of in-use monitors which
-// is populated only as a thread dies (see omFlush()).
+// is populated only as a thread dies (see om_flush()).
//
// These operations are called at all safepoints, immediately after mutators
// are stopped, but before any objects have moved. Collectively they traverse
@@ -1530,8 +1502,8 @@
// Deflate a single monitor if not in-use
// Return true if deflated, false if in-use
bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
- ObjectMonitor** freeHeadp,
- ObjectMonitor** freeTailp) {
+ ObjectMonitor** free_head_p,
+ ObjectMonitor** free_tail_p) {
bool deflated;
// Normal case ... The monitor is associated with obj.
const markWord mark = obj->mark();
@@ -1565,14 +1537,22 @@
assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT,
p2i(mid->object()));
- // Move the object to the working free list defined by freeHeadp, freeTailp
- if (*freeHeadp == NULL) *freeHeadp = mid;
- if (*freeTailp != NULL) {
- ObjectMonitor * prevtail = *freeTailp;
- assert(prevtail->FreeNext == NULL, "cleaned up deflated?");
- prevtail->FreeNext = mid;
+ // Move the deflated ObjectMonitor to the working free list
+ // defined by free_head_p and free_tail_p.
+ if (*free_head_p == NULL) *free_head_p = mid;
+ if (*free_tail_p != NULL) {
+ // We append to the list so the caller can use mid->_next_om
+ // to fix the linkages in its context.
+ ObjectMonitor* prevtail = *free_tail_p;
+ // Should have been cleaned up by the caller:
+ assert(prevtail->_next_om == NULL, "cleaned up deflated?");
+ prevtail->_next_om = mid;
}
- *freeTailp = mid;
+ *free_tail_p = mid;
+ // At this point, mid->_next_om still refers to its current
+ // value and another ObjectMonitor's _next_om field still
+ // refers to this ObjectMonitor. Those linkages have to be
+ // cleaned up by the caller who has the complete context.
deflated = true;
}
return deflated;
@@ -1591,57 +1571,58 @@
// See also ParallelSPCleanupTask and
// SafepointSynchronize::do_cleanup_tasks() in safepoint.cpp and
// Threads::parallel_java_threads_do() in thread.cpp.
-int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listHeadp,
- ObjectMonitor** freeHeadp,
- ObjectMonitor** freeTailp) {
+int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** list_p,
+ ObjectMonitor** free_head_p,
+ ObjectMonitor** free_tail_p) {
ObjectMonitor* mid;
ObjectMonitor* next;
ObjectMonitor* cur_mid_in_use = NULL;
int deflated_count = 0;
- for (mid = *listHeadp; mid != NULL;) {
+ for (mid = *list_p; mid != NULL;) {
oop obj = (oop) mid->object();
- if (obj != NULL && deflate_monitor(mid, obj, freeHeadp, freeTailp)) {
- // if deflate_monitor succeeded,
- // extract from per-thread in-use list
- if (mid == *listHeadp) {
- *listHeadp = mid->FreeNext;
+ if (obj != NULL && deflate_monitor(mid, obj, free_head_p, free_tail_p)) {
+ // Deflation succeeded and already updated free_head_p and
+ // free_tail_p as needed. Finish the move to the local free list
+ // by unlinking mid from the global or per-thread in-use list.
+ if (mid == *list_p) {
+ *list_p = mid->_next_om;
} else if (cur_mid_in_use != NULL) {
- cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list
+ cur_mid_in_use->_next_om = mid->_next_om; // maintain the current thread in-use list
}
- next = mid->FreeNext;
- mid->FreeNext = NULL; // This mid is current tail in the freeHeadp list
+ next = mid->_next_om;
+ mid->_next_om = NULL; // This mid is current tail in the free_head_p list
mid = next;
deflated_count++;
} else {
cur_mid_in_use = mid;
- mid = mid->FreeNext;
+ mid = mid->_next_om;
}
}
return deflated_count;
}
void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) {
- counters->nInuse = 0; // currently associated with objects
- counters->nInCirculation = 0; // extant
- counters->nScavenged = 0; // reclaimed (global and per-thread)
- counters->perThreadScavenged = 0; // per-thread scavenge total
- counters->perThreadTimes = 0.0; // per-thread scavenge times
+ counters->n_in_use = 0; // currently associated with objects
+ counters->n_in_circulation = 0; // extant
+ counters->n_scavenged = 0; // reclaimed (global and per-thread)
+ counters->per_thread_scavenged = 0; // per-thread scavenge total
+ counters->per_thread_times = 0.0; // per-thread scavenge times
}
void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
bool deflated = false;
- ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors
- ObjectMonitor * freeTailp = NULL;
+ ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged monitors
+ ObjectMonitor* free_tail_p = NULL;
elapsedTimer timer;
if (log_is_enabled(Info, monitorinflation)) {
timer.start();
}
- // Prevent omFlush from changing mids in Thread dtor's during deflation
+ // Prevent om_flush from changing mids in Thread dtor's during deflation
// And in case the vm thread is acquiring a lock during a safepoint
// See e.g. 6320749
Thread::muxAcquire(&gListLock, "deflate_idle_monitors");
@@ -1649,30 +1630,30 @@
// Note: the thread-local monitors lists get deflated in
// a separate pass. See deflate_thread_local_monitors().
- // For moribund threads, scan gOmInUseList
+ // For moribund threads, scan g_om_in_use_list
int deflated_count = 0;
- if (gOmInUseList) {
- counters->nInCirculation += gOmInUseCount;
- deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp);
- gOmInUseCount -= deflated_count;
- counters->nScavenged += deflated_count;
- counters->nInuse += gOmInUseCount;
+ if (g_om_in_use_list) {
+ counters->n_in_circulation += g_om_in_use_count;
+ deflated_count = deflate_monitor_list((ObjectMonitor **)&g_om_in_use_list, &free_head_p, &free_tail_p);
+ g_om_in_use_count -= deflated_count;
+ counters->n_scavenged += deflated_count;
+ counters->n_in_use += g_om_in_use_count;
}
- // Move the scavenged monitors back to the global free list.
- if (freeHeadp != NULL) {
- guarantee(freeTailp != NULL && counters->nScavenged > 0, "invariant");
- assert(freeTailp->FreeNext == NULL, "invariant");
- // constant-time list splice - prepend scavenged segment to gFreeList
- freeTailp->FreeNext = gFreeList;
- gFreeList = freeHeadp;
+ if (free_head_p != NULL) {
+ // Move the deflated ObjectMonitors back to the global free list.
+ guarantee(free_tail_p != NULL && counters->n_scavenged > 0, "invariant");
+ assert(free_tail_p->_next_om == NULL, "invariant");
+ // constant-time list splice - prepend scavenged segment to g_free_list
+ free_tail_p->_next_om = g_free_list;
+ g_free_list = free_head_p;
}
Thread::muxRelease(&gListLock);
timer.stop();
LogStreamHandle(Debug, monitorinflation) lsh_debug;
LogStreamHandle(Info, monitorinflation) lsh_info;
- LogStream * ls = NULL;
+ LogStream* ls = NULL;
if (log_is_enabled(Debug, monitorinflation)) {
ls = &lsh_debug;
} else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) {
@@ -1688,9 +1669,9 @@
// monitors. Note: if the work is split among more than one
// worker thread, then the reported time will likely be more
// than a beginning to end measurement of the phase.
- log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->perThreadTimes, counters->perThreadScavenged);
+ log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->per_thread_times, counters->per_thread_scavenged);
- gMonitorFreeCount += counters->nScavenged;
+ g_om_free_count += counters->n_scavenged;
if (log_is_enabled(Debug, monitorinflation)) {
// exit_globals()'s call to audit_and_print_stats() is done
@@ -1698,26 +1679,26 @@
ObjectSynchronizer::audit_and_print_stats(false /* on_exit */);
} else if (log_is_enabled(Info, monitorinflation)) {
Thread::muxAcquire(&gListLock, "finish_deflate_idle_monitors");
- log_info(monitorinflation)("gMonitorPopulation=%d, gOmInUseCount=%d, "
- "gMonitorFreeCount=%d", gMonitorPopulation,
- gOmInUseCount, gMonitorFreeCount);
+ log_info(monitorinflation)("g_om_population=%d, g_om_in_use_count=%d, "
+ "g_om_free_count=%d", g_om_population,
+ g_om_in_use_count, g_om_free_count);
Thread::muxRelease(&gListLock);
}
ForceMonitorScavenge = 0; // Reset
- OM_PERFDATA_OP(Deflations, inc(counters->nScavenged));
- OM_PERFDATA_OP(MonExtant, set_value(counters->nInCirculation));
+ OM_PERFDATA_OP(Deflations, inc(counters->n_scavenged));
+ OM_PERFDATA_OP(MonExtant, set_value(counters->n_in_circulation));
- GVars.stwRandom = os::random();
- GVars.stwCycle++;
+ GVars.stw_random = os::random();
+ GVars.stw_cycle++;
}
void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors
- ObjectMonitor * freeTailp = NULL;
+ ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged monitors
+ ObjectMonitor* free_tail_p = NULL;
elapsedTimer timer;
if (log_is_enabled(Info, safepoint, cleanup) ||
@@ -1725,38 +1706,38 @@
timer.start();
}
- int deflated_count = deflate_monitor_list(thread->omInUseList_addr(), &freeHeadp, &freeTailp);
+ int deflated_count = deflate_monitor_list(thread->om_in_use_list_addr(), &free_head_p, &free_tail_p);
Thread::muxAcquire(&gListLock, "deflate_thread_local_monitors");
// Adjust counters
- counters->nInCirculation += thread->omInUseCount;
- thread->omInUseCount -= deflated_count;
- counters->nScavenged += deflated_count;
- counters->nInuse += thread->omInUseCount;
- counters->perThreadScavenged += deflated_count;
+ counters->n_in_circulation += thread->om_in_use_count;
+ thread->om_in_use_count -= deflated_count;
+ counters->n_scavenged += deflated_count;
+ counters->n_in_use += thread->om_in_use_count;
+ counters->per_thread_scavenged += deflated_count;
- // Move the scavenged monitors back to the global free list.
- if (freeHeadp != NULL) {
- guarantee(freeTailp != NULL && deflated_count > 0, "invariant");
- assert(freeTailp->FreeNext == NULL, "invariant");
+ if (free_head_p != NULL) {
+ // Move the deflated ObjectMonitors back to the global free list.
+ guarantee(free_tail_p != NULL && deflated_count > 0, "invariant");
+ assert(free_tail_p->_next_om == NULL, "invariant");
- // constant-time list splice - prepend scavenged segment to gFreeList
- freeTailp->FreeNext = gFreeList;
- gFreeList = freeHeadp;
+ // constant-time list splice - prepend scavenged segment to g_free_list
+ free_tail_p->_next_om = g_free_list;
+ g_free_list = free_head_p;
}
timer.stop();
- // Safepoint logging cares about cumulative perThreadTimes and
+ // Safepoint logging cares about cumulative per_thread_times and
// we'll capture most of the cost, but not the muxRelease() which
// should be cheap.
- counters->perThreadTimes += timer.seconds();
+ counters->per_thread_times += timer.seconds();
Thread::muxRelease(&gListLock);
LogStreamHandle(Debug, monitorinflation) lsh_debug;
LogStreamHandle(Info, monitorinflation) lsh_info;
- LogStream * ls = NULL;
+ LogStream* ls = NULL;
if (log_is_enabled(Debug, monitorinflation)) {
ls = &lsh_debug;
} else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) {
@@ -1832,16 +1813,16 @@
return (u_char*)&GVars;
}
-u_char* ObjectSynchronizer::get_gvars_hcSequence_addr() {
- return (u_char*)&GVars.hcSequence;
+u_char* ObjectSynchronizer::get_gvars_hc_sequence_addr() {
+ return (u_char*)&GVars.hc_sequence;
}
size_t ObjectSynchronizer::get_gvars_size() {
return sizeof(SharedGlobals);
}
-u_char* ObjectSynchronizer::get_gvars_stwRandom_addr() {
- return (u_char*)&GVars.stwRandom;
+u_char* ObjectSynchronizer::get_gvars_stw_random_addr() {
+ return (u_char*)&GVars.stw_random;
}
void ObjectSynchronizer::audit_and_print_stats(bool on_exit) {
@@ -1850,7 +1831,7 @@
LogStreamHandle(Debug, monitorinflation) lsh_debug;
LogStreamHandle(Info, monitorinflation) lsh_info;
LogStreamHandle(Trace, monitorinflation) lsh_trace;
- LogStream * ls = NULL;
+ LogStream* ls = NULL;
if (log_is_enabled(Trace, monitorinflation)) {
ls = &lsh_trace;
} else if (log_is_enabled(Debug, monitorinflation)) {
@@ -1866,26 +1847,26 @@
}
// Log counts for the global and per-thread monitor lists:
- int chkMonitorPopulation = log_monitor_list_counts(ls);
+ int chk_om_population = log_monitor_list_counts(ls);
int error_cnt = 0;
ls->print_cr("Checking global lists:");
- // Check gMonitorPopulation:
- if (gMonitorPopulation == chkMonitorPopulation) {
- ls->print_cr("gMonitorPopulation=%d equals chkMonitorPopulation=%d",
- gMonitorPopulation, chkMonitorPopulation);
+ // Check g_om_population:
+ if (g_om_population == chk_om_population) {
+ ls->print_cr("g_om_population=%d equals chk_om_population=%d",
+ g_om_population, chk_om_population);
} else {
- ls->print_cr("ERROR: gMonitorPopulation=%d is not equal to "
- "chkMonitorPopulation=%d", gMonitorPopulation,
- chkMonitorPopulation);
+ ls->print_cr("ERROR: g_om_population=%d is not equal to "
+ "chk_om_population=%d", g_om_population,
+ chk_om_population);
error_cnt++;
}
- // Check gOmInUseList and gOmInUseCount:
+ // Check g_om_in_use_list and g_om_in_use_count:
chk_global_in_use_list_and_count(ls, &error_cnt);
- // Check gFreeList and gMonitorFreeCount:
+ // Check g_free_list and g_om_free_count:
chk_global_free_list_and_count(ls, &error_cnt);
if (!on_exit) {
@@ -1895,10 +1876,10 @@
ls->print_cr("Checking per-thread lists:");
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
- // Check omInUseList and omInUseCount:
+ // Check om_in_use_list and om_in_use_count:
chk_per_thread_in_use_list_and_count(jt, ls, &error_cnt);
- // Check omFreeList and omFreeCount:
+ // Check om_free_list and om_free_count:
chk_per_thread_free_list_and_count(jt, ls, &error_cnt);
}
@@ -1922,7 +1903,7 @@
}
// Check a free monitor entry; log any errors.
-void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
+void ObjectSynchronizer::chk_free_entry(JavaThread* jt, ObjectMonitor* n,
outputStream * out, int *error_cnt_p) {
stringStream ss;
if (n->is_busy()) {
@@ -1967,18 +1948,18 @@
// Check the global free list and count; log the results of the checks.
void ObjectSynchronizer::chk_global_free_list_and_count(outputStream * out,
int *error_cnt_p) {
- int chkMonitorFreeCount = 0;
- for (ObjectMonitor * n = gFreeList; n != NULL; n = n->FreeNext) {
+ int chk_om_free_count = 0;
+ for (ObjectMonitor* n = g_free_list; n != NULL; n = n->_next_om) {
chk_free_entry(NULL /* jt */, n, out, error_cnt_p);
- chkMonitorFreeCount++;
+ chk_om_free_count++;
}
- if (gMonitorFreeCount == chkMonitorFreeCount) {
- out->print_cr("gMonitorFreeCount=%d equals chkMonitorFreeCount=%d",
- gMonitorFreeCount, chkMonitorFreeCount);
+ if (g_om_free_count == chk_om_free_count) {
+ out->print_cr("g_om_free_count=%d equals chk_om_free_count=%d",
+ g_om_free_count, chk_om_free_count);
} else {
- out->print_cr("ERROR: gMonitorFreeCount=%d is not equal to "
- "chkMonitorFreeCount=%d", gMonitorFreeCount,
- chkMonitorFreeCount);
+ out->print_cr("ERROR: g_om_free_count=%d is not equal to "
+ "chk_om_free_count=%d", g_om_free_count,
+ chk_om_free_count);
*error_cnt_p = *error_cnt_p + 1;
}
}
@@ -1986,23 +1967,23 @@
// Check the global in-use list and count; log the results of the checks.
void ObjectSynchronizer::chk_global_in_use_list_and_count(outputStream * out,
int *error_cnt_p) {
- int chkOmInUseCount = 0;
- for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) {
+ int chk_om_in_use_count = 0;
+ for (ObjectMonitor* n = g_om_in_use_list; n != NULL; n = n->_next_om) {
chk_in_use_entry(NULL /* jt */, n, out, error_cnt_p);
- chkOmInUseCount++;
+ chk_om_in_use_count++;
}
- if (gOmInUseCount == chkOmInUseCount) {
- out->print_cr("gOmInUseCount=%d equals chkOmInUseCount=%d", gOmInUseCount,
- chkOmInUseCount);
+ if (g_om_in_use_count == chk_om_in_use_count) {
+ out->print_cr("g_om_in_use_count=%d equals chk_om_in_use_count=%d", g_om_in_use_count,
+ chk_om_in_use_count);
} else {
- out->print_cr("ERROR: gOmInUseCount=%d is not equal to chkOmInUseCount=%d",
- gOmInUseCount, chkOmInUseCount);
+ out->print_cr("ERROR: g_om_in_use_count=%d is not equal to chk_om_in_use_count=%d",
+ g_om_in_use_count, chk_om_in_use_count);
*error_cnt_p = *error_cnt_p + 1;
}
}
// Check an in-use monitor entry; log any errors.
-void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
+void ObjectSynchronizer::chk_in_use_entry(JavaThread* jt, ObjectMonitor* n,
outputStream * out, int *error_cnt_p) {
if (n->header().value() == 0) {
if (jt != NULL) {
@@ -2042,7 +2023,7 @@
}
*error_cnt_p = *error_cnt_p + 1;
}
- ObjectMonitor * const obj_mon = mark.monitor();
+ ObjectMonitor* const obj_mon = mark.monitor();
if (n != obj_mon) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
@@ -2064,18 +2045,18 @@
void ObjectSynchronizer::chk_per_thread_free_list_and_count(JavaThread *jt,
outputStream * out,
int *error_cnt_p) {
- int chkOmFreeCount = 0;
- for (ObjectMonitor * n = jt->omFreeList; n != NULL; n = n->FreeNext) {
+ int chk_om_free_count = 0;
+ for (ObjectMonitor* n = jt->om_free_list; n != NULL; n = n->_next_om) {
chk_free_entry(jt, n, out, error_cnt_p);
- chkOmFreeCount++;
+ chk_om_free_count++;
}
- if (jt->omFreeCount == chkOmFreeCount) {
- out->print_cr("jt=" INTPTR_FORMAT ": omFreeCount=%d equals "
- "chkOmFreeCount=%d", p2i(jt), jt->omFreeCount, chkOmFreeCount);
+ if (jt->om_free_count == chk_om_free_count) {
+ out->print_cr("jt=" INTPTR_FORMAT ": om_free_count=%d equals "
+ "chk_om_free_count=%d", p2i(jt), jt->om_free_count, chk_om_free_count);
} else {
- out->print_cr("ERROR: jt=" INTPTR_FORMAT ": omFreeCount=%d is not "
- "equal to chkOmFreeCount=%d", p2i(jt), jt->omFreeCount,
- chkOmFreeCount);
+ out->print_cr("ERROR: jt=" INTPTR_FORMAT ": om_free_count=%d is not "
+ "equal to chk_om_free_count=%d", p2i(jt), jt->om_free_count,
+ chk_om_free_count);
*error_cnt_p = *error_cnt_p + 1;
}
}
@@ -2084,19 +2065,19 @@
void ObjectSynchronizer::chk_per_thread_in_use_list_and_count(JavaThread *jt,
outputStream * out,
int *error_cnt_p) {
- int chkOmInUseCount = 0;
- for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) {
+ int chk_om_in_use_count = 0;
+ for (ObjectMonitor* n = jt->om_in_use_list; n != NULL; n = n->_next_om) {
chk_in_use_entry(jt, n, out, error_cnt_p);
- chkOmInUseCount++;
+ chk_om_in_use_count++;
}
- if (jt->omInUseCount == chkOmInUseCount) {
- out->print_cr("jt=" INTPTR_FORMAT ": omInUseCount=%d equals "
- "chkOmInUseCount=%d", p2i(jt), jt->omInUseCount,
- chkOmInUseCount);
+ if (jt->om_in_use_count == chk_om_in_use_count) {
+ out->print_cr("jt=" INTPTR_FORMAT ": om_in_use_count=%d equals "
+ "chk_om_in_use_count=%d", p2i(jt), jt->om_in_use_count,
+ chk_om_in_use_count);
} else {
- out->print_cr("ERROR: jt=" INTPTR_FORMAT ": omInUseCount=%d is not "
- "equal to chkOmInUseCount=%d", p2i(jt), jt->omInUseCount,
- chkOmInUseCount);
+ out->print_cr("ERROR: jt=" INTPTR_FORMAT ": om_in_use_count=%d is not "
+ "equal to chk_om_in_use_count=%d", p2i(jt), jt->om_in_use_count,
+ chk_om_in_use_count);
*error_cnt_p = *error_cnt_p + 1;
}
}
@@ -2112,13 +2093,13 @@
}
stringStream ss;
- if (gOmInUseCount > 0) {
+ if (g_om_in_use_count > 0) {
out->print_cr("In-use global monitor info:");
out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
out->print_cr("%18s %s %18s %18s",
"monitor", "BHL", "object", "object type");
out->print_cr("================== === ================== ==================");
- for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) {
+ for (ObjectMonitor* n = g_om_in_use_list; n != NULL; n = n->_next_om) {
const oop obj = (oop) n->object();
const markWord mark = n->header();
ResourceMark rm;
@@ -2143,7 +2124,7 @@
"jt", "monitor", "BHL", "object", "object type");
out->print_cr("================== ================== === ================== ==================");
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
- for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) {
+ for (ObjectMonitor* n = jt->om_in_use_list; n != NULL; n = n->_next_om) {
const oop obj = (oop) n->object();
const markWord mark = n->header();
ResourceMark rm;
@@ -2165,13 +2146,13 @@
// Log counts for the global and per-thread monitor lists and return
// the population count.
int ObjectSynchronizer::log_monitor_list_counts(outputStream * out) {
- int popCount = 0;
+ int pop_count = 0;
out->print_cr("%18s %10s %10s %10s",
"Global Lists:", "InUse", "Free", "Total");
out->print_cr("================== ========== ========== ==========");
out->print_cr("%18s %10d %10d %10d", "",
- gOmInUseCount, gMonitorFreeCount, gMonitorPopulation);
- popCount += gOmInUseCount + gMonitorFreeCount;
+ g_om_in_use_count, g_om_free_count, g_om_population);
+ pop_count += g_om_in_use_count + g_om_free_count;
out->print_cr("%18s %10s %10s %10s",
"Per-Thread Lists:", "InUse", "Free", "Provision");
@@ -2179,10 +2160,10 @@
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
out->print_cr(INTPTR_FORMAT " %10d %10d %10d", p2i(jt),
- jt->omInUseCount, jt->omFreeCount, jt->omFreeProvision);
- popCount += jt->omInUseCount + jt->omFreeCount;
+ jt->om_in_use_count, jt->om_free_count, jt->om_free_provision);
+ pop_count += jt->om_in_use_count + jt->om_free_count;
}
- return popCount;
+ return pop_count;
}
#ifndef PRODUCT
@@ -2192,17 +2173,17 @@
// the list of extant blocks without taking a lock.
int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
- PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
+ PaddedObjectMonitor* block = OrderAccess::load_acquire(&g_block_list);
while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header");
if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) {
address mon = (address)monitor;
address blk = (address)block;
size_t diff = mon - blk;
- assert((diff % sizeof(PaddedEnd<ObjectMonitor>)) == 0, "must be aligned");
+ assert((diff % sizeof(PaddedObjectMonitor)) == 0, "must be aligned");
return 1;
}
- block = (PaddedEnd<ObjectMonitor> *)block->FreeNext;
+ block = (PaddedObjectMonitor*)block->_next_om;
}
return 0;
}
--- a/src/hotspot/share/runtime/synchronizer.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/synchronizer.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -34,12 +34,14 @@
class ObjectMonitor;
class ThreadsList;
+typedef PaddedEnd<ObjectMonitor, DEFAULT_CACHE_LINE_SIZE> PaddedObjectMonitor;
+
struct DeflateMonitorCounters {
- int nInuse; // currently associated with objects
- int nInCirculation; // extant
- int nScavenged; // reclaimed (global and per-thread)
- int perThreadScavenged; // per-thread scavenge total
- double perThreadTimes; // per-thread scavenge times
+ int n_in_use; // currently associated with objects
+ int n_in_circulation; // extant
+ int n_scavenged; // reclaimed (global and per-thread)
+ int per_thread_scavenged; // per-thread scavenge total
+ double per_thread_times; // per-thread scavenge times
};
class ObjectSynchronizer : AllStatic {
@@ -65,22 +67,9 @@
// exit must be implemented non-blocking, since the compiler cannot easily handle
// deoptimization at monitor exit. Hence, it does not take a Handle argument.
- // This is full version of monitor enter and exit. I choose not
- // to use enter() and exit() in order to make sure user be ware
- // of the performance and semantics difference. They are normally
- // used by ObjectLocker etc. The interpreter and compiler use
- // assembly copies of these routines. Please keep them synchronized.
- //
- // attempt_rebias flag is used by UseBiasedLocking implementation
- static void fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias,
- TRAPS);
- static void fast_exit(oop obj, BasicLock* lock, Thread* THREAD);
-
- // WARNING: They are ONLY used to handle the slow cases. They should
- // only be used when the fast cases failed. Use of these functions
- // without previous fast case check may cause fatal error.
- static void slow_enter(Handle obj, BasicLock* lock, TRAPS);
- static void slow_exit(oop obj, BasicLock* lock, Thread* THREAD);
+ // This is the "slow path" version of monitor enter and exit.
+ static void enter(Handle obj, BasicLock* lock, TRAPS);
+ static void exit(oop obj, BasicLock* lock, Thread* THREAD);
// Used only to handle jni locks or other unmatched monitor enter/exit
// Internally they will use heavy weight monitor.
@@ -92,13 +81,13 @@
static void notify(Handle obj, TRAPS);
static void notifyall(Handle obj, TRAPS);
- static bool quick_notify(oopDesc* obj, Thread* Self, bool All);
- static bool quick_enter(oop obj, Thread* Self, BasicLock* Lock);
+ static bool quick_notify(oopDesc* obj, Thread* self, bool All);
+ static bool quick_enter(oop obj, Thread* self, BasicLock* Lock);
// Special internal-use-only method for use by JVM infrastructure
// that needs to wait() on a java-level object but that can't risk
// throwing unexpected InterruptedExecutionExceptions.
- static void waitUninterruptibly(Handle obj, jlong Millis, Thread * THREAD);
+ static void wait_uninterruptibly(Handle obj, jlong Millis, Thread* THREAD);
// used by classloading to free classloader object lock,
// wait on an internal lock, and reclaim original lock
@@ -106,14 +95,14 @@
static intptr_t complete_exit(Handle obj, TRAPS);
static void reenter (Handle obj, intptr_t recursion, TRAPS);
- // thread-specific and global objectMonitor free list accessors
- static ObjectMonitor * omAlloc(Thread * Self);
- static void omRelease(Thread * Self, ObjectMonitor * m,
- bool FromPerThreadAlloc);
- static void omFlush(Thread * Self);
+ // thread-specific and global ObjectMonitor free list accessors
+ static ObjectMonitor* om_alloc(Thread* self);
+ static void om_release(Thread* self, ObjectMonitor* m,
+ bool FromPerThreadAlloc);
+ static void om_flush(Thread* self);
// Inflate light weight monitor to heavy weight monitor
- static ObjectMonitor* inflate(Thread * Self, oop obj, const InflateCause cause);
+ static ObjectMonitor* inflate(Thread* self, oop obj, const InflateCause cause);
// This version is only for internal use
static void inflate_helper(oop obj);
static const char* inflate_cause_name(const InflateCause cause);
@@ -121,11 +110,11 @@
// Returns the identity hash value for an oop
// NOTE: It may cause monitor inflation
static intptr_t identity_hash_value_for(Handle obj);
- static intptr_t FastHashCode(Thread * Self, oop obj);
+ static intptr_t FastHashCode(Thread* self, oop obj);
// java.lang.Thread support
static bool current_thread_holds_lock(JavaThread* thread, Handle h_obj);
- static LockOwnership query_lock_ownership(JavaThread * self, Handle h_obj);
+ static LockOwnership query_lock_ownership(JavaThread* self, Handle h_obj);
static JavaThread* get_lock_owner(ThreadsList * t_list, Handle h_obj);
@@ -142,12 +131,12 @@
static void finish_deflate_idle_monitors(DeflateMonitorCounters* counters);
// For a given monitor list: global or per-thread, deflate idle monitors
- static int deflate_monitor_list(ObjectMonitor** listheadp,
- ObjectMonitor** freeHeadp,
- ObjectMonitor** freeTailp);
+ static int deflate_monitor_list(ObjectMonitor** list_p,
+ ObjectMonitor** free_head_p,
+ ObjectMonitor** free_tail_p);
static bool deflate_monitor(ObjectMonitor* mid, oop obj,
- ObjectMonitor** freeHeadp,
- ObjectMonitor** freeTailp);
+ ObjectMonitor** free_head_p,
+ ObjectMonitor** free_tail_p);
static bool is_cleanup_needed();
static void oops_do(OopClosure* f);
// Process oops in thread local used monitors
@@ -155,13 +144,13 @@
// debugging
static void audit_and_print_stats(bool on_exit);
- static void chk_free_entry(JavaThread * jt, ObjectMonitor * n,
+ static void chk_free_entry(JavaThread* jt, ObjectMonitor* n,
outputStream * out, int *error_cnt_p);
static void chk_global_free_list_and_count(outputStream * out,
int *error_cnt_p);
static void chk_global_in_use_list_and_count(outputStream * out,
int *error_cnt_p);
- static void chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
+ static void chk_in_use_entry(JavaThread* jt, ObjectMonitor* n,
outputStream * out, int *error_cnt_p);
static void chk_per_thread_in_use_list_and_count(JavaThread *jt,
outputStream * out,
@@ -178,14 +167,14 @@
enum { _BLOCKSIZE = 128 };
// global list of blocks of monitors
- static PaddedEnd<ObjectMonitor> * volatile gBlockList;
+ static PaddedObjectMonitor* volatile g_block_list;
// global monitor free list
- static ObjectMonitor * volatile gFreeList;
+ static ObjectMonitor* volatile g_free_list;
// global monitor in-use list, for moribund threads,
// monitors they inflated need to be scanned for deflation
- static ObjectMonitor * volatile gOmInUseList;
- // count of entries in gOmInUseList
- static int gOmInUseCount;
+ static ObjectMonitor* volatile g_om_in_use_list;
+ // count of entries in g_om_in_use_list
+ static int g_om_in_use_count;
// Process oops in all global used monitors (i.e. moribund thread's monitors)
static void global_used_oops_do(OopClosure* f);
@@ -194,9 +183,9 @@
// Support for SynchronizerTest access to GVars fields:
static u_char* get_gvars_addr();
- static u_char* get_gvars_hcSequence_addr();
+ static u_char* get_gvars_hc_sequence_addr();
static size_t get_gvars_size();
- static u_char* get_gvars_stwRandom_addr();
+ static u_char* get_gvars_stw_random_addr();
};
// ObjectLocker enforces balanced locking and can never throw an
@@ -211,13 +200,13 @@
BasicLock _lock;
bool _dolock; // default true
public:
- ObjectLocker(Handle obj, Thread* thread, bool doLock = true);
+ ObjectLocker(Handle obj, Thread* thread, bool do_lock = true);
~ObjectLocker();
// Monitor behavior
void wait(TRAPS) { ObjectSynchronizer::wait(_obj, 0, CHECK); } // wait forever
void notify_all(TRAPS) { ObjectSynchronizer::notifyall(_obj, CHECK); }
- void waitUninterruptibly(TRAPS) { ObjectSynchronizer::waitUninterruptibly(_obj, 0, CHECK); }
+ void wait_uninterruptibly(TRAPS) { ObjectSynchronizer::wait_uninterruptibly(_obj, 0, CHECK); }
// complete_exit gives up lock completely, returning recursion count
// reenter reclaims lock with original recursion count
intptr_t complete_exit(TRAPS) { return ObjectSynchronizer::complete_exit(_obj, THREAD); }
--- a/src/hotspot/share/runtime/thread.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/thread.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -259,11 +259,11 @@
_current_pending_monitor_is_from_java = true;
_current_waiting_monitor = NULL;
_num_nested_signal = 0;
- omFreeList = NULL;
- omFreeCount = 0;
- omFreeProvision = 32;
- omInUseList = NULL;
- omInUseCount = 0;
+ om_free_list = NULL;
+ om_free_count = 0;
+ om_free_provision = 32;
+ om_in_use_list = NULL;
+ om_in_use_count = 0;
#ifdef ASSERT
_visited_for_critical_count = false;
@@ -4414,8 +4414,8 @@
void Threads::remove(JavaThread* p, bool is_daemon) {
- // Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread.
- ObjectSynchronizer::omFlush(p);
+ // Reclaim the ObjectMonitors from the om_in_use_list and om_free_list of the moribund thread.
+ ObjectSynchronizer::om_flush(p);
// Extra scope needed for Thread_lock, so we can check
// that we do not remove thread without safepoint code notice
--- a/src/hotspot/share/runtime/thread.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/thread.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -408,13 +408,13 @@
// ObjectMonitor on which this thread called Object.wait()
ObjectMonitor* _current_waiting_monitor;
- // Private thread-local objectmonitor list - a simple cache organized as a SLL.
+ // Per-thread ObjectMonitor lists:
public:
- ObjectMonitor* omFreeList;
- int omFreeCount; // length of omFreeList
- int omFreeProvision; // reload chunk size
- ObjectMonitor* omInUseList; // SLL to track monitors in circulation
- int omInUseCount; // length of omInUseList
+ ObjectMonitor* om_free_list; // SLL of free ObjectMonitors
+ int om_free_count; // # on om_free_list
+ int om_free_provision; // # to try to allocate next
+ ObjectMonitor* om_in_use_list; // SLL of in-use ObjectMonitors
+ int om_in_use_count; // # on om_in_use_list
#ifdef ASSERT
private:
@@ -522,7 +522,7 @@
os::set_native_thread_name(name);
}
- ObjectMonitor** omInUseList_addr() { return (ObjectMonitor **)&omInUseList; }
+ ObjectMonitor** om_in_use_list_addr() { return (ObjectMonitor **)&om_in_use_list; }
Monitor* SR_lock() const { return _SR_lock; }
bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -167,8 +167,6 @@
typedef Hashtable<InstanceKlass*, mtClass> KlassHashtable;
typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
-typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
-
//--------------------------------------------------------------------------------
// VM_STRUCTS
//
@@ -914,11 +912,11 @@
volatile_nonstatic_field(ObjectMonitor, _contentions, jint) \
volatile_nonstatic_field(ObjectMonitor, _waiters, jint) \
volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \
- nonstatic_field(ObjectMonitor, FreeNext, ObjectMonitor*) \
+ nonstatic_field(ObjectMonitor, _next_om, ObjectMonitor*) \
volatile_nonstatic_field(BasicLock, _displaced_header, markWord) \
nonstatic_field(BasicObjectLock, _lock, BasicLock) \
nonstatic_field(BasicObjectLock, _obj, oop) \
- static_ptr_volatile_field(ObjectSynchronizer, gBlockList, PaddedObjectMonitor*) \
+ static_ptr_volatile_field(ObjectSynchronizer, g_block_list, PaddedObjectMonitor*) \
\
/*********************/ \
/* Matcher (C2 only) */ \
--- a/src/hotspot/share/runtime/vmStructs.hpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/runtime/vmStructs.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -168,7 +168,7 @@
{ QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, &typeName::fieldName },
// This macro generates a VMStructEntry line for a static pointer volatile field,
-// e.g.: "static ObjectMonitor * volatile gBlockList;"
+// e.g.: "static ObjectMonitor * volatile g_block_list;"
#define GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \
{ QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (void *)&typeName::fieldName },
@@ -202,7 +202,7 @@
{type* dummy = &typeName::fieldName; }
// This macro checks the type of a static pointer volatile VMStructEntry by comparing pointer types,
-// e.g.: "static ObjectMonitor * volatile gBlockList;"
+// e.g.: "static ObjectMonitor * volatile g_block_list;"
#define CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \
{type volatile * dummy = &typeName::fieldName; }
--- a/src/hotspot/share/services/attachListener.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/services/attachListener.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -331,7 +331,7 @@
out->print_cr("flag name is missing");
return JNI_ERR;
}
- JVMFlag* f = JVMFlag::find_flag((char*)name, strlen(name));
+ JVMFlag* f = JVMFlag::find_flag(name);
if (f) {
f->print_as_flag(out);
out->cr();
--- a/src/hotspot/share/services/dtraceAttacher.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/services/dtraceAttacher.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -50,9 +50,9 @@
}
};
-static void set_bool_flag(const char* flag, bool value) {
- JVMFlag::boolAtPut((char*)flag, strlen(flag), &value,
- JVMFlag::ATTACH_ON_DEMAND);
+static void set_bool_flag(const char* name, bool value) {
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::boolAtPut(flag, &value, JVMFlag::ATTACH_ON_DEMAND);
}
// Enable only the "fine grained" flags. Do *not* touch
--- a/src/hotspot/share/services/management.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/services/management.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1546,7 +1546,7 @@
Handle sh(THREAD, s);
char* str = java_lang_String::as_utf8_string(s);
- JVMFlag* flag = JVMFlag::find_flag(str, strlen(str));
+ JVMFlag* flag = JVMFlag::find_flag(str);
if (flag != NULL &&
add_global_entry(env, sh, &globals[i], flag, THREAD)) {
num_entries++;
--- a/src/hotspot/share/services/writeableFlags.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/services/writeableFlags.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -38,8 +38,8 @@
strncat(buffer, src, TEMP_BUF_SIZE - 1 - strlen(buffer));
}
-static void print_flag_error_message_bounds(const char* name, char* buffer) {
- JVMFlagRange* range = JVMFlagRangeList::find(name);
+static void print_flag_error_message_bounds(const JVMFlag* flag, char* buffer) {
+ JVMFlagRange* range = JVMFlagRangeList::find(flag);
if (range != NULL) {
buffer_concat(buffer, "must have value in range ");
@@ -59,11 +59,12 @@
}
}
-static void print_flag_error_message_if_needed(JVMFlag::Error error, const char* name, FormatBuffer<80>& err_msg) {
+static void print_flag_error_message_if_needed(JVMFlag::Error error, const JVMFlag* flag, FormatBuffer<80>& err_msg) {
if (error == JVMFlag::SUCCESS) {
return;
}
+ const char* name = flag->_name;
char buffer[TEMP_BUF_SIZE] = {'\0'};
if ((error != JVMFlag::MISSING_NAME) && (name != NULL)) {
buffer_concat(buffer, name);
@@ -79,7 +80,7 @@
case JVMFlag::NON_WRITABLE:
buffer_concat(buffer, "flag is not writeable."); break;
case JVMFlag::OUT_OF_BOUNDS:
- if (name != NULL) { print_flag_error_message_bounds(name, buffer); } break;
+ if (name != NULL) { print_flag_error_message_bounds(flag, buffer); } break;
case JVMFlag::VIOLATES_CONSTRAINT:
buffer_concat(buffer, "value violates its flag's constraint."); break;
case JVMFlag::INVALID_FLAG:
@@ -107,8 +108,9 @@
}
JVMFlag::Error WriteableFlags::set_bool_flag(const char* name, bool value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::boolAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::boolAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -124,8 +126,9 @@
}
JVMFlag::Error WriteableFlags::set_int_flag(const char* name, int value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::intAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::intAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -141,8 +144,9 @@
}
JVMFlag::Error WriteableFlags::set_uint_flag(const char* name, uint value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::uintAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::uintAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -158,8 +162,9 @@
}
JVMFlag::Error WriteableFlags::set_intx_flag(const char* name, intx value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::intxAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::intxAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -175,8 +180,9 @@
}
JVMFlag::Error WriteableFlags::set_uintx_flag(const char* name, uintx value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::uintxAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::uintxAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -192,8 +198,9 @@
}
JVMFlag::Error WriteableFlags::set_uint64_t_flag(const char* name, uint64_t value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::uint64_tAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::uint64_tAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -209,8 +216,9 @@
}
JVMFlag::Error WriteableFlags::set_size_t_flag(const char* name, size_t value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::size_tAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::size_tAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -226,15 +234,17 @@
}
JVMFlag::Error WriteableFlags::set_double_flag(const char* name, double value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::doubleAtPut(name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::doubleAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
// set a string global flag using value from AttachOperation
JVMFlag::Error WriteableFlags::set_ccstr_flag(const char* name, const char* value, JVMFlag::Flags origin, FormatBuffer<80>& err_msg) {
- JVMFlag::Error err = JVMFlag::ccstrAtPut((char*)name, &value, origin);
- print_flag_error_message_if_needed(err, name, err_msg);
+ JVMFlag* flag = JVMFlag::find_flag(name);
+ JVMFlag::Error err = JVMFlag::ccstrAtPut(flag, &value, origin);
+ print_flag_error_message_if_needed(err, flag, err_msg);
return err;
}
@@ -267,7 +277,7 @@
return JVMFlag::MISSING_VALUE;
}
- JVMFlag* f = JVMFlag::find_flag((char*)name, strlen(name));
+ JVMFlag* f = JVMFlag::find_flag(name);
if (f) {
// only writeable flags are allowed to be set
if (f->is_writeable()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/classpathStream.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019, 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 "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
+#include "utilities/classpathStream.hpp"
+
+const char* ClasspathStream::get_next() {
+ while (_class_path[_end] != '\0' && _class_path[_end] != os::path_separator()[0]) {
+ _end++;
+ }
+ int path_len = _end - _start;
+ char* path = NEW_RESOURCE_ARRAY(char, path_len + 1);
+ strncpy(path, &_class_path[_start], path_len);
+ path[path_len] = '\0';
+
+ while (_class_path[_end] == os::path_separator()[0]) {
+ _end++;
+ }
+ _start = _end;
+ return path;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/classpathStream.hpp Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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_UTILITIES_CLASSPATHSTREAM_HPP
+#define SHARE_UTILITIES_CLASSPATHSTREAM_HPP
+
+class ClasspathStream : public StackObj {
+ const char* _class_path;
+ int _len;
+ int _start;
+ int _end;
+
+public:
+ ClasspathStream(const char* class_path) {
+ _class_path = class_path;
+ _len = (int)strlen(class_path);
+ _start = 0;
+ _end = 0;
+ }
+
+ bool has_next() {
+ return _start < _len;
+ }
+
+ const char* get_next();
+};
+
+#endif // SHARE_UTILITIES_CLASSPATHSTREAM_HPP
--- a/src/hotspot/share/utilities/globalDefinitions.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/utilities/globalDefinitions.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/utilities/virtualizationSupport.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/src/hotspot/share/utilities/virtualizationSupport.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -24,6 +24,7 @@
*/
#include "precompiled.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/virtualizationSupport.hpp"
@@ -101,4 +102,3 @@
}
}
}
-
--- a/src/java.base/share/classes/java/lang/Math.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/lang/Math.java Thu Aug 29 16:11:22 2019 +0530
@@ -952,6 +952,7 @@
/**
* Returns the argument incremented by one, throwing an exception if the
* result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MAX_VALUE the maximum value}.
*
* @param a the value to increment
* @return the result
@@ -970,6 +971,7 @@
/**
* Returns the argument incremented by one, throwing an exception if the
* result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MAX_VALUE the maximum value}.
*
* @param a the value to increment
* @return the result
@@ -988,6 +990,7 @@
/**
* Returns the argument decremented by one, throwing an exception if the
* result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MIN_VALUE the minimum value}.
*
* @param a the value to decrement
* @return the result
@@ -1006,6 +1009,7 @@
/**
* Returns the argument decremented by one, throwing an exception if the
* result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MIN_VALUE the minimum value}.
*
* @param a the value to decrement
* @return the result
@@ -1024,6 +1028,7 @@
/**
* Returns the negation of the argument, throwing an exception if the
* result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MIN_VALUE the minimum value}.
*
* @param a the value to negate
* @return the result
@@ -1042,6 +1047,7 @@
/**
* Returns the negation of the argument, throwing an exception if the
* result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MIN_VALUE the minimum value}.
*
* @param a the value to negate
* @return the result
--- a/src/java.base/share/classes/java/lang/StrictMath.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/lang/StrictMath.java Thu Aug 29 16:11:22 2019 +0530
@@ -837,6 +837,7 @@
/**
* Returns the argument incremented by one,
* throwing an exception if the result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MAX_VALUE the maximum value}.
*
* @param a the value to increment
* @return the result
@@ -851,6 +852,7 @@
/**
* Returns the argument incremented by one,
* throwing an exception if the result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MAX_VALUE the maximum value}.
*
* @param a the value to increment
* @return the result
@@ -865,6 +867,7 @@
/**
* Returns the argument decremented by one,
* throwing an exception if the result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MIN_VALUE the minimum value}.
*
* @param a the value to decrement
* @return the result
@@ -879,6 +882,7 @@
/**
* Returns the argument decremented by one,
* throwing an exception if the result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MIN_VALUE the minimum value}.
*
* @param a the value to decrement
* @return the result
@@ -893,6 +897,7 @@
/**
* Returns the negation of the argument,
* throwing an exception if the result overflows an {@code int}.
+ * The overflow only occurs for {@linkplain Integer#MIN_VALUE the minimum value}.
*
* @param a the value to negate
* @return the result
@@ -907,6 +912,7 @@
/**
* Returns the negation of the argument,
* throwing an exception if the result overflows a {@code long}.
+ * The overflow only occurs for {@linkplain Long#MIN_VALUE the minimum value}.
*
* @param a the value to negate
* @return the result
--- a/src/java.base/share/classes/java/net/InterfaceAddress.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/net/InterfaceAddress.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.net;
+import java.util.Objects;
+
/**
* This class represents a Network Interface address. In short it's an
* IP address, a subnet mask and a broadcast address when the address is
@@ -99,17 +101,17 @@
* @see java.net.InterfaceAddress#hashCode()
*/
public boolean equals(Object obj) {
- if (!(obj instanceof InterfaceAddress)) {
- return false;
+ if (obj instanceof InterfaceAddress) {
+ InterfaceAddress cmp = (InterfaceAddress) obj;
+
+ if (Objects.equals(address, cmp.address) &&
+ Objects.equals(broadcast, cmp.broadcast) &&
+ maskLength == cmp.maskLength)
+ {
+ return true;
+ }
}
- InterfaceAddress cmp = (InterfaceAddress) obj;
- if ( !(address == null ? cmp.address == null : address.equals(cmp.address)) )
- return false;
- if ( !(broadcast == null ? cmp.broadcast == null : broadcast.equals(cmp.broadcast)) )
- return false;
- if (maskLength != cmp.maskLength)
- return false;
- return true;
+ return false;
}
/**
--- a/src/java.base/share/classes/java/net/ProxySelector.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/net/ProxySelector.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -143,7 +143,9 @@
* contain one element of type
* {@link java.net.Proxy Proxy}
* that represents a direct connection.
- * @throws IllegalArgumentException if the argument is null
+ * @throws IllegalArgumentException if the argument is null or if
+ * the protocol or host cannot be determined from the provided
+ * {@code uri}
*/
public abstract List<Proxy> select(URI uri);
--- a/src/java.base/share/classes/java/net/ServerSocket.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/net/ServerSocket.java Thu Aug 29 16:11:22 2019 +0530
@@ -710,6 +710,10 @@
/**
* Returns the binding state of the ServerSocket.
+ * <p>
+ * If the socket was bound prior to being {@linkplain #close closed},
+ * then this method will continue to return {@code true}
+ * after the socket is closed.
*
* @return true if the ServerSocket successfully bound to an address
* @since 1.4
--- a/src/java.base/share/classes/java/net/URLStreamHandler.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/net/URLStreamHandler.java Thu Aug 29 16:11:22 2019 +0530
@@ -30,6 +30,7 @@
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
+import java.util.Objects;
import sun.net.util.IPAddressUtil;
import sun.net.www.ParseUtil;
@@ -343,10 +344,7 @@
* @since 1.3
*/
protected boolean equals(URL u1, URL u2) {
- String ref1 = u1.getRef();
- String ref2 = u2.getRef();
- return (ref1 == ref2 || (ref1 != null && ref1.equals(ref2))) &&
- sameFile(u1, u2);
+ return Objects.equals(u1.getRef(), u2.getRef()) && sameFile(u1, u2);
}
/**
--- a/src/java.base/share/classes/java/text/AttributedString.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/text/AttributedString.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -1100,8 +1100,7 @@
return false;
}
AttributeEntry other = (AttributeEntry) o;
- return other.key.equals(key) &&
- (value == null ? other.value == null : other.value.equals(value));
+ return other.key.equals(key) && Objects.equals(other.value, value);
}
public Attribute getKey() {
--- a/src/java.base/share/classes/java/util/TreeMap.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/util/TreeMap.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -311,8 +311,7 @@
public void putAll(Map<? extends K, ? extends V> map) {
int mapSize = map.size();
if (size==0 && mapSize!=0 && map instanceof SortedMap) {
- Comparator<?> c = ((SortedMap<?,?>)map).comparator();
- if (c == comparator || (c != null && c.equals(comparator))) {
+ if (Objects.equals(comparator, ((SortedMap<?,?>)map).comparator())) {
++modCount;
try {
buildFromSorted(mapSize, map.entrySet().iterator(),
--- a/src/java.base/share/classes/java/util/TreeSet.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/java/util/TreeSet.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -302,9 +302,7 @@
m instanceof TreeMap) {
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
- Comparator<?> cc = set.comparator();
- Comparator<? super E> mc = map.comparator();
- if (cc==mc || (cc != null && cc.equals(mc))) {
+ if (Objects.equals(set.comparator(), map.comparator())) {
map.addAllForTreeSet(set, PRESENT);
return true;
}
--- a/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java Thu Aug 29 16:11:22 2019 +0530
@@ -24,6 +24,8 @@
*/
package jdk.internal.math;
+import jdk.internal.misc.VM;
+
import java.math.BigInteger;
import java.util.Arrays;
//@ model import org.jmlspecs.models.JMLMath;
@@ -64,52 +66,9 @@
@ }
@*/
- static final int[] SMALL_5_POW = {
- 1,
- 5,
- 5 * 5,
- 5 * 5 * 5,
- 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
- };
+ static final int[] SMALL_5_POW;
- static final long[] LONG_5_POW = {
- 1L,
- 5L,
- 5L * 5,
- 5L * 5 * 5,
- 5L * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- };
+ static final long[] LONG_5_POW;
// Maximum size of cache of powers of 5 as FDBigIntegers.
private static final int MAX_FIVE_POW = 340;
@@ -117,30 +76,84 @@
// Cache of big powers of 5 as FDBigIntegers.
private static final FDBigInteger POW_5_CACHE[];
+ // Zero as an FDBigInteger.
+ public static final FDBigInteger ZERO;
+
+ // Archive proxy
+ private static Object[] archivedCaches;
+
// Initialize FDBigInteger cache of powers of 5.
static {
- POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
- int i = 0;
- while (i < SMALL_5_POW.length) {
- FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
- pow5.makeImmutable();
- POW_5_CACHE[i] = pow5;
- i++;
+ VM.initializeFromArchive(FDBigInteger.class);
+ Object[] caches = archivedCaches;
+ if (caches == null) {
+ long[] long5pow = {
+ 1L,
+ 5L,
+ 5L * 5,
+ 5L * 5 * 5,
+ 5L * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ };
+ int[] small5pow = {
+ 1,
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+ FDBigInteger[] pow5cache = new FDBigInteger[MAX_FIVE_POW];
+ int i = 0;
+ while (i < small5pow.length) {
+ FDBigInteger pow5 = new FDBigInteger(new int[] { small5pow[i] }, 0);
+ pow5.makeImmutable();
+ pow5cache[i] = pow5;
+ i++;
+ }
+ FDBigInteger prev = pow5cache[i - 1];
+ while (i < MAX_FIVE_POW) {
+ pow5cache[i] = prev = prev.mult(5);
+ prev.makeImmutable();
+ i++;
+ }
+ FDBigInteger zero = new FDBigInteger(new int[0], 0);
+ zero.makeImmutable();
+ archivedCaches = caches = new Object[] {small5pow, long5pow, pow5cache, zero};
}
- FDBigInteger prev = POW_5_CACHE[i - 1];
- while (i < MAX_FIVE_POW) {
- POW_5_CACHE[i] = prev = prev.mult(5);
- prev.makeImmutable();
- i++;
- }
- }
-
- // Zero as an FDBigInteger.
- public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
-
- // Ensure ZERO is immutable.
- static {
- ZERO.makeImmutable();
+ SMALL_5_POW = (int[])caches[0];
+ LONG_5_POW = (long[])caches[1];
+ POW_5_CACHE = (FDBigInteger[])caches[2];
+ ZERO = (FDBigInteger)caches[3];
}
// Constant for casting an int to a long via bitwise AND.
--- a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java Thu Aug 29 16:11:22 2019 +0530
@@ -131,32 +131,32 @@
* Converts a floating point value into an ASCII <code>String</code>.
* @return The value converted to a <code>String</code>.
*/
- public String toJavaFormatString();
+ String toJavaFormatString();
/**
* Appends a floating point value to an <code>Appendable</code>.
* @param buf The <code>Appendable</code> to receive the value.
*/
- public void appendTo(Appendable buf);
+ void appendTo(Appendable buf);
/**
* Retrieves the decimal exponent most closely corresponding to this value.
* @return The decimal exponent.
*/
- public int getDecimalExponent();
+ int getDecimalExponent();
/**
* Retrieves the value as an array of digits.
* @param digits The digit array.
* @return The number of valid digits copied into the array.
*/
- public int getDigits(char[] digits);
+ int getDigits(char[] digits);
/**
* Indicates the sign of the value.
* @return {@code value < 0.0}.
*/
- public boolean isNegative();
+ boolean isNegative();
/**
* Indicates whether the value is either infinite or not a number.
@@ -164,7 +164,7 @@
* @return <code>true</code> if and only if the value is <code>NaN</code>
* or infinite.
*/
- public boolean isExceptional();
+ boolean isExceptional();
/**
* Indicates whether the value was rounded up during the binary to ASCII
@@ -172,14 +172,14 @@
*
* @return <code>true</code> if and only if the value was rounded up.
*/
- public boolean digitsRoundedUp();
+ boolean digitsRoundedUp();
/**
* Indicates whether the binary to ASCII conversion was exact.
*
* @return <code>true</code> if any only if the conversion was exact.
*/
- public boolean decimalDigitsExact();
+ boolean decimalDigitsExact();
}
/**
@@ -321,7 +321,7 @@
@Override
public int getDigits(char[] digits) {
- System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+ System.arraycopy(this.digits, firstDigitIndex, digits, 0, this.nDigits);
return this.nDigits;
}
@@ -849,7 +849,7 @@
* </pre>
*/
private static int insignificantDigitsForPow2(int p2) {
- if(p2>1 && p2 < insignificantDigitsNumber.length) {
+ if (p2 > 1 && p2 < insignificantDigitsNumber.length) {
return insignificantDigitsNumber[p2];
}
return 0;
@@ -862,7 +862,7 @@
* for ( i = 0; insignificant >= 10L; i++ )
* insignificant /= 10L;
*/
- private static int[] insignificantDigitsNumber = {
+ private static final int[] insignificantDigitsNumber = {
0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
@@ -1873,11 +1873,11 @@
} // look for and process decimal floating-point string
char[] digits = new char[ len ];
- int nDigits= 0;
boolean decSeen = false;
+ int nDigits = 0;
int decPt = 0;
int nLeadZero = 0;
- int nTrailZero= 0;
+ int nTrailZero = 0;
skipLeadingZerosLoop:
while (i < len) {
@@ -2137,9 +2137,9 @@
// signed zero.
//
- String significandString = null;
- int signifLength = 0;
- int exponentAdjust = 0;
+ String significandString;
+ int signifLength;
+ int exponentAdjust;
{
int leftDigits = 0; // number of meaningful digits to
// left of "decimal" point
@@ -2246,7 +2246,7 @@
boolean round = false;
boolean sticky = false;
- int nextShift = 0;
+ int nextShift;
long significand = 0L;
// First iteration is different, since we only copy
// from the leading significand bit; one more exponent
@@ -2525,7 +2525,6 @@
* Returns <code>s</code> with any leading zeros removed.
*/
static String stripLeadingZeros(String s) {
-// return s.replaceFirst("^0+", "");
if(!s.isEmpty() && s.charAt(0)=='0') {
for(int i=1; i<s.length(); i++) {
if(s.charAt(i)!='0') {
--- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Thu Aug 29 16:11:22 2019 +0530
@@ -44,6 +44,7 @@
import java.net.URI;
import java.net.Proxy;
import java.net.ProxySelector;
+import java.util.List;
import java.util.StringTokenizer;
import java.util.Iterator;
import java.security.Permission;
@@ -242,7 +243,13 @@
});
if (sel != null) {
URI uri = sun.net.www.ParseUtil.toURI(url);
- Iterator<Proxy> it = sel.select(uri).iterator();
+ final List<Proxy> proxies;
+ try {
+ proxies = sel.select(uri);
+ } catch (IllegalArgumentException iae) {
+ throw new IOException("Failed to select a proxy", iae);
+ }
+ final Iterator<Proxy> it = proxies.iterator();
while (it.hasNext()) {
p = it.next();
if (p == null || p == Proxy.NO_PROXY ||
--- a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
* questions.
*/
-/*-
+/*
* FTP stream opener
*/
@@ -34,6 +34,7 @@
import java.net.Proxy;
import java.util.Map;
import java.util.HashMap;
+import java.util.Objects;
import sun.net.ftp.FtpClient;
import sun.net.www.protocol.http.HttpURLConnection;
@@ -47,8 +48,7 @@
protected boolean equals(URL u1, URL u2) {
String userInfo1 = u1.getUserInfo();
String userInfo2 = u2.getUserInfo();
- return super.equals(u1, u2) &&
- (userInfo1 == null? userInfo2 == null: userInfo1.equals(userInfo2));
+ return super.equals(u1, u2) && Objects.equals(userInfo1, userInfo2);
}
protected java.net.URLConnection openConnection(URL u)
--- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Aug 29 16:11:22 2019 +0530
@@ -1178,7 +1178,13 @@
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
logger.finest("ProxySelector Request for " + uri);
}
- Iterator<Proxy> it = sel.select(uri).iterator();
+ final List<Proxy> proxies;
+ try {
+ proxies = sel.select(uri);
+ } catch (IllegalArgumentException iae) {
+ throw new IOException("Failed to select a proxy", iae);
+ }
+ final Iterator<Proxy> it = proxies.iterator();
Proxy p;
while (it.hasNext()) {
p = it.next();
--- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Thu Aug 29 16:11:22 2019 +0530
@@ -274,8 +274,7 @@
* with the same parameters.
*/
public boolean equals(AlgorithmId other) {
- boolean paramsEqual =
- (params == null ? other.params == null : params.equals(other.params));
+ boolean paramsEqual = Objects.equals(other.params, params);
return (algid.equals((Object)other.algid) && paramsEqual);
}
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,21 +25,19 @@
package com.sun.xml.internal.stream;
-import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
-
-import javax.xml.stream.XMLOutputFactory ;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stax.StAXResult;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.PropertyManager;
-
import com.sun.xml.internal.stream.writers.XMLDOMWriterImpl;
import com.sun.xml.internal.stream.writers.XMLEventWriterImpl;
import com.sun.xml.internal.stream.writers.XMLStreamWriterImpl;
@@ -47,7 +45,7 @@
/**
* This class provides the implementation of XMLOutputFactory.
*
- * @author Neeraj Bajaj,
+ * @author Neeraj Bajaj,
* @author k venugopal
*/
public class XMLOutputFactoryImpl extends XMLOutputFactory {
@@ -63,31 +61,39 @@
*/
boolean fReuseInstance = false;
- /** Creates a new instance of XMLOutputFactory */
+ /**
+ * Creates a new instance of XMLOutputFactory
+ */
public XMLOutputFactoryImpl() {
}
- public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
- return createXMLEventWriter(outputStream, null);
+ public XMLEventWriter createXMLEventWriter(OutputStream outputStream)
+ throws XMLStreamException {
+ return createXMLEventWriter(outputStream, null);
}
- public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
+ public XMLEventWriter createXMLEventWriter(OutputStream outputStream, String encoding)
+ throws XMLStreamException {
return new XMLEventWriterImpl(createXMLStreamWriter(outputStream, encoding));
}
- public javax.xml.stream.XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
+ public XMLEventWriter createXMLEventWriter(Result result)
+ throws XMLStreamException {
- if (result instanceof StAXResult && ((StAXResult)result).getXMLEventWriter() != null)
- return ((StAXResult)result).getXMLEventWriter();
+ if (result instanceof StAXResult && ((StAXResult) result).getXMLEventWriter() != null) {
+ return ((StAXResult) result).getXMLEventWriter();
+ }
return new XMLEventWriterImpl(createXMLStreamWriter(result));
}
- public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
+ public XMLEventWriter createXMLEventWriter(java.io.Writer writer)
+ throws XMLStreamException {
return new XMLEventWriterImpl(createXMLStreamWriter(writer));
}
- public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
+ public XMLStreamWriter createXMLStreamWriter(Result result)
+ throws XMLStreamException {
if (result instanceof StreamResult) {
return createXMLStreamWriter((StreamResult) result, null);
@@ -97,57 +103,64 @@
if (((StAXResult) result).getXMLStreamWriter() != null) {
return ((StAXResult) result).getXMLStreamWriter();
} else {
- throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported");
+ throw new UnsupportedOperationException(
+ "Result of type " + result + " is not supported");
}
+ } else if (result.getSystemId() != null) {
+ //this is not correct impl of SAXResult. Keep it for now for compatibility
+ return createXMLStreamWriter(new StreamResult(result.getSystemId()));
} else {
- if (result.getSystemId() !=null) {
- //this is not correct impl of SAXResult. Keep it for now for compatibility
- return createXMLStreamWriter(new StreamResult(result.getSystemId()));
- } else {
- throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported. " +
- "Supported result types are: DOMResult, StAXResult and StreamResult.");
- }
+ throw new UnsupportedOperationException(
+ "Result of type " + result + " is not supported. Supported result "
+ + "types are: DOMResult, StAXResult and StreamResult.");
}
}
- public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
- return createXMLStreamWriter(toStreamResult(null, writer, null) , null);
+ public XMLStreamWriter createXMLStreamWriter(java.io.Writer writer)
+ throws XMLStreamException {
+ return createXMLStreamWriter(toStreamResult(null, writer, null), null);
}
- public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
+ public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream)
+ throws XMLStreamException {
return createXMLStreamWriter(outputStream, null);
}
- public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
- return createXMLStreamWriter(toStreamResult(outputStream, null, null) , encoding);
+ public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream, String encoding)
+ throws XMLStreamException {
+ return createXMLStreamWriter(toStreamResult(outputStream, null, null), encoding);
}
- public Object getProperty(String name) throws java.lang.IllegalArgumentException {
- if(name == null){
+ public Object getProperty(String name)
+ throws IllegalArgumentException {
+ if (name == null) {
throw new IllegalArgumentException("Property not supported");
}
- if(fPropertyManager.containsProperty(name))
+ if (fPropertyManager.containsProperty(name)) {
return fPropertyManager.getProperty(name);
+ }
throw new IllegalArgumentException("Property not supported");
}
public boolean isPropertySupported(String name) {
- if(name == null){
- return false ;
- }
- else{
+ if (name == null) {
+ return false;
+ } else {
return fPropertyManager.containsProperty(name);
}
}
- public void setProperty(String name, Object value) throws java.lang.IllegalArgumentException {
- if(name == null || value == null || !fPropertyManager.containsProperty(name) ){
- throw new IllegalArgumentException("Property "+name+"is not supported");
+ public void setProperty(String name, Object value)
+ throws IllegalArgumentException {
+ if (name == null || value == null || !fPropertyManager.containsProperty(name)) {
+ throw new IllegalArgumentException("Property " + name + "is not supported");
}
- if(name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)){
- fReuseInstance = ((Boolean)value).booleanValue();
- if(DEBUG)System.out.println("fReuseInstance is set to " + fReuseInstance);
+ if (name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)) {
+ fReuseInstance = (Boolean)value;
+ if (DEBUG) {
+ System.out.println("fReuseInstance is set to " + fReuseInstance);
+ }
// TODO: XMLStreamWriters are not Thread safe,
// don't let application think it is optimizing
@@ -157,16 +170,17 @@
+ name
+ " is not supported: XMLStreamWriters are not Thread safe");
}
- }else{//for any other property set the flag
+ } else {//for any other property set the flag
//REVISIT: Even in this case instance can be reused, by passing PropertyManager
fPropertyChanged = true;
}
- fPropertyManager.setProperty(name,value);
+ fPropertyManager.setProperty(name, value);
}
- /** StreamResult object is re-used and the values are set appropriately.
+ /**
+ * StreamResult object is re-used and the values are set appropriately.
*/
- StreamResult toStreamResult(OutputStream os, Writer writer, String systemId){
+ StreamResult toStreamResult(OutputStream os, Writer writer, String systemId) {
StreamResult sr = new StreamResult();
sr.setOutputStream(os);
sr.setWriter(writer);
@@ -174,26 +188,33 @@
return sr;
}
- javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.stream.StreamResult sr, String encoding) throws javax.xml.stream.XMLStreamException {
+ XMLStreamWriter createXMLStreamWriter(StreamResult sr, String encoding)
+ throws XMLStreamException {
//if factory is configured to reuse the instance & this instance can be reused
//& the setProperty() hasn't been called
- try{
- if(fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse() && !fPropertyChanged){
+ try {
+ if (fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse()
+ && !fPropertyChanged) {
fStreamWriter.reset();
fStreamWriter.setOutput(sr, encoding);
- if(DEBUG)System.out.println("reusing instance, object id : " + fStreamWriter);
+ if (DEBUG) {
+ System.out.println("reusing instance, object id : " + fStreamWriter);
+ }
return fStreamWriter;
}
- return fStreamWriter = new XMLStreamWriterImpl(sr, encoding, new PropertyManager(fPropertyManager));
- }catch(java.io.IOException io){
+ return fStreamWriter = new XMLStreamWriterImpl(sr, encoding,
+ new PropertyManager(fPropertyManager));
+ } catch (IOException io) {
throw new XMLStreamException(io);
}
}//createXMLStreamWriter(StreamResult,String)
private static final boolean DEBUG = false;
- /** This flag indicates the change of property. If true,
+ /**
+ * This flag indicates the change of property. If true,
* <code>PropertyManager</code> should be passed when creating
- * <code>XMLStreamWriterImpl</code> */
- private boolean fPropertyChanged ;
+ * <code>XMLStreamWriterImpl</code>
+ */
+ private boolean fPropertyChanged;
}//XMLOutputFactory
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -51,15 +51,16 @@
public class XMLEventWriterImpl implements XMLEventWriter {
//delegate everything to XMLStreamWriter..
- private final XMLStreamWriterBase fStreamWriter;
+ private final XMLStreamWriter fStreamWriter;
private static final boolean DEBUG = false;
/**
- *
+ * Constructs an XMLEventWriterImpl that implements the standard XMLStreamWriter
+ * interface.
* @param streamWriter
*/
public XMLEventWriterImpl(XMLStreamWriter streamWriter) {
- fStreamWriter = (XMLStreamWriterBase) streamWriter;
+ fStreamWriter = streamWriter;
}
/**
@@ -98,9 +99,18 @@
System.out.println("Adding StartDocument = " + startDocument.toString());
}
try {
- fStreamWriter.writeStartDocument(startDocument.getCharacterEncodingScheme(),
- startDocument.getVersion(),
- startDocument.isStandalone(), startDocument.standaloneSet());
+ if (XMLStreamWriterBase.class.isAssignableFrom(fStreamWriter.getClass())) {
+ // internal impl uses the extended interface
+ ((XMLStreamWriterBase)fStreamWriter).writeStartDocument(
+ startDocument.getCharacterEncodingScheme(),
+ startDocument.getVersion(),
+ startDocument.isStandalone(),
+ startDocument.standaloneSet());
+ } else {
+ fStreamWriter.writeStartDocument(
+ startDocument.getCharacterEncodingScheme(),
+ startDocument.getVersion());
+ }
} catch (XMLStreamException e) {
fStreamWriter.writeStartDocument(startDocument.getVersion());
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java Thu Aug 29 16:11:22 2019 +0530
@@ -48,8 +48,8 @@
objectFieldOffset = f.getOffset();
f = type.getField("_owner");
ownerFieldOffset = f.getOffset();
- f = type.getField("FreeNext");
- FreeNextFieldOffset = f.getOffset();
+ f = type.getField("_next_om");
+ nextOMFieldOffset = f.getOffset();
contentionsField = type.getJIntField("_contentions");
waitersField = type.getJIntField("_waiters");
recursionsField = type.getCIntegerField("_recursions");
@@ -83,7 +83,7 @@
public int waiters() { return waitersField.getValue(addr); }
- public Address freeNext() { return addr.getAddressAt(FreeNextFieldOffset); }
+ public Address nextOM() { return addr.getAddressAt(nextOMFieldOffset); }
// FIXME
// void set_queue(void* owner);
@@ -108,7 +108,7 @@
private static long headerFieldOffset;
private static long objectFieldOffset;
private static long ownerFieldOffset;
- private static long FreeNextFieldOffset;
+ private static long nextOMFieldOffset;
private static JIntField contentionsField;
private static JIntField waitersField;
private static CIntegerField recursionsField;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java Wed Aug 28 09:13:01 2019 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java Thu Aug 29 16:11:22 2019 +0530
@@ -44,7 +44,7 @@
Type type;
try {
type = db.lookupType("ObjectSynchronizer");
- gBlockList = type.getAddressField("gBlockList").getValue();
+ gBlockList = type.getAddressField("g_block_list").getValue();
blockSize = db.lookupIntConstant("ObjectSynchronizer::_BLOCKSIZE").intValue();
defaultCacheLineSize = db.lookupIntConstant("DEFAULT_CACHE_LINE_SIZE").intValue();
} catch (RuntimeException e) { }
@@ -101,14 +101,14 @@
}
public boolean hasNext() {
- return (index > 0 || block.freeNext() != null);
+ return (index > 0 || block.nextOM() != null);
}
public Object next() {
Address addr;
if (index == 0) {
// advance to next block
- blockAddr = block.freeNext();
+ blockAddr = block.nextOM();
if (blockAddr == null) {
throw new NoSuchElementException();
}
--- a/test/hotspot/gtest/oops/test_markOop.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/gtest/oops/test_markOop.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -98,9 +98,10 @@
// Lock using biased locking.
BasicObjectLock lock;
lock.set_obj(obj);
- markWord mark = obj->mark().incr_bias_epoch();
- obj->set_mark(mark);
- ObjectSynchronizer::fast_enter(h_obj, lock.lock(), true, THREAD);
+ markWord prototype_header = obj->klass()->prototype_header();
+ markWord mark = obj->mark();
+ markWord biased_mark = markWord::encode((JavaThread*) THREAD, mark.age(), prototype_header.bias_epoch());
+ obj->set_mark(biased_mark);
// Look for the biased_locker in markWord, not prototype_header.
#ifdef _LP64
assert_not_test_pattern(h_obj, "mark(is_biased biased_locker=0x0000000000000000");
--- a/test/hotspot/gtest/runtime/test_os_linux.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/gtest/runtime/test_os_linux.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -27,7 +27,9 @@
#include <sys/mman.h>
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
+#include "utilities/align.hpp"
#include "unittest.hpp"
namespace {
--- a/test/hotspot/gtest/runtime/test_synchronizer.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/gtest/runtime/test_synchronizer.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,9 +30,9 @@
class SynchronizerTest : public ::testing::Test {
public:
static u_char* get_gvars_addr() { return ObjectSynchronizer::get_gvars_addr(); }
- static u_char* get_gvars_hcSequence_addr() { return ObjectSynchronizer::get_gvars_hcSequence_addr(); }
+ static u_char* get_gvars_hc_sequence_addr() { return ObjectSynchronizer::get_gvars_hc_sequence_addr(); }
static size_t get_gvars_size() { return ObjectSynchronizer::get_gvars_size(); }
- static u_char* get_gvars_stwRandom_addr() { return ObjectSynchronizer::get_gvars_stwRandom_addr(); }
+ static u_char* get_gvars_stw_random_addr() { return ObjectSynchronizer::get_gvars_stw_random_addr(); }
};
TEST_VM(SynchronizerTest, sanity) {
@@ -42,27 +42,27 @@
// do some cache line specific sanity checks
u_char *addr_begin = SynchronizerTest::get_gvars_addr();
- u_char *addr_stwRandom = SynchronizerTest::get_gvars_stwRandom_addr();
- u_char *addr_hcSequence = SynchronizerTest::get_gvars_hcSequence_addr();
+ u_char *addr_stw_random = SynchronizerTest::get_gvars_stw_random_addr();
+ u_char *addr_hc_sequence = SynchronizerTest::get_gvars_hc_sequence_addr();
size_t gvars_size = SynchronizerTest::get_gvars_size();
- uint offset_stwRandom = (uint) (addr_stwRandom - addr_begin);
- uint offset_hcSequence = (uint) (addr_hcSequence - addr_begin);
- uint offset_hcSequence_stwRandom = offset_hcSequence - offset_stwRandom;
- uint offset_hcSequence_struct_end = (uint) gvars_size - offset_hcSequence;
+ uint offset_stw_random = (uint) (addr_stw_random - addr_begin);
+ uint offset_hc_sequence = (uint) (addr_hc_sequence - addr_begin);
+ uint offset_hc_sequence_stw_random = offset_hc_sequence - offset_stw_random;
+ uint offset_hc_sequence_struct_end = (uint) gvars_size - offset_hc_sequence;
- EXPECT_GE(offset_stwRandom, cache_line_size)
- << "the SharedGlobals.stwRandom field is closer "
+ EXPECT_GE(offset_stw_random, cache_line_size)
+ << "the SharedGlobals.stw_random field is closer "
<< "to the struct beginning than a cache line which permits "
<< "false sharing.";
- EXPECT_GE(offset_hcSequence_stwRandom, cache_line_size)
- << "the SharedGlobals.stwRandom and "
- << "SharedGlobals.hcSequence fields are closer than a cache "
+ EXPECT_GE(offset_hc_sequence_stw_random, cache_line_size)
+ << "the SharedGlobals.stw_random and "
+ << "SharedGlobals.hc_sequence fields are closer than a cache "
<< "line which permits false sharing.";
- EXPECT_GE(offset_hcSequence_struct_end, cache_line_size)
- << "the SharedGlobals.hcSequence field is closer "
+ EXPECT_GE(offset_hc_sequence_struct_end, cache_line_size)
+ << "the SharedGlobals.hc_sequence field is closer "
<< "to the struct end than a cache line which permits false "
<< "sharing.";
}
--- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp Thu Aug 29 16:11:22 2019 +0530
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "runtime/os.hpp"
#include "unittest.hpp"
+#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
static ::testing::AssertionResult testPageAddress(
--- a/test/hotspot/jtreg/runtime/ErrorHandling/BadNativeStackInErrorHandlingTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/BadNativeStackInErrorHandlingTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -57,7 +57,7 @@
// we should have crashed with a SIGSEGV
output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
- output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+ output_detail.shouldMatch("# +(?:SIGSEGV|SIGBUS|EXCEPTION_ACCESS_VIOLATION).*");
// extract hs-err file
String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
--- a/test/hotspot/jtreg/runtime/ErrorHandling/ErrorFileRedirectTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ErrorFileRedirectTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -58,7 +58,7 @@
// we should have crashed with a SIGSEGV
output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
- output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+ output_detail.shouldMatch("# +(?:SIGSEGV|SIGBUS|EXCEPTION_ACCESS_VIOLATION).*");
// If no redirection happened, we should find a mention of the file in the output.
String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
--- a/test/hotspot/jtreg/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -61,7 +61,7 @@
// we should have crashed with a SIGSEGV
output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
- output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+ output_detail.shouldMatch("# +(?:SIGSEGV|SIGBUS|EXCEPTION_ACCESS_VIOLATION).*");
// extract hs-err file
String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
--- a/test/hotspot/jtreg/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -95,7 +95,7 @@
// we should have crashed with a SIGSEGV
output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
- output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+ output_detail.shouldMatch("# +(?:SIGSEGV|SIGBUS|EXCEPTION_ACCESS_VIOLATION).*");
// VM should have been aborted by WatcherThread
output_detail.shouldMatch(".*timer expired, abort.*");
--- a/test/hotspot/jtreg/runtime/cds/appcds/AppendClasspath.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/AppendClasspath.java Thu Aug 29 16:11:22 2019 +0530
@@ -95,19 +95,5 @@
"-cp", appJar2 + File.pathSeparator + appJar,
"HelloMore")
.assertAbnormalExit(errorMessage1, errorMessage2);
-
- // FAIL: 4) non-existing jar during dump time but jar exists during runtime
- TestCommon.testDump(classPath, TestCommon.list("Hello"));
-
- Files.copy(Paths.get(classDir, "hello.jar"),
- Paths.get(classDir, newFile),
- StandardCopyOption.REPLACE_EXISTING);
-
- TestCommon.run(
- "-cp", classPath,
- "-Xlog:class+path=trace",
- "Hello")
- .assertAbnormalExit(errorMessage1, errorMessage2);
-
}
}
--- a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java Thu Aug 29 16:11:22 2019 +0530
@@ -42,6 +42,11 @@
public class ClassPathAttr {
public static void main(String[] args) throws Exception {
+ testNormalOps();
+ testNonExistentJars();
+ }
+
+ static void testNormalOps() throws Exception {
buildCpAttr("cpattr1", "cpattr1.mf", "CpAttr1", "CpAttr1");
buildCpAttr("cpattr1_long", "cpattr1_long.mf", "CpAttr1", "CpAttr1");
buildCpAttr("cpattr2", "cpattr2.mf", "CpAttr2", "CpAttr2");
@@ -93,6 +98,37 @@
}
}
+ static void testNonExistentJars() throws Exception {
+ buildCpAttr("cpattr6", "cpattr6.mf", "CpAttr6", "CpAttr6");
+
+ String cp = TestCommon.getTestJar("cpattr6.jar");
+ String nonExistPath = System.getProperty("test.classes") + File.separator + "cpattrX.jar";
+ (new File(nonExistPath)).delete();
+
+ TestCommon.testDump(cp, TestCommon.list("CpAttr6"),
+ "-Xlog:class+path");
+
+ TestCommon.run(
+ "-Xlog:class+path",
+ "-cp", cp,
+ "CpAttr6")
+ .assertNormalExit(output -> {
+ output.shouldMatch("should be non-existent: .*cpattrX.jar");
+ });
+
+ // Now make nonExistPath exist. CDS still loads, but archived non-system classes will not be used.
+ Files.copy(Paths.get(cp), Paths.get(nonExistPath),
+ StandardCopyOption.REPLACE_EXISTING);
+
+ TestCommon.run(
+ "-Xlog:class+path",
+ "-cp", cp,
+ "CpAttr6")
+ .assertNormalExit(output -> {
+ output.shouldMatch("Archived non-system classes are disabled because the file .*cpattrX.jar exists");
+ });
+ }
+
private static void buildCpAttr(String jarName, String manifest, String enclosingClassName, String ...testClassNames) throws Exception {
String jarClassesDir = System.getProperty("test.classes") + File.separator + jarName + "_classes";
try { Files.createDirectory(Paths.get(jarClassesDir)); } catch (FileAlreadyExistsException e) { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/NonExistClasspath.java Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Handling of non-existent classpath elements during dump time and run time
+ * @requires vm.cds
+ * @library /test/lib
+ * @modules jdk.jartool/sun.tools.jar
+ * @compile test-classes/Hello.java
+ * @compile test-classes/HelloMore.java
+ * @run driver NonExistClasspath
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class NonExistClasspath {
+ public static void main(String[] args) throws Exception {
+ String appJar = JarBuilder.getOrCreateHelloJar();
+ doTest(appJar, false);
+ doTest(appJar, true);
+ }
+
+ static void doTest(String appJar, boolean bootcp) throws Exception {
+ String classDir = System.getProperty("test.classes");
+ String newFile = "non-exist.jar";
+ String nonExistPath = classDir + File.separator + newFile;
+ final String errorMessage1 = "Unable to use shared archive";
+ final String errorMessage2 = "shared class paths mismatch";
+ final String errorMessage3 = (bootcp ? "BOOT" : "APP") + " classpath mismatch";
+
+ (new File(nonExistPath)).delete();
+
+ String classPath = nonExistPath + File.pathSeparator + appJar;
+ TestCommon.testDump("foobar", TestCommon.list("Hello"), make_args(bootcp, classPath));
+
+ // The nonExistPath doesn't exist yet, so we should be able to run without problem
+ TestCommon.run(make_args(bootcp,
+ classPath,
+ "-Xlog:class+path=trace",
+ "Hello"))
+ .assertNormalExit();
+
+ // Replace nonExistPath with another non-existent file in the CP, it should still work
+ TestCommon.run(make_args(bootcp,
+ nonExistPath + ".duh" + File.pathSeparator + appJar,
+ "-Xlog:class+path=trace",
+ "Hello"))
+ .assertNormalExit();
+
+ // Add a few more non-existent files in the CP, it should still work
+ TestCommon.run(make_args(bootcp,
+ nonExistPath + ".duh" + File.pathSeparator +
+ nonExistPath + ".daa" + File.pathSeparator +
+ nonExistPath + ".boo" + File.pathSeparator +
+ appJar,
+ "-Xlog:class+path=trace",
+ "Hello"))
+ .assertNormalExit();
+
+ // Or, remove all non-existent paths from the CP, it should still work
+ TestCommon.run(make_args(bootcp,
+ appJar,
+ "-Xlog:class+path=trace",
+ "Hello"))
+ .assertNormalExit();
+
+ // Now make nonExistPath exist. CDS will fail to load.
+ Files.copy(Paths.get(classDir, "hello.jar"),
+ Paths.get(classDir, newFile),
+ StandardCopyOption.REPLACE_EXISTING);
+
+ TestCommon.run(make_args(bootcp,
+ classPath,
+ "-Xlog:class+path=trace",
+ "Hello"))
+ .assertAbnormalExit(errorMessage1, errorMessage2, errorMessage3);
+ }
+
+ static String[] make_args(boolean bootcp, String cp, String... suffix) {
+ String args[];
+ if (bootcp) {
+ args = TestCommon.concat("-Xbootclasspath/a:" + cp);
+ } else {
+ args = TestCommon.concat("-cp", cp);
+ }
+
+ return TestCommon.concat(args, suffix);
+ }
+}
--- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java Thu Aug 29 16:11:22 2019 +0530
@@ -61,7 +61,6 @@
public static int offset_version; // CDSFileMapHeaderBase::_version
public static int offset_jvm_ident; // FileMapHeader::_jvm_ident
public static int sp_offset_crc; // CDSFileMapRegion::_crc
- public static int offset_paths_misc_info_size;
public static int file_header_size = -1;// total size of header, variant, need calculation
public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
public static int sp_offset; // offset of CDSFileMapRegion
@@ -117,12 +116,6 @@
// this is not real header size, it is struct size
int_size = wb.getOffsetForName("int_size");
file_header_size = wb.getOffsetForName("file_header_size");
- offset_paths_misc_info_size = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
- offset_magic;
- int path_misc_info_size = (int)readInt(fc, offset_paths_misc_info_size, int_size);
- file_header_size += path_misc_info_size;
- System.out.println("offset_paths_misc_info_size = " + offset_paths_misc_info_size);
- System.out.println("path_misc_info_size = " + path_misc_info_size);
System.out.println("file_header_size = " + file_header_size);
file_header_size = (int)align_up_page(file_header_size);
System.out.println("file_header_size (aligned to page) = " + file_header_size);
@@ -405,10 +398,9 @@
output.shouldNotContain("Checksum verification failed");
copyFile(orgJsaFile, jsa);
- // modify _jvm_ident and _paths_misc_info_size, test should fail
- System.out.println("\n2a. Corrupt _jvm_ident and _paths_misc_info_size, should fail\n");
+ // modify _jvm_ident, test should fail
+ System.out.println("\n2a. Corrupt _jvm_ident, should fail\n");
modifyJvmIdent();
- modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
output = TestCommon.execCommon(execArgs);
output.shouldContain("The shared archive file was created by a different version or build of HotSpot");
output.shouldNotContain("Checksum verification failed");
@@ -422,19 +414,17 @@
output.shouldContain("Hello World");
copyFile(orgJsaFile, jsa);
- // modify _magic and _paths_misc_info_size, test should fail
- System.out.println("\n2c. Corrupt _magic and _paths_misc_info_size, should fail\n");
+ // modify _magic, test should fail
+ System.out.println("\n2c. Corrupt _magic, should fail\n");
modifyHeaderIntField(offset_magic, 0x00000000);
- modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
output = TestCommon.execCommon(execArgs);
output.shouldContain("The shared archive file has a bad magic number");
output.shouldNotContain("Checksum verification failed");
copyFile(orgJsaFile, jsa);
- // modify _version and _paths_misc_info_size, test should fail
- System.out.println("\n2d. Corrupt _version and _paths_misc_info_size, should fail\n");
+ // modify _version, test should fail
+ System.out.println("\n2d. Corrupt _version, should fail\n");
modifyHeaderIntField(offset_version, 0x00000000);
- modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
output = TestCommon.execCommon(execArgs);
output.shouldContain("The shared archive file has the wrong version");
output.shouldNotContain("Checksum verification failed");
--- a/test/hotspot/jtreg/runtime/cds/appcds/TraceLongClasspath.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/runtime/cds/appcds/TraceLongClasspath.java Thu Aug 29 16:11:22 2019 +0530
@@ -24,7 +24,7 @@
/*
* @test
- * @summary ensure -XX:+TraceClassPaths showing entire expecting app classpath
+ * @summary ensure -Xlog:class+path showing entire expecting app classpath
* @requires vm.cds
* @library /test/lib
* @modules jdk.jartool/sun.tools.jar
@@ -85,22 +85,23 @@
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps +
"/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar";
- String myCP = longClassPath + ps + appJar;
+ String dumpCP = longClassPath + ps + appJar;
// Dump an archive with a specified JAR file in -classpath
- TestCommon.testDump(myCP, TestCommon.list("Hello"));
+ TestCommon.testDump(dumpCP, TestCommon.list("Hello"));
- // Then try to execute the archive with a different classpath and with -XX:+TraceClassPaths.
- // The diagnosis "expecting" app classpath trace should show the entire classpath.
+ // Then try to execute the archive with a different classpath and with -Xlog:class+path.
+ // The diagnostic "expecting" app classpath trace should show the entire classpath (excluding any non-existent dump-time paths).
+ String recordedCP = dummyJar + ps + appJar;
TestCommon.run(
- "-XX:+TraceClassPaths", "-Xlog:cds",
+ "-Xlog:class+path", "-Xlog:cds",
"-cp", appJar,
"Hello")
.assertAbnormalExit(output -> {
output.shouldContain("Unable to use shared archive");
output.shouldContain("shared class paths mismatch");
- // the "expecting" app classpath from -XX:+TraceClassPaths should not
+ // the "expecting" app classpath from -Xlog:class+path should not
// be truncated
- output.shouldContain(myCP);
+ output.shouldContain(recordedCP);
});
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/CpAttr6.java Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+public class CpAttr6 {
+ public static void main(String args[]) {
+ System.out.println("Test passed");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/cpattr6.mf Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: cpattrX.jar
+Created-By: 1.9.0-internal (Oracle Corporation)
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java Thu Aug 29 16:11:22 2019 +0530
@@ -59,7 +59,7 @@
"Abstract_VM_Version::_vm_major_version",
"ClassLoaderDataGraph::_head",
"JNIHandles::_weak_global_handles", "PerfMemory::_top",
- "ObjectSynchronizer::gBlockList",
+ "ObjectSynchronizer::g_block_list",
"java_lang_Class::_oop_size_offset"));
expStrMap.put("printstatics SystemDictionary", List.of(
"Static fields of SystemDictionary",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/CustomImplTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2019, 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 stream.XMLStreamWriterTest;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stax.StAXResult;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8230094
+ * @run testng stream.XMLStreamWriterTest.CustomImplTest
+ * @summary Verifies custom implementation of the XMLStreamWriter.
+ */
+public class CustomImplTest {
+
+ @Test
+ public void testEventReader() throws Exception {
+ XMLOutputFactory.newFactory()
+ .createXMLEventWriter(new StAXResult(new StreamWriterFilter()));
+ }
+
+ static class StreamWriterFilter implements XMLStreamWriter
+ {
+ @Override
+ public void writeStartElement(String localName)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeStartElement(String namespaceURI, String localName)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeStartElement(
+ String prefix, String localName, String namespaceURI)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEmptyElement(String namespaceURI, String localName)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEmptyElement(
+ String prefix, String localName, String namespaceURI)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEmptyElement(String localName)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEndElement() throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEndDocument() throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void close() throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void flush() throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeAttribute(String localName, String value)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeAttribute(
+ String prefix, String namespaceURI, String localName, String value)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeAttribute(
+ String namespaceURI, String localName, String value)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeNamespace(String prefix, String namespaceURI)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeDefaultNamespace(String namespaceURI)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeComment(String data) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeProcessingInstruction(String target)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeProcessingInstruction(String target, String data)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeCData(String data) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeDTD(String dtd) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeEntityRef(String name) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeStartDocument() throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeStartDocument(String version) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeStartDocument(String encoding, String version)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeCharacters(String text) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void writeCharacters(char[] text, int start, int len)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public String getPrefix(String uri) throws XMLStreamException
+ {
+ return null;
+ }
+
+ @Override
+ public void setPrefix(String prefix, String uri)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void setDefaultNamespace(String uri) throws XMLStreamException
+ {
+ }
+
+ @Override
+ public void setNamespaceContext(NamespaceContext context)
+ throws XMLStreamException
+ {
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getProperty(String name) throws IllegalArgumentException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
--- a/test/jaxp/javax/xml/jaxp/unittest/transform/SecureProcessingTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SecureProcessingTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
import org.testng.Assert;
import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
/*
* @test
@@ -46,6 +47,7 @@
*/
@Listeners({jaxp.library.FilePolicy.class})
public class SecureProcessingTest {
+ @Test
public void testSecureProcessing() {
boolean _isSecureMode = System.getSecurityManager() != null;
// SECURE_PROCESSING == false
--- a/test/jdk/ProblemList.txt Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jdk/ProblemList.txt Thu Aug 29 16:11:22 2019 +0530
@@ -884,8 +884,8 @@
jdk/jfr/event/io/TestInstrumentation.java 8202142 generic-all
jdk/jfr/api/recording/event/TestPeriod.java 8215890 generic-all
-
jdk/jfr/event/io/EvilInstrument.java 8221331 generic-all
+jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all
############################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/HttpURLConnection/HttpURLProxySelectionTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2019, 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 com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import jdk.test.lib.net.URIBuilder;
+import org.testng.Assert;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import sun.net.spi.DefaultProxySelector;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * @test
+ * @bug 6563286 6797318 8177648 8230220
+ * @summary Tests that sun.net.www.protocol.http.HttpURLConnection when dealing with
+ * sun.net.spi.DefaultProxySelector#select() handles any IllegalArgumentException
+ * correctly
+ * @library /test/lib
+ * @run testng HttpURLProxySelectionTest
+ * @modules java.base/sun.net.spi:+open
+ */
+public class HttpURLProxySelectionTest {
+
+ private static final String WEB_APP_CONTEXT = "/httpurlproxytest";
+
+ private HttpServer server;
+ private SimpleHandler handler;
+ private ProxySelector previousDefault;
+ private CustomProxySelector ourProxySelector = new CustomProxySelector();
+
+ @BeforeTest
+ public void beforeTest() throws Exception {
+ previousDefault = ProxySelector.getDefault();
+ ProxySelector.setDefault(ourProxySelector);
+ handler = new SimpleHandler();
+ server = createServer(handler);
+ }
+
+ @AfterTest
+ public void afterTest() {
+ try {
+ if (server != null) {
+ final int delaySeconds = 0;
+ server.stop(delaySeconds);
+ }
+ } finally {
+ ProxySelector.setDefault(previousDefault);
+ }
+ }
+
+ /**
+ * - Test initiates a HTTP request to server
+ * - Server receives request and sends a 301 redirect to an URI which doesn't have a "host"
+ * - Redirect is expected to fail with IOException (caused by IllegalArgumentException from DefaultProxySelector)
+ *
+ * @throws Exception
+ */
+ @Test
+ public void test() throws Exception {
+ final URL targetURL = URIBuilder.newBuilder()
+ .scheme("http")
+ .host(server.getAddress().getAddress())
+ .port(server.getAddress().getPort())
+ .path(WEB_APP_CONTEXT)
+ .toURL();
+ System.out.println("Sending request to " + targetURL);
+ final HttpURLConnection conn = (HttpURLConnection) targetURL.openConnection();
+ try {
+ conn.getResponseCode();
+ Assert.fail("Request to " + targetURL + " was expected to fail during redirect");
+ } catch (IOException ioe) {
+ // expected because of the redirect to an invalid URL, for which a proxy can't be selected
+
+ // make sure the it was indeed a redirect
+ Assert.assertTrue(handler.redirectSent, "Server was expected to send a redirect, but didn't");
+ Assert.assertTrue(ourProxySelector.selectorUsedForRedirect, "Proxy selector wasn't used for redirect");
+
+ // make sure the IOException was caused by an IllegalArgumentException
+ Assert.assertTrue(ioe.getCause() instanceof IllegalArgumentException, "Unexpected cause in the IOException");
+ }
+ }
+
+
+ private static HttpServer createServer(final HttpHandler handler) throws IOException {
+ final InetSocketAddress serverAddr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+ final int backlog = -1;
+ final HttpServer server = HttpServer.create(serverAddr, backlog);
+ // setup the handler
+ server.createContext(WEB_APP_CONTEXT, handler);
+ // start the server
+ server.start();
+ System.out.println("Server started on " + server.getAddress());
+ return server;
+ }
+
+ private static class SimpleHandler implements HttpHandler {
+ private volatile boolean redirectSent = false;
+
+ @Override
+ public void handle(final HttpExchange httpExchange) throws IOException {
+ final String redirectURL;
+ try {
+ redirectURL = new URI("http", "/irrelevant", null).toString();
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+ httpExchange.getResponseHeaders().add("Location", redirectURL);
+ final URI requestURI = httpExchange.getRequestURI();
+ System.out.println("Handling " + httpExchange.getRequestMethod() + " request "
+ + requestURI + " responding with redirect to " + redirectURL);
+ this.redirectSent = true;
+ httpExchange.sendResponseHeaders(301, -1);
+ }
+
+ }
+
+ private static class CustomProxySelector extends DefaultProxySelector {
+
+ private volatile boolean selectorUsedForRedirect = false;
+
+ @Override
+ public List<Proxy> select(final URI uri) {
+ if (uri.toString().contains("/irrelevant")) {
+ this.selectorUsedForRedirect = true;
+ }
+ return super.select(uri);
+ }
+ }
+}
--- a/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java Thu Aug 29 16:11:22 2019 +0530
@@ -29,6 +29,7 @@
*/
import java.util.*;
import java.net.*;
+import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.net.IPSupport;
public class NoLoopbackPackets {
@@ -62,7 +63,9 @@
if (IPSupport.hasIPv4()) {
groups.add(new InetSocketAddress(InetAddress.getByName("224.1.1.1"), port));
}
- if (IPSupport.hasIPv6()) {
+
+ NetworkConfiguration nc = NetworkConfiguration.probe();
+ if (IPSupport.hasIPv6() && nc.hasTestableIPv6Address()) {
groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port));
groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port));
}
--- a/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -21,18 +21,24 @@
* questions.
*/
-/*
- * @test
- * @summary Tests what happens when push promise handlers and their
- * response body handlers and subscribers throw unexpected exceptions.
+
+/**
+ * This is not a test. Actual tests are implemented by concrete subclasses.
+ * The abstract class AbstractThrowingPushPromises provides a base framework
+ * to test what happens when push promise handlers and their
+ * response body handlers and subscribers throw unexpected exceptions.
+ * Concrete tests that extend this abstract class will need to include
+ * the following jtreg tags:
+ *
* @library /test/lib http2/server
* @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters
- * ReferenceTracker AbstractThrowingPushPromises
+ * ReferenceTracker AbstractThrowingPushPromises
+ * <concrete-class-name>
* @modules java.base/sun.net.www.http
* java.net.http/jdk.internal.net.http.common
* java.net.http/jdk.internal.net.http.frame
* java.net.http/jdk.internal.net.http.hpack
- * @run testng/othervm -Djdk.internal.httpclient.debug=true AbstractThrowingPushPromises
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true <concrete-class-name>
*/
import jdk.test.lib.net.SimpleSSLContext;
--- a/test/jdk/java/net/httpclient/LineStreamsAndSurrogatesTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jdk/java/net/httpclient/LineStreamsAndSurrogatesTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@
}
@Test
- void testUncomplete() throws Exception {
+ public void testUncomplete() throws Exception {
// Uses U+10400 which is encoded as the surrogate pair U+D801 U+DC00
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r les\n\n" +
" fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\ud801\udc00";
@@ -121,7 +121,7 @@
}
@Test
- void testStream1() throws Exception {
+ public void testStream1() throws Exception {
// Uses U+10400 which is encoded as the surrogate pair U+D801 U+DC00
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r\r les\n\n" +
" fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres";
@@ -170,7 +170,7 @@
@Test
- void testStream2() throws Exception {
+ public void testStream2() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r\r" +
" les fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\r\r";
Charset charset = UTF_8;
@@ -216,7 +216,7 @@
}
@Test
- void testStream3_UTF16() throws Exception {
+ public void testStream3_UTF16() throws Exception {
// Uses U+10400 which is encoded as the surrogate pair U+D801 U+DC00
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r\r" +
" les\n\n fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres";
@@ -263,7 +263,7 @@
@Test
- void testStream4_UTF16() throws Exception {
+ public void testStream4_UTF16() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r\r" +
" les fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\r\r";
Charset charset = UTF_16;
--- a/test/jdk/java/net/httpclient/LineSubscribersAndSurrogatesTest.java Wed Aug 28 09:13:01 2019 -0700
+++ b/test/jdk/java/net/httpclient/LineSubscribersAndSurrogatesTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -81,7 +81,7 @@
}
@Test
- void testIncomplete() throws Exception {
+ public void testIncomplete() throws Exception {
// Uses U+10400 which is encoded as the surrogate pair U+D801 U+DC00
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les\n\n fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\ud801\udc00";
@@ -123,7 +123,7 @@
@Test
- void testStringWithFinisherLF() throws Exception {
+ public void testStringWithFinisherLF() throws Exception {
// Uses U+10400 which is encoded as the surrogate pair U+D801 U+DC00
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les\n\n fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\r";
@@ -155,7 +155,7 @@
@Test
- void testStringWithFinisherCR() throws Exception {
+ public void testStringWithFinisherCR() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\r\r";
ObjectSubscriber subscriber = new ObjectSubscriber();
@@ -183,7 +183,7 @@
}
@Test
- void testStringWithFinisherCRLF() throws Exception {
+ public void testStringWithFinisherCRLF() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres";
ObjectSubscriber subscriber = new ObjectSubscriber();
@@ -210,7 +210,7 @@
@Test
- void testStringWithFinisherBR() throws Exception {
+ public void testStringWithFinisherBR() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les\r\r fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres";
ObjectSubscriber subscriber = new ObjectSubscriber();
@@ -240,7 +240,7 @@
}
@Test
- void testStringWithFinisherBR_UTF_16() throws Exception {
+ public void testStringWithFinisherBR_UTF_16() throws Exception {
String text = "Bient\u00f4t\r\n nous plongerons\r\n dans\r" +
" les\r\r fr\u00f4\ud801\udc00des\r\n t\u00e9n\u00e8bres\r\r";
ObjectSubscriber subscriber = new ObjectSubscriber();
--- a/test/jdk/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest1.java Wed Aug 28 09:13:01 2019 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-package validation.jdk8037819;
-
-import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl;
-import com.sun.org.apache.xerces.internal.xs.ItemPSVI;
-import validation.BaseTest;
-
-public class BasicTest1 extends BaseTest {
- public static void main(String[] args) throws Exception {
- BasicTest1 test = new BasicTest1();
- test.setUp();
- test.testSimpleValidation();
- test.testSimpleValidationWithTrivialXSIType();
- test.tearDown();
- }
-
- protected String getXMLDocument() {
- return "base.xml";
- }
-
- protected String getSchemaFile() {
- return "base.xsd";
- }
-
- public BasicTest1() {
- super("BasicTest1");
- }
-
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- public void testSimpleValidation() {
- try {
- reset();
- validateDocument();
- } catch (Exception e) {
- fail("Validation failed: " + e.getMessage());
- }
- doValidityAsserts();
- }
-
- public void testSimpleValidationWithTrivialXSIType() {
- try {
- reset();
- ((PSVIElementNSImpl) fRootNode).setAttributeNS(
- "http://www.w3.org/2001/XMLSchema-instance", "type", "X");
- validateDocument();
- } catch (Exception e) {
- fail("Validation failed: " + e.getMessage());
- }
- doValidityAsserts();
- }
-
- private void doValidityAsserts() {
- assertValidity(ItemPSVI.VALIDITY_VALID, fRootNode.getValidity());
- assertValidationAttempted(ItemPSVI.VALIDATION_FULL, fRootNode
- .getValidationAttempted());
- assertElementName("A", fRootNode.getElementDeclaration().getName());
- assertElementNamespaceNull(fRootNode.getElementDeclaration()
- .getNamespace());
- assertTypeName("X", fRootNode.getTypeDefinition().getName());
- assertTypeNamespaceNull(fRootNode.getTypeDefinition().getNamespace());
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/net/spi/DefaultProxySelectorTest.java Thu Aug 29 16:11:22 2019 +0530
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import sun.net.spi.DefaultProxySelector;
+
+import java.net.ProxySelector;
+import java.net.URI;
+
+/**
+ * @test
+ * @bug 6563286 6797318 8177648
+ * @summary Tests sun.net.spi.DefaultProxySelector#select(URI)
+ * @run testng DefaultProxySelectorTest
+ * @modules java.base/sun.net.spi:+open
+ */
+public class DefaultProxySelectorTest {
+
+ /**
+ * Tests that {@link DefaultProxySelector#select(URI)} throws
+ * {@link IllegalArgumentException} when passed {@code null}
+ */
+ @Test
+ public void testIllegalArgForNull() {
+ final ProxySelector selector = new DefaultProxySelector();
+ try {
+ selector.select(null);
+ Assert.fail("select() was expected to fail for null URI");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ /**
+ * Tests that {@link DefaultProxySelector} throws a {@link IllegalArgumentException}
+ * for URIs that don't have host information
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testIllegalArgForNoHost() throws Exception {
+ final ProxySelector selector = new DefaultProxySelector();
+ assertFailsWithIAE(selector, new URI("http", "/test", null));
+ assertFailsWithIAE(selector, new URI("https", "/test2", null));
+ assertFailsWithIAE(selector, new URI("ftp", "/test3", null));
+ }
+
+
+ /**
+ * Tests that {@link DefaultProxySelector} throws a {@link IllegalArgumentException}
+ * for URIs that don't have protocol/scheme information
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testIllegalArgForNoScheme() throws Exception {
+ final ProxySelector selector = new DefaultProxySelector();
+ assertFailsWithIAE(selector, new URI(null, "/test", null));
+ }
+
+ private static void assertFailsWithIAE(final ProxySelector selector, final URI uri) {
+ try {
+ selector.select(uri);
+ Assert.fail("select() was expected to fail for URI " + uri);
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+}