mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-08 09:31:42 +01:00
Compare commits
138 Commits
jb16-b371
...
vladimir.d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8064d3e6fa | ||
|
|
ea0171018d | ||
|
|
8412c86228 | ||
|
|
bdef3b35f4 | ||
|
|
74822fa981 | ||
|
|
3d25374885 | ||
|
|
f1bfa64909 | ||
|
|
ee3005a5bb | ||
|
|
ab6f55b6b6 | ||
|
|
085d5f315d | ||
|
|
d14b81efa8 | ||
|
|
fed02226c6 | ||
|
|
aff775bbac | ||
|
|
b79a2afac0 | ||
|
|
c6327831b5 | ||
|
|
5340a9f6b3 | ||
|
|
b9e3cb07b9 | ||
|
|
c22b2b1efb | ||
|
|
23930319f2 | ||
|
|
9345bc5b4c | ||
|
|
e087cb9c2a | ||
|
|
546bae8735 | ||
|
|
9086b11d31 | ||
|
|
17bd2096d6 | ||
|
|
00406eadb4 | ||
|
|
a6e08a6ef4 | ||
|
|
3fd069aff2 | ||
|
|
af90ea2a50 | ||
|
|
57aaa887a6 | ||
|
|
8ea056094a | ||
|
|
369062fa33 | ||
|
|
3499b1734d | ||
|
|
aaa927b0c2 | ||
|
|
24db680175 | ||
|
|
55939f0950 | ||
|
|
208a417459 | ||
|
|
ff5ed84e4b | ||
|
|
6d6da716c3 | ||
|
|
4b8eabeec8 | ||
|
|
50769a882e | ||
|
|
b0eb2600be | ||
|
|
bcdf1e7577 | ||
|
|
7d2f5e0d21 | ||
|
|
d45cab03b1 | ||
|
|
e33577c3a5 | ||
|
|
32e9c4d353 | ||
|
|
44d62b3234 | ||
|
|
0f0ab2c5ba | ||
|
|
1a807593ab | ||
|
|
241c14cb92 | ||
|
|
601064c09c | ||
|
|
2120a8a282 | ||
|
|
36ef23fb81 | ||
|
|
2afd3d4821 | ||
|
|
4b8e82db67 | ||
|
|
90d22980d5 | ||
|
|
0d1778962d | ||
|
|
276a53ba14 | ||
|
|
b483235e7f | ||
|
|
bc6ff706da | ||
|
|
27ffa822c1 | ||
|
|
9174496aa0 | ||
|
|
d7d16faf16 | ||
|
|
653e7a8101 | ||
|
|
fcb22de8b0 | ||
|
|
af0e3f69fa | ||
|
|
cd74581779 | ||
|
|
74ce667016 | ||
|
|
161a7eac4a | ||
|
|
54a2e76122 | ||
|
|
be4219caab | ||
|
|
4a3199dc9d | ||
|
|
b63b0ae668 | ||
|
|
7a084221ca | ||
|
|
4165ef6306 | ||
|
|
14b7c5adef | ||
|
|
71fa983bc1 | ||
|
|
8a2f49d98b | ||
|
|
c971c7fa88 | ||
|
|
b9996c7b47 | ||
|
|
f160303ec9 | ||
|
|
307d1c1fd7 | ||
|
|
25302b9289 | ||
|
|
1759eb2b89 | ||
|
|
d27d2e2baa | ||
|
|
c13fd2cb3e | ||
|
|
c1624ddd8d | ||
|
|
65affdb4f7 | ||
|
|
08f6a61016 | ||
|
|
edf629d075 | ||
|
|
d8d095563e | ||
|
|
486f078759 | ||
|
|
9b087fe5da | ||
|
|
bd606c0383 | ||
|
|
d05263d08c | ||
|
|
5629899859 | ||
|
|
d3107db64d | ||
|
|
e2901b99db | ||
|
|
d7723b6110 | ||
|
|
483e5158be | ||
|
|
5f3c9c11ba | ||
|
|
fd6e0efbd5 | ||
|
|
fbd999542a | ||
|
|
5a252a96f1 | ||
|
|
1b9c3ed57b | ||
|
|
8b32d4cc6f | ||
|
|
54152197f5 | ||
|
|
2588bb7a92 | ||
|
|
fb6a542b84 | ||
|
|
4606f42a4b | ||
|
|
6e29b5cd43 | ||
|
|
6c12492aef | ||
|
|
4ead63ebbe | ||
|
|
6934ca4826 | ||
|
|
f6b4e4d52d | ||
|
|
c49a889919 | ||
|
|
1ff8b4b6df | ||
|
|
748f55a971 | ||
|
|
3c594007b5 | ||
|
|
19482e0c9f | ||
|
|
c17f1e9ffe | ||
|
|
e6cae2dd1a | ||
|
|
8373d64d08 | ||
|
|
433d7d4681 | ||
|
|
9d03be4e29 | ||
|
|
0348537300 | ||
|
|
cd285c9022 | ||
|
|
4dcff472fa | ||
|
|
0b6cba009c | ||
|
|
fbb2e417c9 | ||
|
|
c866c331cd | ||
|
|
4c78467a0d | ||
|
|
6b0ad1c96f | ||
|
|
acb92a2a1a | ||
|
|
aea97028fb | ||
|
|
d6404cf65e | ||
|
|
20a26347e4 | ||
|
|
397f951cd2 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
* -text
|
||||
1332
.github/workflows/submit.yml
vendored
1332
.github/workflows/submit.yml
vendored
File diff suppressed because it is too large
Load Diff
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,7 +2,6 @@
|
||||
/dist/
|
||||
/.idea/
|
||||
/.vscode/
|
||||
/nbproject/
|
||||
nbproject/private/
|
||||
/webrev
|
||||
/.src-rev
|
||||
@@ -15,4 +14,3 @@ test/nashorn/lib
|
||||
NashornProfile.txt
|
||||
**/JTreport/**
|
||||
**/JTwork/**
|
||||
/src/utils/LogCompilation/target/
|
||||
|
||||
18
.hgignore
Normal file
18
.hgignore
Normal file
@@ -0,0 +1,18 @@
|
||||
^build/
|
||||
^dist/
|
||||
^.idea/
|
||||
^.vscode/
|
||||
nbproject/private/
|
||||
^webrev
|
||||
^.src-rev$
|
||||
^.jib/
|
||||
(^|/)\.DS_Store
|
||||
(^|/)\.metadata/
|
||||
(^|/)\.recommenders/
|
||||
test/nashorn/script/external
|
||||
test/nashorn/lib
|
||||
NashornProfile.txt
|
||||
(^|/)JTreport/
|
||||
(^|/)JTwork/
|
||||
(^|/)\.git/
|
||||
^src/utils/hsdis/build/
|
||||
19
.hgtags
19
.hgtags
@@ -635,30 +635,19 @@ dd5198db2e5b1ebcafe065d987c03ba9fcb50fc3 jdk-15+17
|
||||
7223c6d610343fd8323af9d07d501e01fa1a7696 jdk-15+22
|
||||
f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23
|
||||
497fd9f9129c4928fd5a876dd55e0daf6298b511 jdk-15+24
|
||||
58833044988772ca06c97ab2f142474a8627af80 jdk-15+25
|
||||
58833044988772ca06c97ab2f142474a8627af80 jdk-15+25
|
||||
90b266a84c06f1b3dc0ed8767856793e8c1c357e jdk-15+25
|
||||
0a32396f7a690015d22ca3328ac441a358295d90 jdk-15+26
|
||||
93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-16+0
|
||||
506abc554caeb275928c02bf3a16e95d1978749f jdk-15+27
|
||||
506abc554caeb275928c02bf3a16e95d1978749f jdk-15+27
|
||||
93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-15+27
|
||||
4a485c89d5a08b495961835f5308a96038678aeb jdk-16+1
|
||||
06c9f89459daba98395fad726100feb44f89ba71 jdk-15+28
|
||||
bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2
|
||||
b58fc60580550a4a587cab729d8fd87223ad6932 jdk-15+29
|
||||
76810b3a88c8c641ae3850a8dfd7c40c984aea9d jdk-16+3
|
||||
6909e4a1f25bfe9a2727026f5845fc1fc44a36aa jdk-15+30
|
||||
e2622818f0bd30e736252eba101fe7d2c27f400b jdk-16+4
|
||||
a32f58c6b8be81877411767de7ba9c4cf087c1b5 jdk-15+31
|
||||
143e258f64af490010eb7e0bacc1cfaeceff0993 jdk-16+5
|
||||
2dad000726b8d5db9f3df647fb4949d88f269dd4 jdk-15+32
|
||||
4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6
|
||||
6b65f4e7a975628df51ef755b02642075390041d jdk-15+33
|
||||
c3a4a7ea7c304cabdacdc31741eb94c51351668d jdk-16+7
|
||||
b0817631d2f4395508cb10e81c3858a94d9ae4de jdk-15+34
|
||||
0a73d6f3aab48ff6d7e61e47f0bc2d87a054f217 jdk-16+8
|
||||
fd60c3146a024037cdd9be34c645bb793995a7cc jdk-15+35
|
||||
c075a286cc7df767cce28e8057d6ec5051786490 jdk-16+9
|
||||
b01985b4f88f554f97901e53e1ba314681dd9c19 jdk-16+10
|
||||
e3f940bd3c8fcdf4ca704c6eb1ac745d155859d5 jdk-15+36
|
||||
5c18d696c7ce724ca36df13933aa53f50e12b9e0 jdk-16+11
|
||||
fc8e62b399bd93d06e8d13dc3b384c450e853dcd jdk-16+12
|
||||
fd07cdb26fc70243ef23d688b545514f4ddf1c2b jdk-16+13
|
||||
36b29df125dc88f11657ce93b4998aa9ff5f5d41 jdk-16+14
|
||||
|
||||
33
.jcheck/conf
33
.jcheck/conf
@@ -1,33 +1,2 @@
|
||||
[general]
|
||||
project=jdk
|
||||
jbs=JDK
|
||||
|
||||
[checks]
|
||||
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
|
||||
|
||||
[repository]
|
||||
tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d)
|
||||
branches=
|
||||
|
||||
[census]
|
||||
version=0
|
||||
domain=openjdk.org
|
||||
|
||||
[checks "whitespace"]
|
||||
files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm
|
||||
|
||||
[checks "merge"]
|
||||
message=Merge
|
||||
|
||||
[checks "reviewers"]
|
||||
reviewers=1
|
||||
ignore=duke
|
||||
|
||||
[checks "committer"]
|
||||
role=committer
|
||||
|
||||
[checks "issues"]
|
||||
pattern=^([124-8][0-9]{6}): (\S.*)$
|
||||
|
||||
[checks "problemlists"]
|
||||
dirs=test/jdk|test/langtools|test/lib-test|test/hotspot/jtreg|test/jaxp
|
||||
bugids=dup
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Contributing to the JDK
|
||||
|
||||
Please see <https://openjdk.java.net/contribute/> for how to contribute.
|
||||
12
README
Normal file
12
README
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
Welcome to the JDK!
|
||||
===================
|
||||
|
||||
For build instructions, please see either of these files:
|
||||
|
||||
* doc/building.html (html version)
|
||||
* doc/building.md (markdown version)
|
||||
|
||||
See https://openjdk.java.net/ for more information about
|
||||
the OpenJDK Community and the JDK.
|
||||
|
||||
11
README.md
11
README.md
@@ -1,11 +0,0 @@
|
||||
# Welcome to the JDK!
|
||||
|
||||
For build instructions please see the
|
||||
[online documentation](https://openjdk.java.net/groups/build/doc/building.html),
|
||||
or either of these files:
|
||||
|
||||
- [doc/building.html](doc/building.html) (html version)
|
||||
- [doc/building.md](doc/building.md) (markdown version)
|
||||
|
||||
See <https://openjdk.java.net/> for more information about
|
||||
the OpenJDK Community and the JDK.
|
||||
69
bin/idea.sh
69
bin/idea.sh
@@ -147,7 +147,13 @@ add_replacement() {
|
||||
add_replacement "###MODULE_NAMES###" "$MODULE_NAMES"
|
||||
add_replacement "###VCS_TYPE###" "$VCS_TYPE"
|
||||
SPEC_DIR=`dirname $SPEC`
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
if [ "x$CYGPATH" = "x" ]; then
|
||||
add_replacement "###BUILD_DIR###" "$SPEC_DIR"
|
||||
add_replacement "###JTREG_HOME###" "$JT_HOME"
|
||||
add_replacement "###IMAGES_DIR###" "$SPEC_DIR/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "$TOPLEVEL_DIR"
|
||||
add_replacement "###IDEA_DIR###" "$IDEA_OUTPUT"
|
||||
else
|
||||
add_replacement "###BUILD_DIR###" "`cygpath -am $SPEC_DIR`"
|
||||
add_replacement "###IMAGES_DIR###" "`cygpath -am $SPEC_DIR`/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "`cygpath -am $TOPLEVEL_DIR`"
|
||||
@@ -157,22 +163,6 @@ if [ "x$CYGPATH" != "x" ]; then
|
||||
else
|
||||
add_replacement "###JTREG_HOME###" "`cygpath -am $JT_HOME`"
|
||||
fi
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
add_replacement "###BUILD_DIR###" "`wslpath -am $SPEC_DIR`"
|
||||
add_replacement "###IMAGES_DIR###" "`wslpath -am $SPEC_DIR`/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "`wslpath -am $TOPLEVEL_DIR`"
|
||||
add_replacement "###IDEA_DIR###" "`wslpath -am $IDEA_OUTPUT`"
|
||||
if [ "x$JT_HOME" = "x" ]; then
|
||||
add_replacement "###JTREG_HOME###" ""
|
||||
else
|
||||
add_replacement "###JTREG_HOME###" "`wslpath -am $JT_HOME`"
|
||||
fi
|
||||
else
|
||||
add_replacement "###BUILD_DIR###" "$SPEC_DIR"
|
||||
add_replacement "###JTREG_HOME###" "$JT_HOME"
|
||||
add_replacement "###IMAGES_DIR###" "$SPEC_DIR/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "$TOPLEVEL_DIR"
|
||||
add_replacement "###IDEA_DIR###" "$IDEA_OUTPUT"
|
||||
fi
|
||||
|
||||
SOURCE_PREFIX="<sourceFolder url=\"file://"
|
||||
@@ -180,22 +170,9 @@ SOURCE_POSTFIX="\" isTestSource=\"false\" />"
|
||||
|
||||
for root in $MODULE_ROOTS; do
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
root=`cygpath -am $root`
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
root=`wslpath -am $root`
|
||||
fi
|
||||
|
||||
VM_CI="jdk.internal.vm.ci/share/classes"
|
||||
VM_COMPILER="src/jdk.internal.vm.compiler/share/classes"
|
||||
if test "${root#*$VM_CI}" != "$root" || test "${root#*$VM_COMPILER}" != "$root"; then
|
||||
for subdir in "$root"/*; do
|
||||
if [ -d "$subdir" ]; then
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$subdir"/src"$SOURCE_POSTFIX"
|
||||
fi
|
||||
done
|
||||
else
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
root=`cygpath -am $root`
|
||||
fi
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
done
|
||||
|
||||
add_replacement "###SOURCE_ROOTS###" "$SOURCES"
|
||||
@@ -219,30 +196,16 @@ fi
|
||||
CP=$ANT_HOME/lib/ant.jar
|
||||
rm -rf $CLASSES; mkdir $CLASSES
|
||||
|
||||
if [ "x$CYGPATH" != "x" ] ; then ## CYGPATH may be set in env.cfg
|
||||
JAVAC_SOURCE_FILE=`cygpath -am $IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java`
|
||||
JAVAC_SOURCE_PATH=`cygpath -am $IDEA_OUTPUT/src`
|
||||
JAVAC_CLASSES=`cygpath -am $CLASSES`
|
||||
JAVAC_CP=`cygpath -am $CP`
|
||||
JAVAC=javac
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
JAVAC_SOURCE_FILE=`realpath --relative-to=./ $IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java`
|
||||
JAVAC_SOURCE_PATH=`realpath --relative-to=./ $IDEA_OUTPUT/src`
|
||||
JAVAC_CLASSES=`realpath --relative-to=./ $CLASSES`
|
||||
ANT_TEMP=`mktemp -d -p ./`
|
||||
cp $ANT_HOME/lib/ant.jar $ANT_TEMP/ant.jar
|
||||
JAVAC_CP=$ANT_TEMP/ant.jar
|
||||
JAVAC=javac.exe
|
||||
else
|
||||
if [ "x$CYGPATH" = "x" ] ; then ## CYGPATH may be set in env.cfg
|
||||
JAVAC_SOURCE_FILE=$IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java
|
||||
JAVAC_SOURCE_PATH=$IDEA_OUTPUT/src
|
||||
JAVAC_CLASSES=$CLASSES
|
||||
JAVAC_CP=$CP
|
||||
JAVAC=javac
|
||||
else
|
||||
JAVAC_SOURCE_FILE=`cygpath -am $IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java`
|
||||
JAVAC_SOURCE_PATH=`cygpath -am $IDEA_OUTPUT/src`
|
||||
JAVAC_CLASSES=`cygpath -am $CLASSES`
|
||||
JAVAC_CP=`cygpath -am $CP`
|
||||
fi
|
||||
|
||||
$BOOT_JDK/bin/$JAVAC -d $JAVAC_CLASSES -sourcepath $JAVAC_SOURCE_PATH -cp $JAVAC_CP $JAVAC_SOURCE_FILE
|
||||
|
||||
if [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
rm -rf $ANT_TEMP
|
||||
fi
|
||||
$BOOT_JDK/bin/javac -d $JAVAC_CLASSES -sourcepath $JAVAC_SOURCE_PATH -cp $JAVAC_CP $JAVAC_SOURCE_FILE
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
<li><a href="#native-libraries">Native Libraries</a></li>
|
||||
<li><a href="#creating-and-using-sysroots-with-qemu-deboostrap">Creating And Using Sysroots With qemu-deboostrap</a></li>
|
||||
<li><a href="#building-for-armaarch64">Building for ARM/aarch64</a></li>
|
||||
<li><a href="#building-for-musl">Building for musl</a></li>
|
||||
<li><a href="#verifying-the-build">Verifying the Build</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#build-performance">Build Performance</a><ul>
|
||||
@@ -225,8 +224,6 @@
|
||||
<pre><code>sudo apt-get install build-essential</code></pre>
|
||||
<p>For rpm-based distributions (Fedora, Red Hat, etc), try this:</p>
|
||||
<pre><code>sudo yum groupinstall "Development Tools"</code></pre>
|
||||
<p>For Alpine Linux, aside from basic tooling, install the GNU versions of some programs:</p>
|
||||
<pre><code>sudo apk add build-base bash grep zip</code></pre>
|
||||
<h3 id="aix">AIX</h3>
|
||||
<p>Please consult the AIX section of the <a href="https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms">Supported Build Platforms</a> OpenJDK Build Wiki page for details about which versions of AIX are supported.</p>
|
||||
<h2 id="native-compiler-toolchain-requirements">Native Compiler (Toolchain) Requirements</h2>
|
||||
@@ -268,7 +265,7 @@
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Linux</td>
|
||||
<td style="text-align: left;">gcc 10.2.0</td>
|
||||
<td style="text-align: left;">gcc 9.2.0</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">macOS</td>
|
||||
@@ -276,17 +273,17 @@
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Windows</td>
|
||||
<td style="text-align: left;">Microsoft Visual Studio 2019 update 16.7.2</td>
|
||||
<td style="text-align: left;">Microsoft Visual Studio 2019 update 16.5.3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>All compilers are expected to be able to compile to the C99 language standard, as some C99 features are used in the source code. Microsoft Visual Studio doesn't fully support C99 so in practice shared code is limited to using C99 features that it does support.</p>
|
||||
<h3 id="gcc">gcc</h3>
|
||||
<p>The minimum accepted version of gcc is 5.0. Older versions will generate a warning by <code>configure</code> and are unlikely to work.</p>
|
||||
<p>The JDK is currently known to be able to compile with at least version 10.2 of gcc.</p>
|
||||
<p>The JDK is currently known to be able to compile with at least version 9.2 of gcc.</p>
|
||||
<p>In general, any version between these two should be usable.</p>
|
||||
<h3 id="clang">clang</h3>
|
||||
<p>The minimum accepted version of clang is 3.5. Older versions will not be accepted by <code>configure</code>.</p>
|
||||
<p>The minimum accepted version of clang is 3.2. Older versions will not be accepted by <code>configure</code>.</p>
|
||||
<p>To use clang instead of gcc on Linux, use <code>--with-toolchain-type=clang</code>.</p>
|
||||
<h3 id="apple-xcode">Apple Xcode</h3>
|
||||
<p>The oldest supported version of Xcode is 8.</p>
|
||||
@@ -295,8 +292,9 @@
|
||||
<p>It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This <a href="http://iosdevelopertips.com/xcode/install-multiple-versions-of-xcode.html">blog page</a> has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use <code>xcode-select -s</code> before running <code>configure</code>, or use <code>--with-toolchain-path</code> to point to the version of Xcode to use, e.g. <code>configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin</code></p>
|
||||
<p>If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on <a href="#problems-with-the-build-environment">Problems with the Build Environment</a>, and <a href="#getting-help">Getting Help</a> to find out if there are any recent, non-merged patches available for this update.</p>
|
||||
<h3 id="microsoft-visual-studio">Microsoft Visual Studio</h3>
|
||||
<p>The minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by <code>configure</code> and will not work. The maximum accepted version of Visual Studio is 2019.</p>
|
||||
<p>If you have multiple versions of Visual Studio installed, <code>configure</code> will by default pick the latest. You can request a specific version to be used by setting <code>--with-toolchain-version</code>, e.g. <code>--with-toolchain-version=2017</code>.</p>
|
||||
<p>The minimum accepted version of Visual Studio is 2010. Older versions will not be accepted by <code>configure</code>. The maximum accepted version of Visual Studio is 2019. Versions older than 2017 are unlikely to continue working for long.</p>
|
||||
<p>If you have multiple versions of Visual Studio installed, <code>configure</code> will by default pick the latest. You can request a specific version to be used by setting <code>--with-toolchain-version</code>, e.g. <code>--with-toolchain-version=2015</code>.</p>
|
||||
<p>If you get <code>LINK: fatal error LNK1123: failure during conversion to COFF: file invalid</code> when building using Visual Studio 2010, you have encountered <a href="http://support.microsoft.com/kb/2757355">KB2757355</a>, a bug triggered by a specific installation order. However, the solution suggested by the KB article does not always resolve the problem. See <a href="https://stackoverflow.com/questions/10888391">this stackoverflow discussion</a> for other suggestions.</p>
|
||||
<h3 id="ibm-xl-cc">IBM XL C/C++</h3>
|
||||
<p>Please consult the AIX section of the <a href="https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms">Supported Build Platforms</a> OpenJDK Build Wiki page for details about which versions of XLC are supported.</p>
|
||||
<h2 id="boot-jdk-requirements">Boot JDK Requirements</h2>
|
||||
@@ -316,7 +314,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install libfreetype6-dev</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install freetype-devel</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add freetype-dev</code>.</li>
|
||||
</ul>
|
||||
<p>Use <code>--with-freetype-include=<path></code> and <code>--with-freetype-lib=<path></code> if <code>configure</code> does not automatically locate the platform FreeType files.</p>
|
||||
<h3 id="cups">CUPS</h3>
|
||||
@@ -324,7 +321,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install libcups2-dev</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install cups-devel</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add cups-dev</code>.</li>
|
||||
</ul>
|
||||
<p>Use <code>--with-cups=<path></code> if <code>configure</code> does not properly locate your CUPS files.</p>
|
||||
<h3 id="x11">X11</h3>
|
||||
@@ -332,7 +328,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev</code>.</li>
|
||||
</ul>
|
||||
<p>Use <code>--with-x=<path></code> if <code>configure</code> does not properly locate your X11 files.</p>
|
||||
<h3 id="alsa">ALSA</h3>
|
||||
@@ -340,7 +335,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install libasound2-dev</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install alsa-lib-devel</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add alsa-lib-dev</code>.</li>
|
||||
</ul>
|
||||
<p>Use <code>--with-alsa=<path></code> if <code>configure</code> does not properly locate your ALSA files.</p>
|
||||
<h3 id="libffi">libffi</h3>
|
||||
@@ -348,7 +342,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install libffi-dev</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install libffi-devel</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add libffi-dev</code>.</li>
|
||||
</ul>
|
||||
<p>Use <code>--with-libffi=<path></code> if <code>configure</code> does not properly locate your libffi files.</p>
|
||||
<h2 id="build-tools-requirements">Build Tools Requirements</h2>
|
||||
@@ -357,7 +350,6 @@
|
||||
<ul>
|
||||
<li>To install on an apt-based Linux, try running <code>sudo apt-get install autoconf</code>.</li>
|
||||
<li>To install on an rpm-based Linux, try running <code>sudo yum install autoconf</code>.</li>
|
||||
<li>To install on Alpine Linux, try running <code>sudo apk add autoconf</code>.</li>
|
||||
<li>To install on macOS, try running <code>brew install autoconf</code>.</li>
|
||||
<li>To install on Windows, try running <code><path to Cygwin setup>/setup-x86_64 -q -P autoconf</code>.</li>
|
||||
</ul>
|
||||
@@ -697,15 +689,6 @@ ls build/linux-aarch64-normal-server-release/</code></pre>
|
||||
<p>Additional architectures might be supported by Debian/Ubuntu Ports.</p>
|
||||
<h3 id="building-for-armaarch64">Building for ARM/aarch64</h3>
|
||||
<p>A common cross-compilation target is the ARM CPU. When building for ARM, it is useful to set the ABI profile. A number of pre-defined ABI profiles are available using <code>--with-abi-profile</code>: arm-vfp-sflt, arm-vfp-hflt, arm-sflt, armv5-vfp-sflt, armv6-vfp-hflt. Note that soft-float ABIs are no longer properly supported by the JDK.</p>
|
||||
<h3 id="building-for-musl">Building for musl</h3>
|
||||
<p>Just like it's possible to cross-compile for a different CPU, it's possible to cross-compile for musl libc on a glibc-based <em>build</em> system. A devkit suitable for most target CPU architectures can be obtained from <a href="https://musl.cc">musl.cc</a>. After installing the required packages in the sysroot, configure the build with <code>--openjdk-target</code>:</p>
|
||||
<pre><code>sh ./configure --with-jvm-variants=server \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--with-build-jdk=$BUILD_JDK \
|
||||
--openjdk-target=x86_64-unknown-linux-musl \
|
||||
--with-devkit=$DEVKIT \
|
||||
--with-sysroot=$SYSROOT</code></pre>
|
||||
<p>and run <code>make</code> normally.</p>
|
||||
<h3 id="verifying-the-build">Verifying the Build</h3>
|
||||
<p>The build will end up in a directory named like <code>build/linux-arm-normal-server-release</code>.</p>
|
||||
<p>Inside this build output directory, the <code>images/jdk</code> will contain the newly built JDK, for your <em>target</em> system.</p>
|
||||
|
||||
@@ -273,13 +273,6 @@ For rpm-based distributions (Fedora, Red Hat, etc), try this:
|
||||
sudo yum groupinstall "Development Tools"
|
||||
```
|
||||
|
||||
For Alpine Linux, aside from basic tooling, install the GNU versions of some
|
||||
programs:
|
||||
|
||||
```
|
||||
sudo apk add build-base bash grep zip
|
||||
```
|
||||
|
||||
### AIX
|
||||
|
||||
Please consult the AIX section of the [Supported Build Platforms](
|
||||
@@ -309,9 +302,9 @@ issues.
|
||||
|
||||
Operating system Toolchain version
|
||||
------------------ -------------------------------------------------------
|
||||
Linux gcc 10.2.0
|
||||
Linux gcc 9.2.0
|
||||
macOS Apple Xcode 10.1 (using clang 10.0.0)
|
||||
Windows Microsoft Visual Studio 2019 update 16.7.2
|
||||
Windows Microsoft Visual Studio 2019 update 16.5.3
|
||||
|
||||
All compilers are expected to be able to compile to the C99 language standard,
|
||||
as some C99 features are used in the source code. Microsoft Visual Studio
|
||||
@@ -323,14 +316,14 @@ features that it does support.
|
||||
The minimum accepted version of gcc is 5.0. Older versions will generate a warning
|
||||
by `configure` and are unlikely to work.
|
||||
|
||||
The JDK is currently known to be able to compile with at least version 10.2 of
|
||||
The JDK is currently known to be able to compile with at least version 9.2 of
|
||||
gcc.
|
||||
|
||||
In general, any version between these two should be usable.
|
||||
|
||||
### clang
|
||||
|
||||
The minimum accepted version of clang is 3.5. Older versions will not be
|
||||
The minimum accepted version of clang is 3.2. Older versions will not be
|
||||
accepted by `configure`.
|
||||
|
||||
To use clang instead of gcc on Linux, use `--with-toolchain-type=clang`.
|
||||
@@ -362,13 +355,20 @@ available for this update.
|
||||
|
||||
### Microsoft Visual Studio
|
||||
|
||||
The minimum accepted version of Visual Studio is 2017. Older versions will not
|
||||
be accepted by `configure` and will not work. The maximum accepted
|
||||
version of Visual Studio is 2019.
|
||||
The minimum accepted version of Visual Studio is 2010. Older versions will not
|
||||
be accepted by `configure`. The maximum accepted version of Visual Studio is
|
||||
2019. Versions older than 2017 are unlikely to continue working for long.
|
||||
|
||||
If you have multiple versions of Visual Studio installed, `configure` will by
|
||||
default pick the latest. You can request a specific version to be used by
|
||||
setting `--with-toolchain-version`, e.g. `--with-toolchain-version=2017`.
|
||||
setting `--with-toolchain-version`, e.g. `--with-toolchain-version=2015`.
|
||||
|
||||
If you get `LINK: fatal error LNK1123: failure during conversion to COFF: file
|
||||
invalid` when building using Visual Studio 2010, you have encountered
|
||||
[KB2757355](http://support.microsoft.com/kb/2757355), a bug triggered by a
|
||||
specific installation order. However, the solution suggested by the KB article
|
||||
does not always resolve the problem. See [this stackoverflow discussion](
|
||||
https://stackoverflow.com/questions/10888391) for other suggestions.
|
||||
|
||||
### IBM XL C/C++
|
||||
|
||||
@@ -438,7 +438,6 @@ rather than bundling the JDK's own copy.
|
||||
libfreetype6-dev`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
freetype-devel`.
|
||||
* To install on Alpine Linux, try running `sudo apk add freetype-dev`.
|
||||
|
||||
Use `--with-freetype-include=<path>` and `--with-freetype-lib=<path>`
|
||||
if `configure` does not automatically locate the platform FreeType files.
|
||||
@@ -453,7 +452,6 @@ your operating system.
|
||||
libcups2-dev`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
cups-devel`.
|
||||
* To install on Alpine Linux, try running `sudo apk add cups-dev`.
|
||||
|
||||
Use `--with-cups=<path>` if `configure` does not properly locate your CUPS
|
||||
files.
|
||||
@@ -467,8 +465,6 @@ Linux.
|
||||
libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel`.
|
||||
* To install on Alpine Linux, try running `sudo apk add libx11-dev
|
||||
libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev`.
|
||||
|
||||
Use `--with-x=<path>` if `configure` does not properly locate your X11 files.
|
||||
|
||||
@@ -481,7 +477,6 @@ required on Linux. At least version 0.9.1 of ALSA is required.
|
||||
libasound2-dev`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
alsa-lib-devel`.
|
||||
* To install on Alpine Linux, try running `sudo apk add alsa-lib-dev`.
|
||||
|
||||
Use `--with-alsa=<path>` if `configure` does not properly locate your ALSA
|
||||
files.
|
||||
@@ -496,7 +491,6 @@ Hotspot.
|
||||
libffi-dev`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
libffi-devel`.
|
||||
* To install on Alpine Linux, try running `sudo apk add libffi-dev`.
|
||||
|
||||
Use `--with-libffi=<path>` if `configure` does not properly locate your libffi
|
||||
files.
|
||||
@@ -512,7 +506,6 @@ platforms. At least version 2.69 is required.
|
||||
autoconf`.
|
||||
* To install on an rpm-based Linux, try running `sudo yum install
|
||||
autoconf`.
|
||||
* To install on Alpine Linux, try running `sudo apk add autoconf`.
|
||||
* To install on macOS, try running `brew install autoconf`.
|
||||
* To install on Windows, try running `<path to Cygwin setup>/setup-x86_64 -q
|
||||
-P autoconf`.
|
||||
@@ -1127,25 +1120,6 @@ available using `--with-abi-profile`: arm-vfp-sflt, arm-vfp-hflt, arm-sflt,
|
||||
armv5-vfp-sflt, armv6-vfp-hflt. Note that soft-float ABIs are no longer
|
||||
properly supported by the JDK.
|
||||
|
||||
### Building for musl
|
||||
|
||||
Just like it's possible to cross-compile for a different CPU, it's possible to
|
||||
cross-compile for musl libc on a glibc-based *build* system.
|
||||
A devkit suitable for most target CPU architectures can be obtained from
|
||||
[musl.cc](https://musl.cc). After installing the required packages in the
|
||||
sysroot, configure the build with `--openjdk-target`:
|
||||
|
||||
```
|
||||
sh ./configure --with-jvm-variants=server \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--with-build-jdk=$BUILD_JDK \
|
||||
--openjdk-target=x86_64-unknown-linux-musl \
|
||||
--with-devkit=$DEVKIT \
|
||||
--with-sysroot=$SYSROOT
|
||||
```
|
||||
|
||||
and run `make` normally.
|
||||
|
||||
### Verifying the Build
|
||||
|
||||
The build will end up in a directory named like
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>HotSpot Coding Style</title>
|
||||
<style type="text/css">
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">HotSpot Coding Style</h1>
|
||||
</header>
|
||||
<nav id="TOC">
|
||||
<ul>
|
||||
<li><a href="#introduction">Introduction</a><ul>
|
||||
<li><a href="#why-care-about-style">Why Care About Style?</a></li>
|
||||
<li><a href="#counterexamples-and-updates">Counterexamples and Updates</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#structure-and-formatting">Structure and Formatting</a><ul>
|
||||
<li><a href="#factoring-and-class-design">Factoring and Class Design</a></li>
|
||||
<li><a href="#source-files">Source Files</a></li>
|
||||
<li><a href="#jtreg-tests">JTReg Tests</a></li>
|
||||
<li><a href="#naming">Naming</a></li>
|
||||
<li><a href="#commenting">Commenting</a></li>
|
||||
<li><a href="#macros">Macros</a></li>
|
||||
<li><a href="#whitespace">Whitespace</a></li>
|
||||
<li><a href="#miscellaneous">Miscellaneous</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#use-of-c-features">Use of C++ Features</a><ul>
|
||||
<li><a href="#error-handling">Error Handling</a></li>
|
||||
<li><a href="#rtti-runtime-type-information">RTTI (Runtime Type Information)</a></li>
|
||||
<li><a href="#memory-allocation">Memory Allocation</a></li>
|
||||
<li><a href="#class-inheritance">Class Inheritance</a></li>
|
||||
<li><a href="#namespaces">Namespaces</a></li>
|
||||
<li><a href="#c-standard-library">C++ Standard Library</a></li>
|
||||
<li><a href="#type-deduction">Type Deduction</a></li>
|
||||
<li><a href="#expression-sfinae">Expression SFINAE</a></li>
|
||||
<li><a href="#enum">enum</a></li>
|
||||
<li><a href="#thread_local">thread_local</a></li>
|
||||
<li><a href="#nullptr">nullptr</a></li>
|
||||
<li><a href="#atomic"><atomic></a></li>
|
||||
<li><a href="#additional-permitted-features">Additional Permitted Features</a></li>
|
||||
<li><a href="#excluded-features">Excluded Features</a></li>
|
||||
<li><a href="#undecided-features">Undecided Features</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
<p>This is a collection of rules, guidelines, and suggestions for writing HotSpot code. Following these will help new code fit in with existing HotSpot code, making it easier to read and maintain. Failure to follow these guidelines may lead to discussion during code reviews, if not outright rejection of a change.</p>
|
||||
<h3 id="why-care-about-style">Why Care About Style?</h3>
|
||||
<p>Some programmers seem to have lexers and even C preprocessors installed directly behind their eyeballs. The rest of us require code that is not only functionally correct but also easy to read. More than that, since there is no one style for easy-to-read code, and since a mashup of many styles is just as confusing as no style at all, it is important for coders to be conscious of the many implicit stylistic choices that historically have gone into the HotSpot code base.</p>
|
||||
<p>Some of these guidelines are driven by the cross-platform requirements for HotSpot. Shared code must work on a variety of platforms, and may encounter deficiencies in some. Using platform conditionalization in shared code is usually avoided, while shared code is strongly preferred to multiple platform-dependent implementations, so some language features may be recommended against.</p>
|
||||
<p>Some of the guidelines here are relatively arbitrary choices among equally plausible alternatives. The purpose of stating and enforcing these rules is largely to provide a consistent look to the code. That consistency makes the code more readable by avoiding non-functional distractions from the interesting functionality.</p>
|
||||
<p>When changing pre-existing code, it is reasonable to adjust it to match these conventions. Exception: If the pre-existing code clearly conforms locally to its own peculiar conventions, it is not worth reformatting the whole thing. Also consider separating changes that make extensive stylistic updates from those which make functional changes.</p>
|
||||
<h3 id="counterexamples-and-updates">Counterexamples and Updates</h3>
|
||||
<p>Many of the guidelines mentioned here have (sometimes widespread) counterexamples in the HotSpot code base. Finding a counterexample is not sufficient justification for new code to follow the counterexample as a precedent, since readers of your code will rightfully expect your code to follow the greater bulk of precedents documented here.</p>
|
||||
<p>Occasionally a guideline mentioned here may be just out of synch with the actual HotSpot code base. If you find that a guideline is consistently contradicted by a large number of counterexamples, please bring it up for discussion and possible change. The architectural rule, of course, is "When in Rome do as the Romans". Sometimes in the suburbs of Rome the rules are a little different; these differences can be pointed out here.</p>
|
||||
<p>Proposed changes should be discussed on the <a href="mailto:hotspot-dev@openjdk.java.net">HotSpot Developers</a> mailing list, and approved by <a href="https://en.wikipedia.org/wiki/Rough_consensus">rough consensus</a> of the <a href="https://openjdk.java.net/census#hotspot">HotSpot Group</a> Members. The Group Lead determines whether consensus has been reached. Changes are likely to be cautious and incremental, since HotSpot coders have been using these guidelines for years.</p>
|
||||
<h2 id="structure-and-formatting">Structure and Formatting</h2>
|
||||
<h3 id="factoring-and-class-design">Factoring and Class Design</h3>
|
||||
<ul>
|
||||
<li><p>Group related code together, so readers can concentrate on one section of one file.</p></li>
|
||||
<li><p>Classes are the primary code structuring mechanism. Place related functionality in a class, or a set of related classes. Use of either namespaces or public non-member functions is rare in HotSpot code. Static non-member functions are not uncommon.</p></li>
|
||||
<li><p>If a class <code>FooBar</code> is going to be used in more than one place, put it a file named fooBar.hpp and fooBar.cpp. If the class is a sidekick to a more important class <code>BazBat</code>, it can go in bazBat.hpp.</p></li>
|
||||
<li><p>Put a member function <code>FooBar::bang</code> into the same file that defined <code>FooBar</code>, or its associated <em>.inline.hpp or </em>.cpp file.</p></li>
|
||||
<li><p>Use public accessor functions for member variables accessed outside the class.</p></li>
|
||||
<li><p>Assign names to constant literals and use the names instead.</p></li>
|
||||
<li><p>Keep functions small, a screenful at most. Split out chunks of logic into file-local classes or static functions if needed.</p></li>
|
||||
<li><p>Factor away nonessential complexity into local inline helper functions and helper classes.</p></li>
|
||||
<li><p>Think clearly about internal invariants that apply to each class, and document them in the form of asserts within member functions.</p></li>
|
||||
<li><p>Make simple, self-evident contracts for member functions. If you cannot communicate a simple contract, redesign the class.</p></li>
|
||||
<li><p>Implement classes as if expecting rough usage by clients. Check for incorrect usage of a class using <code>assert(...)</code>, <code>guarantee(...)</code>, <code>ShouldNotReachHere()</code> and comments wherever needed. Performance is almost never a reason to omit asserts.</p></li>
|
||||
<li><p>When possible, design as if for reusability. This forces a clear design of the class's externals, and clean hiding of its internals.</p></li>
|
||||
<li><p>Initialize all variables and data structures to a known state. If a class has a constructor, initialize it there.</p></li>
|
||||
<li><p>Do no optimization before its time. Prove the need to optimize.</p></li>
|
||||
<li><p>When you must defactor to optimize, preserve as much structure as possible. If you must hand-inline some name, label the local copy with the original name.</p></li>
|
||||
<li><p>If you need to use a hidden detail (e.g., a structure offset), name it (as a constant or function) in the class that owns it.</p></li>
|
||||
<li><p>Don't use the Copy and Paste keys to replicate more than a couple lines of code. Name what you must repeat.</p></li>
|
||||
<li><p>If a class needs a member function to change a user-visible attribute, the change should be done with a "setter" accessor matched to the simple "getter".</p></li>
|
||||
</ul>
|
||||
<h3 id="source-files">Source Files</h3>
|
||||
<ul>
|
||||
<li><p>All source files must have a globally unique basename. The build system depends on this uniqueness.</p></li>
|
||||
<li><p>Do not put non-trivial function implementations in .hpp files. If the implementation depends on other .hpp files, put it in a .cpp or a .inline.hpp file.</p></li>
|
||||
<li><p>.inline.hpp files should only be included in .cpp or .inline.hpp files.</p></li>
|
||||
<li><p>All .cpp files include precompiled.hpp as the first include line.</p></li>
|
||||
<li><p>precompiled.hpp is just a build time optimization, so don't rely on it to resolve include problems.</p></li>
|
||||
<li><p>Keep the include lines alphabetically sorted.</p></li>
|
||||
<li><p>Put conditional inclusions (<code>#if ...</code>) at the end of the include list.</p></li>
|
||||
</ul>
|
||||
<h3 id="jtreg-tests">JTReg Tests</h3>
|
||||
<ul>
|
||||
<li><p>JTReg tests should have meaningful names.</p></li>
|
||||
<li><p>JTReg tests associated with specific bugs should be tagged with the <code>@bug</code> keyword in the test description.</p></li>
|
||||
<li><p>JTReg tests should be organized by component or feature under <code>test/</code>, in a directory hierarchy that generally follows that of the <code>src/</code> directory. There may be additional subdirectories to further categorize tests by feature. This structure makes it easy to run a collection of tests associated with a specific feature by specifying the associated directory as the source of the tests to run.</p>
|
||||
<ul>
|
||||
<li>Some (older) tests use the associated bug number in the directory name, the test name, or both. That naming style should no longer be used, with existing tests using that style being candidates for migration.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
<h3 id="naming">Naming</h3>
|
||||
<ul>
|
||||
<li><p>The length of a name may be correlated to the size of its scope. In particular, short names (even single letter names) may be fine in a small scope, but are usually inappropriate for larger scopes.</p></li>
|
||||
<li><p>Prefer whole words rather than abbreviations, unless the abbreviation is more widely used than the long form in the code's domain.</p></li>
|
||||
<li><p>Choose names consistently. Do not introduce spurious variations. Abbreviate corresponding terms to a consistent length.</p></li>
|
||||
<li><p>Global names must be unique, to avoid <a href="https://en.cppreference.com/w/cpp/language/definition" title="One Definition Rule">One Definition Rule</a> (ODR) violations. A common prefixing scheme for related global names is often used. (This is instead of using namespaces, which are mostly avoided in HotSpot.)</p></li>
|
||||
<li><p>Don't give two names to the semantically same thing. But use different names for semantically different things, even if they are representationally the same. (So use meaningful <code>typedef</code> or template alias names where appropriate.)</p></li>
|
||||
<li><p>When choosing names, avoid categorical nouns like "variable", "field", "parameter", "value", and verbs like "compute", "get". (<code>storeValue(int param)</code> is bad.)</p></li>
|
||||
<li><p>Type names and global names should use mixed-case with the first letter of each word capitalized (<code>FooBar</code>).</p></li>
|
||||
<li><p>Embedded abbreviations in otherwise mixed-case names are usually capitalized entirely rather than being treated as a single word with only the initial letter capitalized, e.g. "HTML" rather than "Html".</p></li>
|
||||
<li><p>Function and local variable names use lowercase with words separated by a single underscore (<code>foo_bar</code>).</p></li>
|
||||
<li><p>Class data member names have a leading underscore, and use lowercase with words separated by a single underscore (<code>_foo_bar</code>).</p></li>
|
||||
<li><p>Constant names may be upper-case or mixed-case, according to historical necessity. (Note: There are many examples of constants with lowercase names.)</p></li>
|
||||
<li><p>Constant names should follow an existing pattern, and must have a distinct appearance from other names in related APIs.</p></li>
|
||||
<li><p>Class and type names should be noun phrases. Consider an "er" suffix for a class that represents an action.</p></li>
|
||||
<li><p>Function names should be verb phrases that reflect changes of state known to a class's user, or else noun phrases if they cause no change of state visible to the class's user.</p></li>
|
||||
<li><p>Getter accessor names are noun phrases, with no "<code>get_</code>" noise word. Boolean getters can also begin with "<code>is_</code>" or "<code>has_</code>". Member function for reading data members usually have the same name as the data member, exclusive of the leading underscore.</p></li>
|
||||
<li><p>Setter accessor names prepend "<code>set_</code>" to the getter name.</p></li>
|
||||
<li><p>Other member function names are verb phrases, as if commands to the receiver.</p></li>
|
||||
<li><p>Avoid leading underscores (as "<code>_oop</code>") except in cases required above. (Names with leading underscores can cause portability problems.)</p></li>
|
||||
</ul>
|
||||
<h3 id="commenting">Commenting</h3>
|
||||
<ul>
|
||||
<li><p>Clearly comment subtle fixes.</p></li>
|
||||
<li><p>Clearly comment tricky classes and functions.</p></li>
|
||||
<li><p>If you have to choose between commenting code and writing wiki content, comment the code. Link from the wiki to the source file if it makes sense.</p></li>
|
||||
<li><p>As a general rule don't add bug numbers to comments (they would soon overwhelm the code). But if the bug report contains significant information that can't reasonably be added as a comment, then refer to the bug report.</p></li>
|
||||
<li><p>Personal names are discouraged in the source code, which is a team product.</p></li>
|
||||
</ul>
|
||||
<h3 id="macros">Macros</h3>
|
||||
<ul>
|
||||
<li><p>You can almost always use an inline function or class instead of a macro. Use a macro only when you really need it.</p></li>
|
||||
<li><p>Templates may be preferable to multi-line macros. (There may be subtle performance effects with templates on some platforms; revert to macros if absolutely necessary.)</p></li>
|
||||
<li><p><code>#ifdef</code>s should not be used to introduce platform-specific code into shared code (except for <code>_LP64</code>). They must be used to manage header files, in the pattern found at the top of every source file. They should be used mainly for major build features, including <code>PRODUCT</code>, <code>ASSERT</code>, <code>_LP64</code>, <code>INCLUDE_SERIALGC</code>, <code>COMPILER1</code>, etc.</p></li>
|
||||
<li><p>For build features such as <code>PRODUCT</code>, use <code>#ifdef PRODUCT</code> for multiple-line inclusions or exclusions.</p></li>
|
||||
<li><p>For short inclusions or exclusions based on build features, use macros like <code>PRODUCT_ONLY</code> and <code>NOT_PRODUCT</code>. But avoid using them with multiple-line arguments, since debuggers do not handle that well.</p></li>
|
||||
<li><p>Use <code>CATCH</code>, <code>THROW</code>, etc. for HotSpot-specific exception processing.</p></li>
|
||||
</ul>
|
||||
<h3 id="whitespace">Whitespace</h3>
|
||||
<ul>
|
||||
<li><p>In general, don't change whitespace unless it improves readability or consistency. Gratuitous whitespace changes will make integrations and backports more difficult.</p></li>
|
||||
<li><p>Use One-True-Brace-Style. The opening brace for a function or class is normally at the end of the line; it is sometimes moved to the beginning of the next line for emphasis. Substatements are enclosed in braces, even if there is only a single statement. Extremely simple one-line statements may drop braces around a substatement.</p></li>
|
||||
<li><p>Indentation levels are two columns.</p></li>
|
||||
<li><p>There is no hard line length limit. That said, bear in mind that excessively long lines can cause difficulties. Some people like to have multiple side-by-side windows in their editors, and long lines may force them to choose among unpleasant options. They can use wide windows, reducing the number that can fit across the screen, and wasting a lot of screen real estate because most lines are not that long. Alternatively, they can have more windows across the screen, with long lines wrapping (or worse, requiring scrolling to see in their entirety), which is harder to read. Similar issues exist for side-by-side code reviews.</p></li>
|
||||
<li><p>Tabs are not allowed in code. Set your editor accordingly.<br> (Emacs: <code>(setq-default indent-tabs-mode nil)</code>.)</p></li>
|
||||
<li><p>Use good taste to break lines and align corresponding tokens on adjacent lines.</p></li>
|
||||
<li><p>Use spaces around operators, especially comparisons and assignments. (Relaxable for boolean expressions and high-precedence operators in classic math-style formulas.)</p></li>
|
||||
<li><p>Put spaces on both sides of control flow keywords <code>if</code>, <code>else</code>, <code>for</code>, <code>switch</code>, etc. Don't add spaces around the associated <em>control</em> expressions. Examples:</p>
|
||||
<pre><code>while (test_foo(args...)) { // Yes
|
||||
while(test_foo(args...)) { // No, missing space after while
|
||||
while ( test_foo(args...) ) { // No, excess spaces around control</code></pre></li>
|
||||
<li><p>Use extra parentheses in expressions whenever operator precedence seems doubtful. Always use parentheses in shift/mask expressions (<code><<</code>, <code>&</code>, <code>|</code>). Don't add whitespace immediately inside parentheses.</p></li>
|
||||
<li><p>Use more spaces and blank lines between larger constructs, such as classes or function definitions.</p></li>
|
||||
<li><p>If the surrounding code has any sort of vertical organization, adjust new lines horizontally to be consistent with that organization. (E.g., trailing backslashes on long macro definitions often align.)</p></li>
|
||||
</ul>
|
||||
<h3 id="miscellaneous">Miscellaneous</h3>
|
||||
<ul>
|
||||
<li><p>Use the <a href="https://en.cppreference.com/w/cpp/language/raii" title="Resource Acquisition Is Initialization">Resource Acquisition Is Initialization</a> (RAII) design pattern to manage bracketed critical sections. See class <code>ResourceMark</code> for an example.</p></li>
|
||||
<li>Avoid implicit conversions to <code>bool</code>.
|
||||
<ul>
|
||||
<li>Use <code>bool</code> for boolean values.</li>
|
||||
<li>Do not use ints or pointers as (implicit) booleans with <code>&&</code>, <code>||</code>, <code>if</code>, <code>while</code>. Instead, compare explicitly, i.e. <code>if (x != 0)</code> or <code>if (ptr != nullptr)</code>, etc.</li>
|
||||
<li>Do not use declarations in <em>condition</em> forms, i.e. don't use <code>if (T v = value) { ... }</code>.</li>
|
||||
</ul></li>
|
||||
<li><p>Use functions from globalDefinitions.hpp and related files when performing bitwise operations on integers. Do not code directly as C operators, unless they are extremely simple. (Examples: <code>align_up</code>, <code>is_power_of_2</code>, <code>exact_log2</code>.)</p></li>
|
||||
<li><p>Use arrays with abstractions supporting range checks.</p></li>
|
||||
<li><p>Always enumerate all cases in a switch statement or provide a default case. It is ok to have an empty default with comment.</p></li>
|
||||
</ul>
|
||||
<h2 id="use-of-c-features">Use of C++ Features</h2>
|
||||
<p>HotSpot was originally written in a subset of the C++98/03 language. More recently, support for C++14 is provided, though again, HotSpot only uses a subset. (Backports to JDK versions lacking support for more recent Standards must of course stick with the original C++98/03 subset.)</p>
|
||||
<p>This section describes that subset. Features from the C++98/03 language may be used unless explicitly excluded here. Features from C++11 and C++14 may be explicitly permitted or explicitly excluded, and discussed accordingly here. There is a third category, undecided features, about which HotSpot developers have not yet reached a consensus, or perhaps have not discussed at all. Use of these features is also excluded.</p>
|
||||
<p>(The use of some features may not be immediately obvious and may slip in anyway, since the compiler will accept them. The code review process is the main defense against this.)</p>
|
||||
<p>Some features are discussed in their own subsection, typically to provide more extensive discussion or rationale for limitations. Features that don't have their own subsection are listed in omnibus feature sections for permitted, excluded, and undecided features.</p>
|
||||
<p>Lists of new features for C++11 and C++14, along with links to their descriptions, can be found in the online documentation for some of the compilers and libraries. The C++14 Standard is the definitive description.</p>
|
||||
<ul>
|
||||
<li><a href="https://gcc.gnu.org/projects/cxx-status.html">C++ Standards Support in GCC</a></li>
|
||||
<li><a href="https://clang.llvm.org/cxx_status.html">C++ Support in Clang</a></li>
|
||||
<li><a href="https://docs.microsoft.com/en-us/cpp/visual-cpp-language-conformance">Visual C++ Language Conformance</a></li>
|
||||
<li><a href="https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html">libstdc++ Status</a></li>
|
||||
<li><a href="https://libcxx.llvm.org/cxx1y_status.html">libc++ Status</a></li>
|
||||
</ul>
|
||||
<p>As a rule of thumb, permitting features which simplify writing code and, especially, reading code, is encouraged.</p>
|
||||
<p>Similar discussions for some other projects:</p>
|
||||
<ul>
|
||||
<li><p><a href="https://google.github.io/styleguide/cppguide.html">Google C++ Style Guide</a> — Currently (2020) targeting C++17.</p></li>
|
||||
<li><p><a href="https://chromium-cpp.appspot.com">C++11 and C++14 use in Chromium</a> — Categorizes features as allowed, banned, or to be discussed.</p></li>
|
||||
<li><p><a href="https://llvm.org/docs/CodingStandards.html">llvm Coding Standards</a> — Currently (2020) targeting C++14.</p></li>
|
||||
<li><p><a href="https://firefox-source-docs.mozilla.org/code-quality/coding-style/using_cxx_in_firefox_code.html">Using C++ in Mozilla code</a> — C++17 support is required for recent versions (2020).</p></li>
|
||||
</ul>
|
||||
<h3 id="error-handling">Error Handling</h3>
|
||||
<p>Do not use exceptions. Exceptions are disabled by the build configuration for some platforms.</p>
|
||||
<p>Rationale: There is significant concern over the performance cost of exceptions and their usage model and implications for maintainable code. That's not just a matter of history that has been fixed; there remain questions and problems even today (2019). See, for example, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf">Zero cost deterministic exceptions</a>. Because of this, HotSpot has always used a build configuration that disables exceptions where that is available. As a result, HotSpot code uses error handling mechanisms such as two-phase construction, factory functions, returning error codes, and immediate termination. Even if the cost of exceptions were not a concern, the existing body of code was not written with exception safety in mind. Making HotSpot exception safe would be a very large undertaking.</p>
|
||||
<p>In addition to the usual alternatives to exceptions, HotSpot provides its own exception mechanism. This is based on a set of macros defined in utilities/exceptions.hpp.</p>
|
||||
<h3 id="rtti-runtime-type-information">RTTI (Runtime Type Information)</h3>
|
||||
<p>Do not use <a href="https://en.wikipedia.org/wiki/Run-time_type_information" title="Runtime Type Information">Runtime Type Information</a> (RTTI). <a href="https://en.wikipedia.org/wiki/Run-time_type_information" title="Runtime Type Information">RTTI</a> is disabled by the build configuration for some platforms. Among other things, this means <code>dynamic_cast</code> cannot be used.</p>
|
||||
<p>Rationale: Other than to implement exceptions (which HotSpot doesn't use), most potential uses of <a href="https://en.wikipedia.org/wiki/Run-time_type_information" title="Runtime Type Information">RTTI</a> are better done via virtual functions. Some of the remainder can be replaced by bespoke mechanisms. The cost of the additional runtime data structures needed to support <a href="https://en.wikipedia.org/wiki/Run-time_type_information" title="Runtime Type Information">RTTI</a> are deemed not worthwhile, given the alternatives.</p>
|
||||
<h3 id="memory-allocation">Memory Allocation</h3>
|
||||
<p>Do not use the standard global allocation and deallocation functions (operator new and related functions). Use of these functions by HotSpot code is disabled for some platforms.</p>
|
||||
<p>Rationale: HotSpot often uses "resource" or "arena" allocation. Even where heap allocation is used, the standard global functions are avoided in favor of wrappers around malloc and free that support the VM's Native Memory Tracking (NMT) feature.</p>
|
||||
<p>Native memory allocation failures are often treated as non-recoverable. The place where "out of memory" is (first) detected may be an innocent bystander, unrelated to the actual culprit.</p>
|
||||
<h3 id="class-inheritance">Class Inheritance</h3>
|
||||
<p>Use public single inheritance.</p>
|
||||
<p>Prefer composition rather than non-public inheritance.</p>
|
||||
<p>Restrict inheritance to the "is-a" case; use composition rather than non-is-a related inheritance.</p>
|
||||
<p>Avoid multiple inheritance. Never use virtual inheritance.</p>
|
||||
<h3 id="namespaces">Namespaces</h3>
|
||||
<p>Avoid using namespaces. HotSpot code normally uses "all static" classes rather than namespaces for grouping. An "all static" class is not instantiable, has only static members, and is normally derived (possibly indirectly) from the helper class <code>AllStatic</code>.</p>
|
||||
<p>Benefits of using such classes include:</p>
|
||||
<ul>
|
||||
<li><p>Provides access control for members, which is unavailable with namespaces.</p></li>
|
||||
<li><p>Avoids <a href="https://en.cppreference.com/w/cpp/language/adl" title="Argument Dependent Lookup">Argument Dependent Lookup</a> (ADL).</p></li>
|
||||
<li><p>Closed for additional members. Namespaces allow names to be added in multiple contexts, making it harder to see the complete API.</p></li>
|
||||
</ul>
|
||||
<p>Namespaces should be used only in cases where one of those "benefits" is actually a hindrance.</p>
|
||||
<p>In particular, don't use anonymous namespaces. They seem like they should be useful, and indeed have some real benefits for naming and generated code size on some platforms. Unfortunately, debuggers don't seem to like them at all.</p>
|
||||
<p><a href="https://groups.google.com/forum/#!topic/mozilla.dev.platform/KsaG3lEEaRM" class="uri">https://groups.google.com/forum/#!topic/mozilla.dev.platform/KsaG3lEEaRM</a><br> Suggests Visual Studio debugger might not be able to refer to anonymous namespace symbols, so can't set breakpoints in them. Though the discussion seems to go back and forth on that.</p>
|
||||
<p><a href="https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html" class="uri">https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html</a><br> Search for "Anonymous namespaces" Suggests preferring "static" to anonymous namespaces where applicable, because of poor debugger support for anonymous namespaces.</p>
|
||||
<p><a href="https://sourceware.org/bugzilla/show_bug.cgi?id=16874" class="uri">https://sourceware.org/bugzilla/show_bug.cgi?id=16874</a><br> Bug for similar gdb problems.</p>
|
||||
<h3 id="c-standard-library">C++ Standard Library</h3>
|
||||
<p>Avoid using the C++ Standard Library.</p>
|
||||
<p>Historically, HotSpot has mostly avoided use of the Standard Library.</p>
|
||||
<p>(It used to be impossible to use most of it in shared code, because the build configuration for Solaris with Solaris Studio made all but a couple of pieces inaccessible. Support for header-only parts was added in mid-2017. Support for Solaris was removed in 2020.)</p>
|
||||
<p>Some reasons for this include</p>
|
||||
<ul>
|
||||
<li><p>Exceptions. Perhaps the largest core issue with adopting the use of Standard Library facilities is exceptions. HotSpot does not use exceptions and, for platforms which allow doing so, builds with them turned off. Many Standard Library facilities implicitly or explicitly use exceptions.</p></li>
|
||||
<li><p><code>assert</code>. An issue that is quickly encountered is the <code>assert</code> macro name collision (<a href="https://bugs.openjdk.java.net/browse/JDK-8007770">JDK-8007770</a>). Some mechanism for addressing this would be needed before much of the Standard Library could be used. (Not all Standard Library implementations use assert in header files, but some do.)</p></li>
|
||||
<li><p>Memory allocation. HotSpot requires explicit control over where allocations occur. The C++98/03 <code>std::allocator</code> class is too limited to support our usage. (Changes in more recent Standards may remove this limitation.)</p></li>
|
||||
<li><p>Implementation vagaries. Bugs, or simply different implementation choices, can lead to different behaviors among the various Standard Libraries we need to deal with.</p></li>
|
||||
<li><p>Inconsistent naming conventions. HotSpot and the C++ Standard use different naming conventions. The coexistence of those different conventions might appear jarring and reduce readability.</p></li>
|
||||
</ul>
|
||||
<p>There are a few exceptions to this rule.</p>
|
||||
<ul>
|
||||
<li><code>#include <new></code> to use placement <code>new</code>, <code>std::nothrow</code>, and <code>std::nothrow_t</code>.</li>
|
||||
<li><code>#include <limits></code> to use <code>std::numeric_limits</code>.</li>
|
||||
<li><code>#include <type_traits></code>.</li>
|
||||
<li><code>#include <cstddef></code> to use <code>std::nullptr_t</code>.</li>
|
||||
</ul>
|
||||
<p>TODO: Rather than directly #including (permitted) Standard Library headers, use a convention of #including wrapper headers (in some location like hotspot/shared/stdcpp). This provides a single place for dealing with issues we might have for any given header, esp. platform-specific issues.</p>
|
||||
<h3 id="type-deduction">Type Deduction</h3>
|
||||
<p>Use type deduction only if it makes the code clearer or safer. Do not use it merely to avoid the inconvenience of writing an explicit type, unless that type is itself difficult to write. An example of the latter is a function template return type that depends on template parameters in a non-trivial way.</p>
|
||||
<p>There are several contexts where types are deduced.</p>
|
||||
<ul>
|
||||
<li><p>Function argument deduction. This is always permitted, and indeed encouraged. It is nearly always better to allow the type of a function template argument to be deduced rather than explicitly specified.</p></li>
|
||||
<li><p><code>auto</code> variable declarations (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf">n1984</a>)<br> For local variables, this can be used to make the code clearer by eliminating type information that is obvious or irrelevant. Excessive use can make code much harder to understand.</p></li>
|
||||
<li><p>Function return type deduction (<a href="https://isocpp.org/files/papers/N3638.html">n3638</a>)<br> Only use if the function body has a very small number of <code>return</code> statements, and generally relatively little other code.</p></li>
|
||||
<li><p>Generic lambdas. Lambdas are not (yet) permitted.</p></li>
|
||||
<li><p>Lambda init captures. Lambdas are not (yet) permitted.</p></li>
|
||||
</ul>
|
||||
<h3 id="expression-sfinae">Expression SFINAE</h3>
|
||||
<p><a href="https://en.cppreference.com/w/cpp/language/sfinae" title="Substitution Failure Is Not An Error">Substitution Failure Is Not An Error</a> (SFINAE) is a template metaprogramming technique that makes use of template parameter substitution failures to make compile-time decisions.</p>
|
||||
<p>C++11 relaxed the rules for what constitutes a hard-error when attempting to substitute template parameters with template arguments, making most deduction errors be substitution errors; see (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html">n2634</a>). This makes <a href="https://en.cppreference.com/w/cpp/language/sfinae" title="Substitution Failure Is Not An Error">SFINAE</a> more powerful and easier to use. However, the implementation complexity for this change is significant, and this seems to be a place where obscure corner-case bugs in various compilers can be found. So while this feature can (and indeed should) be used (and would be difficult to avoid), caution should be used when pushing to extremes.</p>
|
||||
<p>Here are a few closely related example bugs:<br> <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468" class="uri">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468</a><br> <a href="https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html" class="uri">https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html</a></p>
|
||||
<h3 id="enum">enum</h3>
|
||||
<p>Where appropriate, <em>scoped-enums</em> should be used. (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf">n2347</a>)</p>
|
||||
<p>Use of <em>unscoped-enums</em> is permitted, though ordinary constants may be preferable when the automatic initializer feature isn't used.</p>
|
||||
<p>The underlying type (the <em>enum-base</em>) of an unscoped enum type should always be specified explicitly. When unspecified, the underlying type is dependent on the range of the enumerator values and the platform.</p>
|
||||
<p>The underlying type of a <em>scoped-enum</em> should also be specified explicitly if conversions may be applied to values of that type.</p>
|
||||
<p>Due to bugs in certain (very old) compilers, there is widespread use of enums and avoidance of in-class initialization of static integral constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants.</p>
|
||||
<h3 id="thread_local">thread_local</h3>
|
||||
<p>Do not use <code>thread_local</code> (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm">n2659</a>); instead, use the HotSpot macro <code>THREAD_LOCAL</code>. The initializer must be a constant expression.</p>
|
||||
<p>As was discussed in the review for <a href="https://mail.openjdk.java.net/pipermail/hotspot-dev/2019-September/039487.html">JDK-8230877</a>, <code>thread_local</code> allows dynamic initialization and destruction semantics. However, that support requires a run-time penalty for references to non-function-local <code>thread_local</code> variables defined in a different translation unit, even if they don't need dynamic initialization. Dynamic initialization and destruction of namespace-scoped thread local variables also has the same ordering problems as for ordinary namespace-scoped variables.</p>
|
||||
<h3 id="nullptr">nullptr</h3>
|
||||
<p>Prefer <code>nullptr</code> (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf">n2431</a>) to <code>NULL</code>. Don't use (constexpr or literal) 0 for pointers.</p>
|
||||
<p>For historical reasons there are widespread uses of both <code>NULL</code> and of integer 0 as a pointer value.</p>
|
||||
<h3 id="atomic"><atomic></h3>
|
||||
<p>Do not use facilities provided by the <code><atomic></code> header (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html">n2427</a>), (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm">n2752</a>); instead, use the HotSpot <code>Atomic</code> class and related facilities.</p>
|
||||
<p>Atomic operations in HotSpot code must have semantics which are consistent with those provided by the JDK's compilers for Java. There are platform-specific implementation choices that a C++ compiler might make or change that are outside the scope of the C++ Standard, and might differ from what the Java compilers implement.</p>
|
||||
<p>In addition, HotSpot <code>Atomic</code> has a concept of "conservative" memory ordering, which may differ from (may be stronger than) sequentially consistent. There are algorithms in HotSpot that are believed to rely on that ordering.</p>
|
||||
<h3 id="additional-permitted-features">Additional Permitted Features</h3>
|
||||
<ul>
|
||||
<li><p><code>constexpr</code> (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf">n2235</a>) (<a href="https://isocpp.org/files/papers/N3652.html">n3652</a>)</p></li>
|
||||
<li><p>Sized deallocation (<a href="https://isocpp.org/files/papers/n3778.html">n3778</a>)</p></li>
|
||||
<li><p>Variadic templates (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf">n2242</a>) (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf">n2555</a>)</p></li>
|
||||
<li><p>Static assertions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html">n1720</a>)</p></li>
|
||||
<li><p><code>decltype</code> (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">n2343</a>) (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">n3276</a>)</p></li>
|
||||
<li><p>Right angle brackets (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html">n1757</a>)</p></li>
|
||||
<li><p>Default template arguments for function templates (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226">CWG D226</a>)</p></li>
|
||||
<li><p>Template aliases (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf">n2258</a>)</p></li>
|
||||
<li><p>Delegating constructors (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf">n1986</a>)</p></li>
|
||||
<li><p>Explicit conversion operators (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">n2437</a>)</p></li>
|
||||
<li><p>Standard Layout Types (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm">n2342</a>)</p></li>
|
||||
<li><p>Defaulted and deleted functions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">n2346</a>)</p></li>
|
||||
<li><p>Dynamic initialization and destruction with concurrency (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm">n2660</a>)</p></li>
|
||||
<li><p><code>final</code> virtual specifiers for classes and virtual functions (<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm">n2928</a>), (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm">n3206</a>), (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm">n3272</a>)</p></li>
|
||||
<li><p>Local and unnamed types as template parameters (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm">n2657</a>)</p></li>
|
||||
</ul>
|
||||
<h3 id="excluded-features">Excluded Features</h3>
|
||||
<ul>
|
||||
<li>New string and character literals
|
||||
<ul>
|
||||
<li>New character types (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html">n2249</a>)</li>
|
||||
<li>Unicode string literals (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">n2442</a>)</li>
|
||||
<li>Raw string literals (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">n2442</a>)</li>
|
||||
<li>Universal character name literals (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html">n2170</a>)</li>
|
||||
</ul>
|
||||
<p>HotSpot doesn't need any of the new character and string literal types.</p></li>
|
||||
<li><p>User-defined literals (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf">n2765</a>) — User-defined literals should not be added casually, but only through a proposal to add a specific UDL.</p></li>
|
||||
<li><p>Inline namespaces (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm">n2535</a>) — HotSpot makes very limited use of namespaces.</p></li>
|
||||
<li><p><code>using namespace</code> directives. In particular, don't use <code>using namespace std;</code> to avoid needing to qualify Standard Library names.</p></li>
|
||||
<li><p>Propagating exceptions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html">n2179</a>) — HotSpot does not permit the use of exceptions, so this feature isn't useful.</p></li>
|
||||
<li><p>Avoid namespace-scoped variables with non-constexpr initialization. In particular, avoid variables with types requiring non-trivial initialization or destruction. Initialization order problems can be difficult to deal with and lead to surprises, as can destruction ordering. HotSpot doesn't generally try to cleanup on exit, and running destructors at exit can also lead to problems.</p></li>
|
||||
<li><p><code>[[deprecated]]</code> attribute (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html">n3760</a>) — Not relevant in HotSpot code.</p></li>
|
||||
<li><p>Avoid most operator overloading, preferring named functions. When operator overloading is used, ensure the semantics conform to the normal expected behavior of the operation.</p></li>
|
||||
<li><p>Avoid most implicit conversion constructors and (implicit or explicit) conversion operators. (Note that conversion to <code>bool</code> isn't needed in HotSpot code because of the "no implicit boolean" guideline.)</p></li>
|
||||
<li><p>Avoid covariant return types.</p></li>
|
||||
<li><p>Avoid <code>goto</code> statements.</p></li>
|
||||
</ul>
|
||||
<h3 id="undecided-features">Undecided Features</h3>
|
||||
<p>This list is incomplete; it serves to explicitly call out some features that have not yet been discussed.</p>
|
||||
<ul>
|
||||
<li><p><code>overrides</code> virtual specifiers for virtual functions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm">n3272</a>)</p></li>
|
||||
<li><p>Trailing return type syntax for functions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm">n2541</a>)</p></li>
|
||||
<li><p>Variable templates (<a href="https://isocpp.org/files/papers/N3651.pdf">n3651</a>)</p></li>
|
||||
<li><p>Member initializers and aggregates (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html">n3653</a>)</p></li>
|
||||
<li><p><code>[[noreturn]]</code> attribute (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf">n2761</a>)</p></li>
|
||||
<li><p>Rvalue references and move semantics</p></li>
|
||||
<li><p>Lambdas</p></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,828 +0,0 @@
|
||||
% HotSpot Coding Style
|
||||
|
||||
## Introduction
|
||||
|
||||
This is a collection of rules, guidelines, and suggestions for writing
|
||||
HotSpot code. Following these will help new code fit in with existing
|
||||
HotSpot code, making it easier to read and maintain. Failure to
|
||||
follow these guidelines may lead to discussion during code reviews, if
|
||||
not outright rejection of a change.
|
||||
|
||||
### Why Care About Style?
|
||||
|
||||
Some programmers seem to have lexers and even C preprocessors
|
||||
installed directly behind their eyeballs. The rest of us require code
|
||||
that is not only functionally correct but also easy to read. More than
|
||||
that, since there is no one style for easy-to-read code, and since a
|
||||
mashup of many styles is just as confusing as no style at all, it is
|
||||
important for coders to be conscious of the many implicit stylistic
|
||||
choices that historically have gone into the HotSpot code base.
|
||||
|
||||
Some of these guidelines are driven by the cross-platform requirements
|
||||
for HotSpot. Shared code must work on a variety of platforms, and may
|
||||
encounter deficiencies in some. Using platform conditionalization in
|
||||
shared code is usually avoided, while shared code is strongly
|
||||
preferred to multiple platform-dependent implementations, so some
|
||||
language features may be recommended against.
|
||||
|
||||
Some of the guidelines here are relatively arbitrary choices among
|
||||
equally plausible alternatives. The purpose of stating and enforcing
|
||||
these rules is largely to provide a consistent look to the code. That
|
||||
consistency makes the code more readable by avoiding non-functional
|
||||
distractions from the interesting functionality.
|
||||
|
||||
When changing pre-existing code, it is reasonable to adjust it to
|
||||
match these conventions. Exception: If the pre-existing code clearly
|
||||
conforms locally to its own peculiar conventions, it is not worth
|
||||
reformatting the whole thing. Also consider separating changes that
|
||||
make extensive stylistic updates from those which make functional
|
||||
changes.
|
||||
|
||||
### Counterexamples and Updates
|
||||
|
||||
Many of the guidelines mentioned here have (sometimes widespread)
|
||||
counterexamples in the HotSpot code base. Finding a counterexample is
|
||||
not sufficient justification for new code to follow the counterexample
|
||||
as a precedent, since readers of your code will rightfully expect your
|
||||
code to follow the greater bulk of precedents documented here.
|
||||
|
||||
Occasionally a guideline mentioned here may be just out of synch with
|
||||
the actual HotSpot code base. If you find that a guideline is
|
||||
consistently contradicted by a large number of counterexamples, please
|
||||
bring it up for discussion and possible change. The architectural
|
||||
rule, of course, is "When in Rome do as the Romans". Sometimes in the
|
||||
suburbs of Rome the rules are a little different; these differences
|
||||
can be pointed out here.
|
||||
|
||||
Proposed changes should be discussed on the
|
||||
[HotSpot Developers](mailto:hotspot-dev@openjdk.java.net) mailing
|
||||
list, and approved by
|
||||
[rough consensus](https://en.wikipedia.org/wiki/Rough_consensus) of
|
||||
the [HotSpot Group](https://openjdk.java.net/census#hotspot) Members.
|
||||
The Group Lead determines whether consensus has been reached.
|
||||
Changes are likely to be cautious and incremental, since HotSpot
|
||||
coders have been using these guidelines for years.
|
||||
|
||||
## Structure and Formatting
|
||||
|
||||
### Factoring and Class Design
|
||||
|
||||
* Group related code together, so readers can concentrate on one
|
||||
section of one file.
|
||||
|
||||
* Classes are the primary code structuring mechanism. Place related
|
||||
functionality in a class, or a set of related classes. Use of either
|
||||
namespaces or public non-member functions is rare in HotSpot code.
|
||||
Static non-member functions are not uncommon.
|
||||
|
||||
* If a class `FooBar` is going to be used in more than one place, put it
|
||||
a file named fooBar.hpp and fooBar.cpp. If the class is a sidekick
|
||||
to a more important class `BazBat`, it can go in bazBat.hpp.
|
||||
|
||||
* Put a member function `FooBar::bang` into the same file that defined
|
||||
`FooBar`, or its associated *.inline.hpp or *.cpp file.
|
||||
|
||||
* Use public accessor functions for member variables accessed
|
||||
outside the class.
|
||||
|
||||
* Assign names to constant literals and use the names instead.
|
||||
|
||||
* Keep functions small, a screenful at most. Split out chunks of
|
||||
logic into file-local classes or static functions if needed.
|
||||
|
||||
* Factor away nonessential complexity into local inline helper
|
||||
functions and helper classes.
|
||||
|
||||
* Think clearly about internal invariants that apply to each class,
|
||||
and document them in the form of asserts within member functions.
|
||||
|
||||
* Make simple, self-evident contracts for member functions. If you cannot
|
||||
communicate a simple contract, redesign the class.
|
||||
|
||||
* Implement classes as if expecting rough usage by clients. Check for
|
||||
incorrect usage of a class using `assert(...)`, `guarantee(...)`,
|
||||
`ShouldNotReachHere()` and comments wherever needed. Performance is
|
||||
almost never a reason to omit asserts.
|
||||
|
||||
* When possible, design as if for reusability. This forces a clear
|
||||
design of the class's externals, and clean hiding of its internals.
|
||||
|
||||
* Initialize all variables and data structures to a known state. If a
|
||||
class has a constructor, initialize it there.
|
||||
|
||||
* Do no optimization before its time. Prove the need to optimize.
|
||||
|
||||
* When you must defactor to optimize, preserve as much structure as
|
||||
possible. If you must hand-inline some name, label the local copy with
|
||||
the original name.
|
||||
|
||||
* If you need to use a hidden detail (e.g., a structure offset), name
|
||||
it (as a constant or function) in the class that owns it.
|
||||
|
||||
* Don't use the Copy and Paste keys to replicate more than a couple
|
||||
lines of code. Name what you must repeat.
|
||||
|
||||
* If a class needs a member function to change a user-visible attribute, the
|
||||
change should be done with a "setter" accessor matched to the simple
|
||||
"getter".
|
||||
|
||||
### Source Files
|
||||
|
||||
* All source files must have a globally unique basename. The build
|
||||
system depends on this uniqueness.
|
||||
|
||||
* Do not put non-trivial function implementations in .hpp files. If
|
||||
the implementation depends on other .hpp files, put it in a .cpp or
|
||||
a .inline.hpp file.
|
||||
|
||||
* .inline.hpp files should only be included in .cpp or .inline.hpp
|
||||
files.
|
||||
|
||||
* All .cpp files include precompiled.hpp as the first include line.
|
||||
|
||||
* precompiled.hpp is just a build time optimization, so don't rely on
|
||||
it to resolve include problems.
|
||||
|
||||
* Keep the include lines alphabetically sorted.
|
||||
|
||||
* Put conditional inclusions (`#if ...`) at the end of the include list.
|
||||
|
||||
### JTReg Tests
|
||||
|
||||
* JTReg tests should have meaningful names.
|
||||
|
||||
* JTReg tests associated with specific bugs should be tagged with the
|
||||
`@bug` keyword in the test description.
|
||||
|
||||
* JTReg tests should be organized by component or feature under
|
||||
`test/`, in a directory hierarchy that generally follows that of the
|
||||
`src/` directory. There may be additional subdirectories to further
|
||||
categorize tests by feature. This structure makes it easy to run a
|
||||
collection of tests associated with a specific feature by specifying
|
||||
the associated directory as the source of the tests to run.
|
||||
|
||||
* Some (older) tests use the associated bug number in the directory
|
||||
name, the test name, or both. That naming style should no longer be
|
||||
used, with existing tests using that style being candidates for migration.
|
||||
|
||||
### Naming
|
||||
|
||||
* The length of a name may be correlated to the size of its scope. In
|
||||
particular, short names (even single letter names) may be fine in a
|
||||
small scope, but are usually inappropriate for larger scopes.
|
||||
|
||||
* Prefer whole words rather than abbreviations, unless the
|
||||
abbreviation is more widely used than the long form in the code's
|
||||
domain.
|
||||
|
||||
* Choose names consistently. Do not introduce spurious
|
||||
variations. Abbreviate corresponding terms to a consistent length.
|
||||
|
||||
* Global names must be unique, to avoid [One Definition Rule][ODR] (ODR)
|
||||
violations. A common prefixing scheme for related global names is
|
||||
often used. (This is instead of using namespaces, which are mostly
|
||||
avoided in HotSpot.)
|
||||
|
||||
* Don't give two names to the semantically same thing. But use
|
||||
different names for semantically different things, even if they are
|
||||
representationally the same. (So use meaningful `typedef` or template
|
||||
alias names where appropriate.)
|
||||
|
||||
* When choosing names, avoid categorical nouns like "variable",
|
||||
"field", "parameter", "value", and verbs like "compute", "get".
|
||||
(`storeValue(int param)` is bad.)
|
||||
|
||||
* Type names and global names should use mixed-case with the first
|
||||
letter of each word capitalized (`FooBar`).
|
||||
|
||||
* Embedded abbreviations in
|
||||
otherwise mixed-case names are usually capitalized entirely rather
|
||||
than being treated as a single word with only the initial letter
|
||||
capitalized, e.g. "HTML" rather than "Html".
|
||||
|
||||
* Function and local variable names use lowercase with words separated
|
||||
by a single underscore (`foo_bar`).
|
||||
|
||||
* Class data member names have a leading underscore, and use lowercase
|
||||
with words separated by a single underscore (`_foo_bar`).
|
||||
|
||||
* Constant names may be upper-case or mixed-case, according to
|
||||
historical necessity. (Note: There are many examples of constants
|
||||
with lowercase names.)
|
||||
|
||||
* Constant names should follow an existing pattern, and must have a
|
||||
distinct appearance from other names in related APIs.
|
||||
|
||||
* Class and type names should be noun phrases. Consider an "er" suffix
|
||||
for a class that represents an action.
|
||||
|
||||
* Function names should be verb phrases that reflect changes of state
|
||||
known to a class's user, or else noun phrases if they cause no change
|
||||
of state visible to the class's user.
|
||||
|
||||
* Getter accessor names are noun phrases, with no "`get_`" noise
|
||||
word. Boolean getters can also begin with "`is_`" or "`has_`". Member
|
||||
function for reading data members usually have the same name as the
|
||||
data member, exclusive of the leading underscore.
|
||||
|
||||
* Setter accessor names prepend "`set_`" to the getter name.
|
||||
|
||||
* Other member function names are verb phrases, as if commands to the receiver.
|
||||
|
||||
* Avoid leading underscores (as "`_oop`") except in cases required
|
||||
above. (Names with leading underscores can cause portability
|
||||
problems.)
|
||||
|
||||
### Commenting
|
||||
|
||||
* Clearly comment subtle fixes.
|
||||
|
||||
* Clearly comment tricky classes and functions.
|
||||
|
||||
* If you have to choose between commenting code and writing wiki
|
||||
content, comment the code. Link from the wiki to the source file if
|
||||
it makes sense.
|
||||
|
||||
* As a general rule don't add bug numbers to comments (they would soon
|
||||
overwhelm the code). But if the bug report contains significant
|
||||
information that can't reasonably be added as a comment, then refer to
|
||||
the bug report.
|
||||
|
||||
* Personal names are discouraged in the source code, which is a team
|
||||
product.
|
||||
|
||||
### Macros
|
||||
|
||||
* You can almost always use an inline function or class instead of a
|
||||
macro. Use a macro only when you really need it.
|
||||
|
||||
* Templates may be preferable to multi-line macros. (There may be
|
||||
subtle performance effects with templates on some platforms; revert
|
||||
to macros if absolutely necessary.)
|
||||
|
||||
* `#ifdef`s should not be used to introduce platform-specific code
|
||||
into shared code (except for `_LP64`). They must be used to manage
|
||||
header files, in the pattern found at the top of every source
|
||||
file. They should be used mainly for major build features, including
|
||||
`PRODUCT`, `ASSERT`, `_LP64`, `INCLUDE_SERIALGC`, `COMPILER1`, etc.
|
||||
|
||||
* For build features such as `PRODUCT`, use `#ifdef PRODUCT` for
|
||||
multiple-line inclusions or exclusions.
|
||||
|
||||
* For short inclusions or exclusions based on build features, use
|
||||
macros like `PRODUCT_ONLY` and `NOT_PRODUCT`. But avoid using them
|
||||
with multiple-line arguments, since debuggers do not handle that
|
||||
well.
|
||||
|
||||
* Use `CATCH`, `THROW`, etc. for HotSpot-specific exception processing.
|
||||
|
||||
### Whitespace
|
||||
|
||||
* In general, don't change whitespace unless it improves readability
|
||||
or consistency. Gratuitous whitespace changes will make integrations
|
||||
and backports more difficult.
|
||||
|
||||
* Use One-True-Brace-Style. The opening brace for a function or class
|
||||
is normally at the end of the line; it is sometimes moved to the
|
||||
beginning of the next line for emphasis. Substatements are enclosed
|
||||
in braces, even if there is only a single statement. Extremely simple
|
||||
one-line statements may drop braces around a substatement.
|
||||
|
||||
* Indentation levels are two columns.
|
||||
|
||||
* There is no hard line length limit. That said, bear in mind that
|
||||
excessively long lines can cause difficulties. Some people like to
|
||||
have multiple side-by-side windows in their editors, and long lines
|
||||
may force them to choose among unpleasant options. They can use wide
|
||||
windows, reducing the number that can fit across the screen, and
|
||||
wasting a lot of screen real estate because most lines are not that
|
||||
long. Alternatively, they can have more windows across the screen,
|
||||
with long lines wrapping (or worse, requiring scrolling to see in
|
||||
their entirety), which is harder to read. Similar issues exist for
|
||||
side-by-side code reviews.
|
||||
|
||||
* Tabs are not allowed in code. Set your editor accordingly.<br>
|
||||
(Emacs: `(setq-default indent-tabs-mode nil)`.)
|
||||
|
||||
* Use good taste to break lines and align corresponding tokens on
|
||||
adjacent lines.
|
||||
|
||||
* Use spaces around operators, especially comparisons and
|
||||
assignments. (Relaxable for boolean expressions and high-precedence
|
||||
operators in classic math-style formulas.)
|
||||
|
||||
* Put spaces on both sides of control flow keywords `if`, `else`,
|
||||
`for`, `switch`, etc. Don't add spaces around the associated
|
||||
_control_ expressions. Examples:
|
||||
|
||||
```
|
||||
while (test_foo(args...)) { // Yes
|
||||
while(test_foo(args...)) { // No, missing space after while
|
||||
while ( test_foo(args...) ) { // No, excess spaces around control
|
||||
```
|
||||
|
||||
* Use extra parentheses in expressions whenever operator precedence
|
||||
seems doubtful. Always use parentheses in shift/mask expressions
|
||||
(`<<`, `&`, `|`). Don't add whitespace immediately inside
|
||||
parentheses.
|
||||
|
||||
* Use more spaces and blank lines between larger constructs, such as
|
||||
classes or function definitions.
|
||||
|
||||
* If the surrounding code has any sort of vertical organization,
|
||||
adjust new lines horizontally to be consistent with that
|
||||
organization. (E.g., trailing backslashes on long macro definitions
|
||||
often align.)
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* Use the [Resource Acquisition Is Initialization][RAII] (RAII)
|
||||
design pattern to manage bracketed critical
|
||||
sections. See class `ResourceMark` for an example.
|
||||
|
||||
* Avoid implicit conversions to `bool`.
|
||||
* Use `bool` for boolean values.
|
||||
* Do not use ints or pointers as (implicit) booleans with `&&`, `||`,
|
||||
`if`, `while`. Instead, compare explicitly, i.e. `if (x != 0)` or
|
||||
`if (ptr != nullptr)`, etc.
|
||||
* Do not use declarations in _condition_ forms, i.e. don't use
|
||||
`if (T v = value) { ... }`.
|
||||
|
||||
* Use functions from globalDefinitions.hpp and related files when
|
||||
performing bitwise
|
||||
operations on integers. Do not code directly as C operators, unless
|
||||
they are extremely simple. (Examples: `align_up`, `is_power_of_2`,
|
||||
`exact_log2`.)
|
||||
|
||||
* Use arrays with abstractions supporting range checks.
|
||||
|
||||
* Always enumerate all cases in a switch statement or provide a default
|
||||
case. It is ok to have an empty default with comment.
|
||||
|
||||
|
||||
## Use of C++ Features
|
||||
|
||||
HotSpot was originally written in a subset of the C++98/03 language.
|
||||
More recently, support for C++14 is provided, though again,
|
||||
HotSpot only uses a subset. (Backports to JDK versions lacking
|
||||
support for more recent Standards must of course stick with the
|
||||
original C++98/03 subset.)
|
||||
|
||||
This section describes that subset. Features from the C++98/03
|
||||
language may be used unless explicitly excluded here. Features from
|
||||
C++11 and C++14 may be explicitly permitted or explicitly excluded,
|
||||
and discussed accordingly here. There is a third category, undecided
|
||||
features, about which HotSpot developers have not yet reached a
|
||||
consensus, or perhaps have not discussed at all. Use of these
|
||||
features is also excluded.
|
||||
|
||||
(The use of some features may not be immediately obvious and may slip
|
||||
in anyway, since the compiler will accept them. The code review
|
||||
process is the main defense against this.)
|
||||
|
||||
Some features are discussed in their own subsection, typically to provide
|
||||
more extensive discussion or rationale for limitations. Features that
|
||||
don't have their own subsection are listed in omnibus feature sections
|
||||
for permitted, excluded, and undecided features.
|
||||
|
||||
Lists of new features for C++11 and C++14, along with links to their
|
||||
descriptions, can be found in the online documentation for some of the
|
||||
compilers and libraries. The C++14 Standard is the definitive
|
||||
description.
|
||||
|
||||
* [C++ Standards Support in GCC](https://gcc.gnu.org/projects/cxx-status.html)
|
||||
* [C++ Support in Clang](https://clang.llvm.org/cxx_status.html)
|
||||
* [Visual C++ Language Conformance](https://docs.microsoft.com/en-us/cpp/visual-cpp-language-conformance)
|
||||
* [libstdc++ Status](https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html)
|
||||
* [libc++ Status](https://libcxx.llvm.org/cxx1y_status.html)
|
||||
|
||||
As a rule of thumb, permitting features which simplify writing code
|
||||
and, especially, reading code, is encouraged.
|
||||
|
||||
Similar discussions for some other projects:
|
||||
|
||||
* [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) —
|
||||
Currently (2020) targeting C++17.
|
||||
|
||||
* [C++11 and C++14 use in Chromium](https://chromium-cpp.appspot.com) —
|
||||
Categorizes features as allowed, banned, or to be discussed.
|
||||
|
||||
* [llvm Coding Standards](https://llvm.org/docs/CodingStandards.html) —
|
||||
Currently (2020) targeting C++14.
|
||||
|
||||
* [Using C++ in Mozilla code](https://firefox-source-docs.mozilla.org/code-quality/coding-style/using_cxx_in_firefox_code.html) —
|
||||
C++17 support is required for recent versions (2020).
|
||||
|
||||
### Error Handling
|
||||
|
||||
Do not use exceptions. Exceptions are disabled by the build configuration
|
||||
for some platforms.
|
||||
|
||||
Rationale: There is significant concern over the performance cost of
|
||||
exceptions and their usage model and implications for maintainable code.
|
||||
That's not just a matter of history that has been fixed; there remain
|
||||
questions and problems even today (2019). See, for example, [Zero cost
|
||||
deterministic
|
||||
exceptions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf).
|
||||
Because of this, HotSpot has always used a build configuration that disables
|
||||
exceptions where that is available. As a result, HotSpot code uses error
|
||||
handling mechanisms such as two-phase construction, factory functions,
|
||||
returning error codes, and immediate termination. Even if the cost of
|
||||
exceptions were not a concern, the existing body of code was not written with
|
||||
exception safety in mind. Making HotSpot exception safe would be a very large
|
||||
undertaking.
|
||||
|
||||
In addition to the usual alternatives to exceptions, HotSpot provides its
|
||||
own exception mechanism. This is based on a set of macros defined in
|
||||
utilities/exceptions.hpp.
|
||||
|
||||
### RTTI (Runtime Type Information)
|
||||
|
||||
Do not use [Runtime Type Information][RTTI] (RTTI).
|
||||
[RTTI][] is disabled by the build configuration for some
|
||||
platforms. Among other things, this means `dynamic_cast` cannot be used.
|
||||
|
||||
Rationale: Other than to implement exceptions (which HotSpot doesn't use),
|
||||
most potential uses of [RTTI][] are better done via virtual functions. Some of
|
||||
the remainder can be replaced by bespoke mechanisms. The cost of the
|
||||
additional runtime data structures needed to support [RTTI][] are deemed not
|
||||
worthwhile, given the alternatives.
|
||||
|
||||
### Memory Allocation
|
||||
|
||||
Do not use the standard global allocation and deallocation functions
|
||||
(operator new and related functions). Use of these functions by HotSpot
|
||||
code is disabled for some platforms.
|
||||
|
||||
Rationale: HotSpot often uses "resource" or "arena" allocation. Even
|
||||
where heap allocation is used, the standard global functions are
|
||||
avoided in favor of wrappers around malloc and free that support the
|
||||
VM's Native Memory Tracking (NMT) feature.
|
||||
|
||||
Native memory allocation failures are often treated as non-recoverable.
|
||||
The place where "out of memory" is (first) detected may be an innocent
|
||||
bystander, unrelated to the actual culprit.
|
||||
|
||||
### Class Inheritance
|
||||
|
||||
Use public single inheritance.
|
||||
|
||||
Prefer composition rather than non-public inheritance.
|
||||
|
||||
Restrict inheritance to the "is-a" case; use composition rather than
|
||||
non-is-a related inheritance.
|
||||
|
||||
Avoid multiple inheritance. Never use virtual inheritance.
|
||||
|
||||
### Namespaces
|
||||
|
||||
Avoid using namespaces. HotSpot code normally uses "all static"
|
||||
classes rather than namespaces for grouping. An "all static" class is
|
||||
not instantiable, has only static members, and is normally derived
|
||||
(possibly indirectly) from the helper class `AllStatic`.
|
||||
|
||||
Benefits of using such classes include:
|
||||
|
||||
* Provides access control for members, which is unavailable with
|
||||
namespaces.
|
||||
|
||||
* Avoids [Argument Dependent Lookup][ADL] (ADL).
|
||||
|
||||
* Closed for additional members. Namespaces allow names to be added in
|
||||
multiple contexts, making it harder to see the complete API.
|
||||
|
||||
Namespaces should be used only in cases where one of those "benefits"
|
||||
is actually a hindrance.
|
||||
|
||||
In particular, don't use anonymous namespaces. They seem like they should
|
||||
be useful, and indeed have some real benefits for naming and generated code
|
||||
size on some platforms. Unfortunately, debuggers don't seem to like them at
|
||||
all.
|
||||
|
||||
<https://groups.google.com/forum/#!topic/mozilla.dev.platform/KsaG3lEEaRM><br>
|
||||
Suggests Visual Studio debugger might not be able to refer to
|
||||
anonymous namespace symbols, so can't set breakpoints in them.
|
||||
Though the discussion seems to go back and forth on that.
|
||||
|
||||
<https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html><br>
|
||||
Search for "Anonymous namespaces"
|
||||
Suggests preferring "static" to anonymous namespaces where applicable,
|
||||
because of poor debugger support for anonymous namespaces.
|
||||
|
||||
<https://sourceware.org/bugzilla/show_bug.cgi?id=16874><br>
|
||||
Bug for similar gdb problems.
|
||||
|
||||
### C++ Standard Library
|
||||
|
||||
Avoid using the C++ Standard Library.
|
||||
|
||||
Historically, HotSpot has mostly avoided use of the Standard
|
||||
Library.
|
||||
|
||||
(It used to be impossible to use most of it in shared code,
|
||||
because the build configuration for Solaris with Solaris Studio made
|
||||
all but a couple of pieces inaccessible. Support for header-only
|
||||
parts was added in mid-2017. Support for Solaris was removed
|
||||
in 2020.)
|
||||
|
||||
Some reasons for this include
|
||||
|
||||
* Exceptions. Perhaps the largest core issue with adopting the use of
|
||||
Standard Library facilities is exceptions. HotSpot does not use
|
||||
exceptions and, for platforms which allow doing so, builds with them
|
||||
turned off. Many Standard Library facilities implicitly or explicitly
|
||||
use exceptions.
|
||||
|
||||
* `assert`. An issue that is quickly encountered is the `assert` macro name
|
||||
collision ([JDK-8007770](https://bugs.openjdk.java.net/browse/JDK-8007770)).
|
||||
Some mechanism for addressing this would be needed before much of the
|
||||
Standard Library could be used. (Not all Standard Library implementations
|
||||
use assert in header files, but some do.)
|
||||
|
||||
* Memory allocation. HotSpot requires explicit control over where
|
||||
allocations occur. The C++98/03 `std::allocator` class is too limited
|
||||
to support our usage. (Changes in more recent Standards may remove
|
||||
this limitation.)
|
||||
|
||||
* Implementation vagaries. Bugs, or simply different implementation choices,
|
||||
can lead to different behaviors among the various Standard Libraries we need
|
||||
to deal with.
|
||||
|
||||
* Inconsistent naming conventions. HotSpot and the C++ Standard use
|
||||
different naming conventions. The coexistence of those different conventions
|
||||
might appear jarring and reduce readability.
|
||||
|
||||
There are a few exceptions to this rule.
|
||||
|
||||
* `#include <new>` to use placement `new`, `std::nothrow`, and `std::nothrow_t`.
|
||||
* `#include <limits>` to use `std::numeric_limits`.
|
||||
* `#include <type_traits>`.
|
||||
* `#include <cstddef>` to use `std::nullptr_t`.
|
||||
|
||||
TODO: Rather than directly \#including (permitted) Standard Library
|
||||
headers, use a convention of \#including wrapper headers (in some
|
||||
location like hotspot/shared/stdcpp). This provides a single place
|
||||
for dealing with issues we might have for any given header, esp.
|
||||
platform-specific issues.
|
||||
|
||||
### Type Deduction
|
||||
|
||||
Use type deduction only if it makes the code clearer or safer. Do not
|
||||
use it merely to avoid the inconvenience of writing an explicit type,
|
||||
unless that type is itself difficult to write. An example of the
|
||||
latter is a function template return type that depends on template
|
||||
parameters in a non-trivial way.
|
||||
|
||||
There are several contexts where types are deduced.
|
||||
|
||||
* Function argument deduction. This is always permitted, and indeed
|
||||
encouraged. It is nearly always better to allow the type of a
|
||||
function template argument to be deduced rather than explicitly
|
||||
specified.
|
||||
|
||||
* `auto` variable declarations
|
||||
([n1984](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf))<br>
|
||||
For local variables, this can be used to make the code clearer by
|
||||
eliminating type information that is obvious or irrelevant. Excessive
|
||||
use can make code much harder to understand.
|
||||
|
||||
* Function return type deduction
|
||||
([n3638](https://isocpp.org/files/papers/N3638.html))<br>
|
||||
Only use if the function body has a very small number of `return`
|
||||
statements, and generally relatively little other code.
|
||||
|
||||
* Generic lambdas. Lambdas are not (yet) permitted.
|
||||
|
||||
* Lambda init captures. Lambdas are not (yet) permitted.
|
||||
|
||||
### Expression SFINAE
|
||||
|
||||
[Substitution Failure Is Not An Error][SFINAE] (SFINAE)
|
||||
is a template metaprogramming technique that makes use of
|
||||
template parameter substitution failures to make compile-time decisions.
|
||||
|
||||
C++11 relaxed the rules for what constitutes a hard-error when
|
||||
attempting to substitute template parameters with template arguments,
|
||||
making most deduction errors be substitution errors; see
|
||||
([n2634](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html)).
|
||||
This makes [SFINAE][] more powerful and easier to use. However, the
|
||||
implementation complexity for this change is significant, and this
|
||||
seems to be a place where obscure corner-case bugs in various
|
||||
compilers can be found. So while this feature can (and indeed should)
|
||||
be used (and would be difficult to avoid), caution should be used when
|
||||
pushing to extremes.
|
||||
|
||||
Here are a few closely related example bugs:<br>
|
||||
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468><br>
|
||||
<https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html>
|
||||
|
||||
### enum
|
||||
|
||||
Where appropriate, _scoped-enums_ should be used.
|
||||
([n2347](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf))
|
||||
|
||||
Use of _unscoped-enums_ is permitted, though ordinary constants may be
|
||||
preferable when the automatic initializer feature isn't used.
|
||||
|
||||
The underlying type (the _enum-base_) of an unscoped enum type should
|
||||
always be specified explicitly. When unspecified, the underlying type
|
||||
is dependent on the range of the enumerator values and the platform.
|
||||
|
||||
The underlying type of a _scoped-enum_ should also be specified
|
||||
explicitly if conversions may be applied to values of that type.
|
||||
|
||||
Due to bugs in certain (very old) compilers, there is widespread use
|
||||
of enums and avoidance of in-class initialization of static integral
|
||||
constant members. Compilers having such bugs are no longer supported.
|
||||
Except where an enum is semantically appropriate, new code should use
|
||||
integral constants.
|
||||
|
||||
### thread_local
|
||||
|
||||
Do not use `thread_local`
|
||||
([n2659](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm));
|
||||
instead, use the HotSpot macro `THREAD_LOCAL`. The initializer must
|
||||
be a constant expression.
|
||||
|
||||
As was discussed in the review for
|
||||
[JDK-8230877](https://mail.openjdk.java.net/pipermail/hotspot-dev/2019-September/039487.html),
|
||||
`thread_local` allows dynamic initialization and destruction
|
||||
semantics. However, that support requires a run-time penalty for
|
||||
references to non-function-local `thread_local` variables defined in a
|
||||
different translation unit, even if they don't need dynamic
|
||||
initialization. Dynamic initialization and destruction of
|
||||
namespace-scoped thread local variables also has the same ordering
|
||||
problems as for ordinary namespace-scoped variables.
|
||||
|
||||
### nullptr
|
||||
|
||||
Prefer `nullptr`
|
||||
([n2431](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf))
|
||||
to `NULL`. Don't use (constexpr or literal) 0 for pointers.
|
||||
|
||||
For historical reasons there are widespread uses of both `NULL` and of
|
||||
integer 0 as a pointer value.
|
||||
|
||||
### <atomic>
|
||||
|
||||
Do not use facilities provided by the `<atomic>` header
|
||||
([n2427](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html)),
|
||||
([n2752](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm));
|
||||
instead, use the HotSpot `Atomic` class and related facilities.
|
||||
|
||||
Atomic operations in HotSpot code must have semantics which are
|
||||
consistent with those provided by the JDK's compilers for Java. There
|
||||
are platform-specific implementation choices that a C++ compiler might
|
||||
make or change that are outside the scope of the C++ Standard, and
|
||||
might differ from what the Java compilers implement.
|
||||
|
||||
In addition, HotSpot `Atomic` has a concept of "conservative" memory
|
||||
ordering, which may differ from (may be stronger than) sequentially
|
||||
consistent. There are algorithms in HotSpot that are believed to rely
|
||||
on that ordering.
|
||||
|
||||
### Additional Permitted Features
|
||||
|
||||
* `constexpr`
|
||||
([n2235](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf))
|
||||
([n3652](https://isocpp.org/files/papers/N3652.html))
|
||||
|
||||
* Sized deallocation
|
||||
([n3778](https://isocpp.org/files/papers/n3778.html))
|
||||
|
||||
* Variadic templates
|
||||
([n2242](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf))
|
||||
([n2555](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf))
|
||||
|
||||
* Static assertions
|
||||
([n1720](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html))
|
||||
|
||||
* `decltype`
|
||||
([n2343](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf))
|
||||
([n3276](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf))
|
||||
|
||||
* Right angle brackets
|
||||
([n1757](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html))
|
||||
|
||||
* Default template arguments for function templates
|
||||
([CWG D226](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226))
|
||||
|
||||
* Template aliases
|
||||
([n2258](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf))
|
||||
|
||||
* Delegating constructors
|
||||
([n1986](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf))
|
||||
|
||||
* Explicit conversion operators
|
||||
([n2437](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf))
|
||||
|
||||
* Standard Layout Types
|
||||
([n2342](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm))
|
||||
|
||||
* Defaulted and deleted functions
|
||||
([n2346](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm))
|
||||
|
||||
* Dynamic initialization and destruction with concurrency
|
||||
([n2660](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm))
|
||||
|
||||
* `final` virtual specifiers for classes and virtual functions
|
||||
([n2928](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm)),
|
||||
([n3206](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm)),
|
||||
([n3272](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm))
|
||||
|
||||
* Local and unnamed types as template parameters
|
||||
([n2657](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm))
|
||||
|
||||
### Excluded Features
|
||||
|
||||
* New string and character literals
|
||||
* New character types
|
||||
([n2249](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html))
|
||||
* Unicode string literals
|
||||
([n2442](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm))
|
||||
* Raw string literals
|
||||
([n2442](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm))
|
||||
* Universal character name literals
|
||||
([n2170](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html))
|
||||
|
||||
HotSpot doesn't need any of the new character and string literal
|
||||
types.
|
||||
|
||||
* User-defined literals
|
||||
([n2765](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf)) —
|
||||
User-defined literals should not be added casually, but only
|
||||
through a proposal to add a specific UDL.
|
||||
|
||||
* Inline namespaces
|
||||
([n2535](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm)) —
|
||||
HotSpot makes very limited use of namespaces.
|
||||
|
||||
* `using namespace` directives. In particular, don't use `using
|
||||
namespace std;` to avoid needing to qualify Standard Library names.
|
||||
|
||||
* Propagating exceptions
|
||||
([n2179](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html)) —
|
||||
HotSpot does not permit the use of exceptions, so this feature isn't useful.
|
||||
|
||||
* Avoid namespace-scoped variables with non-constexpr initialization.
|
||||
In particular, avoid variables with types requiring non-trivial
|
||||
initialization or destruction. Initialization order problems can be
|
||||
difficult to deal with and lead to surprises, as can destruction
|
||||
ordering. HotSpot doesn't generally try to cleanup on exit, and
|
||||
running destructors at exit can also lead to problems.
|
||||
|
||||
* `[[deprecated]]` attribute
|
||||
([n3760](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html)) —
|
||||
Not relevant in HotSpot code.
|
||||
|
||||
* Avoid most operator overloading, preferring named functions. When
|
||||
operator overloading is used, ensure the semantics conform to the
|
||||
normal expected behavior of the operation.
|
||||
|
||||
* Avoid most implicit conversion constructors and (implicit or explicit)
|
||||
conversion operators. (Note that conversion to `bool` isn't needed
|
||||
in HotSpot code because of the "no implicit boolean" guideline.)
|
||||
|
||||
* Avoid covariant return types.
|
||||
|
||||
* Avoid `goto` statements.
|
||||
|
||||
### Undecided Features
|
||||
|
||||
This list is incomplete; it serves to explicitly call out some
|
||||
features that have not yet been discussed.
|
||||
|
||||
* `overrides` virtual specifiers for virtual functions
|
||||
([n3272](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm))
|
||||
|
||||
* Trailing return type syntax for functions
|
||||
([n2541](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm))
|
||||
|
||||
* Variable templates
|
||||
([n3651](https://isocpp.org/files/papers/N3651.pdf))
|
||||
|
||||
* Member initializers and aggregates
|
||||
([n3653](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html))
|
||||
|
||||
* `[[noreturn]]` attribute
|
||||
([n2761](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf))
|
||||
|
||||
* Rvalue references and move semantics
|
||||
|
||||
* Lambdas
|
||||
|
||||
|
||||
[ADL]: https://en.cppreference.com/w/cpp/language/adl
|
||||
"Argument Dependent Lookup"
|
||||
|
||||
[ODR]: https://en.cppreference.com/w/cpp/language/definition
|
||||
"One Definition Rule"
|
||||
|
||||
[RAII]: https://en.cppreference.com/w/cpp/language/raii
|
||||
"Resource Acquisition Is Initialization"
|
||||
|
||||
[RTTI]: https://en.wikipedia.org/wiki/Run-time_type_information
|
||||
"Runtime Type Information"
|
||||
|
||||
[SFINAE]: https://en.cppreference.com/w/cpp/language/sfinae
|
||||
"Substitution Failure Is Not An Error"
|
||||
@@ -1,223 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Native/Unit Test Development Guidelines</title>
|
||||
<style type="text/css">
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">Native/Unit Test Development Guidelines</h1>
|
||||
</header>
|
||||
<nav id="TOC">
|
||||
<ul>
|
||||
<li><a href="#good-test-properties">Good test properties</a><ul>
|
||||
<li><a href="#lightness">Lightness</a></li>
|
||||
<li><a href="#isolation">Isolation</a></li>
|
||||
<li><a href="#atomicity-and-self-containment">Atomicity and self-containment</a></li>
|
||||
<li><a href="#repeatability">Repeatability</a></li>
|
||||
<li><a href="#informativeness">Informativeness</a></li>
|
||||
<li><a href="#testing-instead-of-visiting">Testing instead of visiting</a></li>
|
||||
<li><a href="#nearness">Nearness</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#asserts">Asserts</a><ul>
|
||||
<li><a href="#several-checks">Several checks</a></li>
|
||||
<li><a href="#first-parameter-is-expected-value">First parameter is expected value</a></li>
|
||||
<li><a href="#floating-point-comparison">Floating-point comparison</a></li>
|
||||
<li><a href="#c-string-comparison">C string comparison</a></li>
|
||||
<li><a href="#error-messages">Error messages</a></li>
|
||||
<li><a href="#uncluttered-output">Uncluttered output</a></li>
|
||||
<li><a href="#failures-propagation">Failures propagation</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#naming-and-grouping">Naming and Grouping</a><ul>
|
||||
<li><a href="#test-group-names">Test group names</a></li>
|
||||
<li><a href="#filename">Filename</a></li>
|
||||
<li><a href="#file-location">File location</a></li>
|
||||
<li><a href="#test-names">Test names</a></li>
|
||||
<li><a href="#fixture-classes">Fixture classes</a></li>
|
||||
<li><a href="#friend-classes">Friend classes</a></li>
|
||||
<li><a href="#oscpu-specific-tests">OS/CPU specific tests</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#miscellaneous">Miscellaneous</a><ul>
|
||||
<li><a href="#hotspot-style">Hotspot style</a></li>
|
||||
<li><a href="#codetest-metrics">Code/test metrics</a></li>
|
||||
<li><a href="#access-to-non-public-members">Access to non-public members</a></li>
|
||||
<li><a href="#death-tests">Death tests</a></li>
|
||||
<li><a href="#external-flags">External flags</a></li>
|
||||
<li><a href="#test-specific-flags">Test-specific flags</a></li>
|
||||
<li><a href="#flag-restoring">Flag restoring</a></li>
|
||||
<li><a href="#googletest-documentation">GoogleTest documentation</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#todo">TODO</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<p>The purpose of these guidelines is to establish a shared vision on what kind of native tests and how we want to develop them for Hotspot using GoogleTest. Hence these guidelines include style items as well as test approach items.</p>
|
||||
<p>First section of this document describes properties of good tests which are common for almost all types of test regardless of language, framework, etc. Further sections provide recommendations to achieve those properties and other HotSpot and/or GoogleTest specific guidelines.</p>
|
||||
<h2 id="good-test-properties">Good test properties</h2>
|
||||
<h3 id="lightness">Lightness</h3>
|
||||
<p>Use the most lightweight type of tests.</p>
|
||||
<p>In Hotspot, there are 3 different types of tests regarding their dependency on a JVM, each next level is slower than previous</p>
|
||||
<ul>
|
||||
<li><p><code>TEST</code> : a test does not depend on a JVM</p></li>
|
||||
<li><p><code>TEST_VM</code> : a test does depend on an initialized JVM, but are supposed not to break a JVM, i.e. leave it in a workable state.</p></li>
|
||||
<li><p><code>TEST_OTHER_VM</code> : a test depends on a JVM and requires a freshly initialized JVM or leaves a JVM in non-workable state</p></li>
|
||||
</ul>
|
||||
<h3 id="isolation">Isolation</h3>
|
||||
<p>Tests have to be isolated: not to have visible side-effects, influences on other tests results.</p>
|
||||
<p>Results of one test should not depend on test execution order, other tests, otherwise it is becoming almost impossible to find out why a test failed. Due to hotspot-specific, it is not so easy to get a full isolation, e.g. we share an initialized JVM between all <code>TEST_VM</code> tests, so if your test changes JVM's state too drastically and does not change it back, you had better consider <code>TEST_OTHER_VM</code>.</p>
|
||||
<h3 id="atomicity-and-self-containment">Atomicity and self-containment</h3>
|
||||
<p>Tests should be <em>atomic</em> and <em>self-contained</em> at the same time.</p>
|
||||
<p>One test should check a particular part of a class, subsystem, functionality, etc. Then it is quite easy to determine what parts of a product are broken basing on test failures. On the other hand, a test should test that part more-or-less entirely, because when one sees a test <code>FooTest::bar</code>, they assume all aspects of bar from <code>Foo</code> are tested.</p>
|
||||
<p>However, it is impossible to cover all aspects even of a method, not to mention a subsystem. In such cases, it is recommended to have several tests, one for each aspect of a thing under test. For example one test to tests how <code>Foo::bar</code> works if an argument is <code>null</code>, another test to test how it works if an argument is acceptable but <code>Foo</code> is not in the right state to accept it and so on. This helps not only to make tests atomic, self-contained but also makes test name self-descriptive (discussed in more details in <a href="#test-names">Test names</a>).</p>
|
||||
<h3 id="repeatability">Repeatability</h3>
|
||||
<p>Tests have to be repeatable.</p>
|
||||
<p>Reproducibility is very crucial for a test. No one likes sporadic test failures, they are hard to investigate, fix and verify a fix.</p>
|
||||
<p>In some cases, it is quite hard to write a 100% repeatable test, since besides a test there can be other moving parts, e.g. in case of <code>TEST_VM</code> there are several concurrently running threads. Despite this, we should try to make a test as reproducible as possible.</p>
|
||||
<h3 id="informativeness">Informativeness</h3>
|
||||
<p>In case of a failure, a test should be as <em>informative</em> as possible.</p>
|
||||
<p>Having more information about a test failure than just compared values can be very useful for failure troubleshooting, it can reduce or even completely eliminate debugging hours. This is even more important in case of not 100% reproducible failures.</p>
|
||||
<p>Achieving this property, one can easily make a test too verbose, so it will be really hard to find useful information in the ocean of useless information. Hence they should not only think about how to provide <a href="#error-messages">good information</a>, but also <a href="#uncluttered-output">when to do it</a>.</p>
|
||||
<h3 id="testing-instead-of-visiting">Testing instead of visiting</h3>
|
||||
<p>Tests should <em>test</em>.</p>
|
||||
<p>It is not enough just to "visit" some code, a test should check that code does that it has to do, compare return values with expected values, check that desired side effects are done, and undesired are not, and so on. In other words, a test should contain at least one GoogleTest assertion and do not rely on JVM asserts.</p>
|
||||
<p>Generally speaking to write a good test, one should create a model of the system under tests, a model of possible bugs (or bugs which one wants to find) and design tests using those models.</p>
|
||||
<h3 id="nearness">Nearness</h3>
|
||||
<p>Prefer having checks inside test code.</p>
|
||||
<p>Not only does having test logic outside, e.g. verification method, depending on asserts in product code contradict with several items above but also decreases test’s readability and stability. It is much easier to understand that a test is testing when all testing logic is located inside a test or nearby in shared test libraries. As a rule of thumb, the closer a check to a test, the better.</p>
|
||||
<h2 id="asserts">Asserts</h2>
|
||||
<h3 id="several-checks">Several checks</h3>
|
||||
<p>Prefer <code>EXPECT</code> over <code>ASSERT</code> if possible.</p>
|
||||
<p>This is related to the <a href="#informativeness">informativeness</a> property of tests, information for other checks can help to better localize a defect’s root-cause. One should use <code>ASSERT</code> if it is impossible to continue test execution or if it does not make much sense. Later in the text, <code>EXPECT</code> forms will be used to refer to both <code>ASSERT/EXPECT</code>.</p>
|
||||
<p>When it is possible to make several different checks, but impossible to continue test execution if at least one check fails, you can use <code>::testing::Test::HasNonfatalFailure()</code> function. The recommended way to express that is <code>ASSERT_FALSE(::testing::Test::HasNonfatalFailure())</code>. Besides making it clear why a test is aborted, it also allows you to provide more information about a failure.</p>
|
||||
<h3 id="first-parameter-is-expected-value">First parameter is expected value</h3>
|
||||
<p>In all equality assertions, expected values should be passed as the first parameter.</p>
|
||||
<p>This convention is adopted by GoogleTest, and there is a slight difference in how GoogleTest treats parameters, the most important one is <code>null</code> detection. Due to different reasons, <code>null</code> detection is enabled only for the first parameter, that is to said <code>EXPECT_EQ(NULL, object)</code> checks that object is <code>null</code>, while <code>EXPECT_EQ(object, NULL)</code> checks that object equals to <code>NULL</code>, GoogleTest is very strict regarding types of compared values so the latter will generates a compile-time error.</p>
|
||||
<h3 id="floating-point-comparison">Floating-point comparison</h3>
|
||||
<p>Use floating-point special macros to compare <code>float/double</code> values.</p>
|
||||
<p>Because of floating-point number representations and round-off errors, regular equality comparison will not return true in most cases. There are special <code>EXPECT_FLOAT_EQ/EXPECT_DOUBLE_EQ</code> assertions which check that the distance between compared values is not more than 4 ULPs, there is also <code>EXPECT_NEAR(v1, v2, eps)</code> which checks that the absolute value of the difference between <code>v1</code> and <code>v2</code> is not greater than <code>eps</code>.</p>
|
||||
<h3 id="c-string-comparison">C string comparison</h3>
|
||||
<p>Use string special macros for C strings comparisons.</p>
|
||||
<p><code>EXPECT_EQ</code> just compares pointers’ values, which is hardly what one wants comparing C strings. GoogleTest provides <code>EXPECT_STREQ</code> and <code>EXPECT_STRNE</code> macros to compare C string contents. There are also case-insensitive versions <code>EXPECT_STRCASEEQ</code>, <code>EXPECT_STRCASENE</code>.</p>
|
||||
<h3 id="error-messages">Error messages</h3>
|
||||
<p>Provide informative, but not too verbose error messages.</p>
|
||||
<p>All GoogleTest asserts print compared expressions and their values, so there is no need to have them in error messages. Asserts print only compared values, they do not print any of interim variables, e.g. <code>ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18)</code> prints only one value. If you use some complex predicates, please consider <code>EXPECT_PRED*</code> or <code>EXPECT_FORMAT_PRED</code> assertions family, they check that a predicate returns true/success and print out all parameters values.</p>
|
||||
<p>However in some cases, default information is not enough, a commonly used example is an assert inside a loop, GoogleTest will not print iteration values (unless it is an assert's parameter). Other demonstrative examples are printing error code and a corresponding error message; printing internal states which might have an impact on results. One should add this information to assert message using <code><<</code> operator.</p>
|
||||
<h3 id="uncluttered-output">Uncluttered output</h3>
|
||||
<p>Print information only if it is needed.</p>
|
||||
<p>Too verbose tests which print all information even if they pass are very bad practice. They just pollute output, so it becomes harder to find useful information. In order not print information till it is really needed, one should consider saving it to a temporary buffer and pass to an assert. <a href="https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp" class="uri">https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp</a> has a good example how to do that.</p>
|
||||
<h3 id="failures-propagation">Failures propagation</h3>
|
||||
<p>Wrap a subroutine call into <code>EXPECT_NO_FATAL_FAILURE</code> macro to propagate failures.</p>
|
||||
<p><code>ASSERT</code> and <code>FAIL</code> abort only the current function, so if you have them in a subroutine, a test will not be aborted after the subroutine even if <code>ASSERT</code> or <code>FAIL</code> fails. You should call such subroutines in <code>ASSERT_NO_FATAL_FAILURE</code> macro to propagate fatal failures and abort a test. <code>(EXPECT|ASSERT)_NO_FATAL_FAILURE</code> can also be used to provide more information.</p>
|
||||
<p>Due to obvious reasons, there are no <code>(EXPECT|ASSERT)_NO_NONFATAL_FAILURE</code> macros. However, if you need to check if a subroutine generated a nonfatal failure (failed an <code>EXPECT</code>), you can use <code>::testing::Test::HasNonfatalFailure</code> function, or <code>::testing::Test::HasFailure</code> function to check if a subroutine generated any failures, see <a href="#several-checks">Several checks</a>.</p>
|
||||
<h2 id="naming-and-grouping">Naming and Grouping</h2>
|
||||
<h3 id="test-group-names">Test group names</h3>
|
||||
<p>Test group names should be in CamelCase, start and end with a letter. A test group should be named after tested class, functionality, subsystem, etc.</p>
|
||||
<p>This naming scheme helps to find tests, filter them and simplifies test failure analysis. For example, class <code>Foo</code> - test group <code>Foo</code>, compiler logging subsystem - test group <code>CompilerLogging</code>, G1 GC — test group <code>G1GC</code>, and so forth.</p>
|
||||
<h3 id="filename">Filename</h3>
|
||||
<p>A test file must have <code>test_</code> prefix and <code>.cpp</code> suffix.</p>
|
||||
<p>Both are actually requirements from the current build system to recognize your tests.</p>
|
||||
<h3 id="file-location">File location</h3>
|
||||
<p>Test file location should reflect a location of the tested part of the product.</p>
|
||||
<ul>
|
||||
<li><p>All unit tests for a class from <code>foo/bar/baz.cpp</code> should be placed <code>foo/bar/test_baz.cpp</code> in <code>hotspot/test/native/</code> directory. Having all tests for a class in one file is a common practice for unit tests, it helps to see all existing tests at once, share functions and/or resources without losing encapsulation.</p></li>
|
||||
<li><p>For tests which test more than one class, directory hierarchy should be the same as product hierarchy, and file name should reflect the name of the tested subsystem/functionality. For example, if a sub-system under tests belongs to <code>gc/g1</code>, tests should be placed in <code>gc/g1</code> directory.</p></li>
|
||||
</ul>
|
||||
<p>Please note that framework prepends directory name to a test group name. For example, if <code>TEST(foo, check_this)</code> and <code>TEST(bar, check_that)</code> are defined in <code>hotspot/test/native/gc/shared/test_foo.cpp</code> file, they will be reported as <code>gc/shared/foo::check_this</code> and <code>gc/shared/bar::check_that</code>.</p>
|
||||
<h3 id="test-names">Test names</h3>
|
||||
<p>Test names should be in small_snake_case, start and end with a letter. A test name should reflect that a test checks.</p>
|
||||
<p>Such naming makes tests self-descriptive and helps a lot during the whole test life cycle. It is easy to do test planning, test inventory, to see what things are not tested, to review tests, to analyze test failures, to evolve a test, etc. For example <code>foo_return_0_if_name_is_null</code> is better than <code>foo_sanity</code> or <code>foo_basic</code> or just <code>foo</code>, <code>humongous_objects_can_not_be_moved_by_young_gc</code> is better than <code>ho_young_gc</code>.</p>
|
||||
<p>Actually using underscore is against GoogleTest project convention, because it can lead to illegal identifiers, however, this is too strict. Restricting usage of underscore for test names only and prohibiting test name starts or ends with an underscore are enough to be safe.</p>
|
||||
<h3 id="fixture-classes">Fixture classes</h3>
|
||||
<p>Fixture classes should be named after tested classes, subsystems, etc (follow <a href="#test-group-names">Test group names rule</a>) and have <code>Test</code> suffix to prevent class name conflicts.</p>
|
||||
<h3 id="friend-classes">Friend classes</h3>
|
||||
<p>All test purpose friends should have either <code>Test</code> or <code>Testable</code> suffix.</p>
|
||||
<p>It greatly simplifies understanding of friendship’s purpose and allows statically check that private members are not exposed unexpectedly. Having <code>FooTest</code> as a friend of <code>Foo</code> without any comments will be understood as a necessary evil to get testability.</p>
|
||||
<h3 id="oscpu-specific-tests">OS/CPU specific tests</h3>
|
||||
<p>Guard OS/CPU specific tests by <code>#ifdef</code> and have OS/CPU name in filename.</p>
|
||||
<p>For the time being, we do not support separate directories for OS, CPU, OS-CPU specific tests, in case we will have lots of such tests, we will change directory layout and build system to support that in the same way it is done in hotspot.</p>
|
||||
<h2 id="miscellaneous">Miscellaneous</h2>
|
||||
<h3 id="hotspot-style">Hotspot style</h3>
|
||||
<p>Abide the norms and rules accepted in Hotspot style guide.</p>
|
||||
<p>Tests are a part of Hotspot, so everything (if applicable) we use for Hotspot, should be used for tests as well. Those guidelines cover test-specific things.</p>
|
||||
<h3 id="codetest-metrics">Code/test metrics</h3>
|
||||
<p>Coverage information and other code/test metrics are quite useful to decide what tests should be written, what tests should be improved and what can be removed.</p>
|
||||
<p>For unit tests, widely used and well-known coverage metric is branch coverage, which provides good quality of tests with relatively easy test development process. For other levels of testing, branch coverage is not as good, and one should consider others metrics, e.g. transaction flow coverage, data flow coverage.</p>
|
||||
<h3 id="access-to-non-public-members">Access to non-public members</h3>
|
||||
<p>Use explicit friend class to get access to non-public members.</p>
|
||||
<p>We do not use GoogleTest macro to declare friendship relation, because, from our point of view, it is less clear than an explicit declaration.</p>
|
||||
<p>Declaring a test fixture class as a friend class of a tested test is the easiest and the clearest way to get access. However, it has some disadvantages, here is some of them:</p>
|
||||
<ul>
|
||||
<li>Each test has to be declared as a friend</li>
|
||||
<li>Subclasses do not inheritance friendship relation</li>
|
||||
</ul>
|
||||
<p>In other words, it is harder to share code between tests. Hence if you want to share code or expect it to be useful in other tests, you should consider making members in a tested class protected and introduce a shared test-only class which expose those members via public functions, or even making members publicly accessible right away in a product class. If it is not an option to change members visibility, one can create a friend class which exposes members.</p>
|
||||
<h3 id="death-tests">Death tests</h3>
|
||||
<p>You can not use death tests inside <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code>.</p>
|
||||
<p>We tried to make Hotspot-GoogleTest integration as transparent as possible, however, due to the current implementation of <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> tests, you cannot use death test functionality in them. These tests are implemented as GoogleTest death tests, and GoogleTest does not allow to have a death test inside another death test.</p>
|
||||
<h3 id="external-flags">External flags</h3>
|
||||
<p>Passing external flags to a tested JVM is not supported.</p>
|
||||
<p>The rationality of such design decision is to simplify both tests and a test framework and to avoid failures related to incompatible flags combination till there is a good solution for that. However there are cases when one wants to test a JVM with specific flags combination, <code>_JAVA_OPTIONS</code> environment variable can be used to do that. Flags from <code>_JAVA_OPTIONS</code> will be used in <code>TEST_VM</code>, <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> tests.</p>
|
||||
<h3 id="test-specific-flags">Test-specific flags</h3>
|
||||
<p>Passing flags to a tested JVM in <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> should be possible, but is not implemented yet.</p>
|
||||
<p>Facility to pass test-specific flags is needed for system, regression or other types of tests which require a fully initialized JVM in some particular configuration, e.g. with Serial GC selected. There is no support for such tests now, however, there is a plan to add that in upcoming releases.</p>
|
||||
<p>For now, if a test depends on flags values, it should have <code>if (!<flag>) { return }</code> guards in the very beginning and <code>@requires</code> comment similar to jtreg <code>@requires</code> directive right before test macros. <a href="https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp" class="uri">https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp</a> ha an example of this temporary workaround. It is important to follow that pattern as it allows us to easily find all such tests and update them as soon as there is an implementation of flag passing facility.</p>
|
||||
<p>In long-term, we expect jtreg to support GoogleTest tests as first class citizens, that is to say, jtreg will parse <span class="citation" data-cites="requires">@requires</span> comments and filter out inapplicable tests.</p>
|
||||
<h3 id="flag-restoring">Flag restoring</h3>
|
||||
<p>Restore changed flags.</p>
|
||||
<p>It is quite common for tests to configure JVM in a certain way changing flags’ values. GoogleTest provides two ways to set up environment before a test and restore it afterward: using either constructor and destructor or <code>SetUp</code> and <code>TearDown</code> functions. Both ways require to use a test fixture class, which sometimes is too wordy. The simpler facilities like <code>FLAG_GUARD</code> macro or <code>*FlagSetting</code> classes could be used in such cases to restore/set values.</p>
|
||||
<p>Caveats:</p>
|
||||
<ul>
|
||||
<li><p>Changing a flag’s value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state.</p></li>
|
||||
<li><p><code>FLAG_SET_*</code> macros can change more than one flag (in order to maintain invariants) so it is hard to predict what flags will be changed and it makes restoring all changed flags a nontrivial task. Thus in case one uses <code>FLAG_SET_*</code> macros, they should use <code>TEST_OTHER_VM</code> test type.</p></li>
|
||||
</ul>
|
||||
<h3 id="googletest-documentation">GoogleTest documentation</h3>
|
||||
<p>In case you have any questions regarding GoogleTest itself, its asserts, test declaration macros, other macros, etc, please consult its documentation.</p>
|
||||
<h2 id="todo">TODO</h2>
|
||||
<p>Although this document provides guidelines on the most important parts of test development using GTest, it still misses a few items:</p>
|
||||
<ul>
|
||||
<li><p>Examples, esp for <a href="#access-to-non-public-members">access to non-public members</a></p></li>
|
||||
<li>test types: purpose, drawbacks, limitation
|
||||
<ul>
|
||||
<li><code>TEST_VM</code></li>
|
||||
<li><code>TEST_VM_F</code></li>
|
||||
<li><code>TEST_OTHER_VM</code></li>
|
||||
<li><code>TEST_VM_ASSERT</code></li>
|
||||
<li><code>TEST_VM_ASSERT_MSG</code></li>
|
||||
</ul></li>
|
||||
<li>Miscellaneous
|
||||
<ul>
|
||||
<li>Test libraries
|
||||
<ul>
|
||||
<li>where to place</li>
|
||||
<li>how to write</li>
|
||||
<li>how to use</li>
|
||||
</ul></li>
|
||||
<li>test your tests
|
||||
<ul>
|
||||
<li>how to run tests in random order</li>
|
||||
<li>how to run only specific tests</li>
|
||||
<li>how to run each test separately</li>
|
||||
<li>check that a test can find bugs it is supposed to by introducing them</li>
|
||||
</ul></li>
|
||||
<li>mocks/stubs/dependency injection</li>
|
||||
<li>setUp/tearDown
|
||||
<ul>
|
||||
<li>vs c-tor/d-tor</li>
|
||||
<li>empty test to test them</li>
|
||||
</ul></li>
|
||||
<li>internal (declared in .cpp) struct/classes</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,451 +0,0 @@
|
||||
% Native/Unit Test Development Guidelines
|
||||
|
||||
The purpose of these guidelines is to establish a shared vision on
|
||||
what kind of native tests and how we want to develop them for Hotspot
|
||||
using GoogleTest. Hence these guidelines include style items as well
|
||||
as test approach items.
|
||||
|
||||
First section of this document describes properties of good tests
|
||||
which are common for almost all types of test regardless of language,
|
||||
framework, etc. Further sections provide recommendations to achieve
|
||||
those properties and other HotSpot and/or GoogleTest specific
|
||||
guidelines.
|
||||
|
||||
## Good test properties
|
||||
|
||||
### Lightness
|
||||
|
||||
Use the most lightweight type of tests.
|
||||
|
||||
In Hotspot, there are 3 different types of tests regarding their
|
||||
dependency on a JVM, each next level is slower than previous
|
||||
|
||||
* `TEST` : a test does not depend on a JVM
|
||||
|
||||
* `TEST_VM` : a test does depend on an initialized JVM, but are
|
||||
supposed not to break a JVM, i.e. leave it in a workable state.
|
||||
|
||||
* `TEST_OTHER_VM` : a test depends on a JVM and requires a freshly
|
||||
initialized JVM or leaves a JVM in non-workable state
|
||||
|
||||
### Isolation
|
||||
|
||||
Tests have to be isolated: not to have visible side-effects,
|
||||
influences on other tests results.
|
||||
|
||||
Results of one test should not depend on test execution order, other
|
||||
tests, otherwise it is becoming almost impossible to find out why a
|
||||
test failed. Due to hotspot-specific, it is not so easy to get a full
|
||||
isolation, e.g. we share an initialized JVM between all `TEST_VM` tests,
|
||||
so if your test changes JVM's state too drastically and does not
|
||||
change it back, you had better consider `TEST_OTHER_VM`.
|
||||
|
||||
### Atomicity and self-containment
|
||||
|
||||
Tests should be *atomic* and *self-contained* at the same time.
|
||||
|
||||
One test should check a particular part of a class, subsystem,
|
||||
functionality, etc. Then it is quite easy to determine what parts of a
|
||||
product are broken basing on test failures. On the other hand, a test
|
||||
should test that part more-or-less entirely, because when one sees a
|
||||
test `FooTest::bar`, they assume all aspects of bar from `Foo` are tested.
|
||||
|
||||
However, it is impossible to cover all aspects even of a method, not
|
||||
to mention a subsystem. In such cases, it is recommended to have
|
||||
several tests, one for each aspect of a thing under test. For example
|
||||
one test to tests how `Foo::bar` works if an argument is `null`, another
|
||||
test to test how it works if an argument is acceptable but `Foo` is not
|
||||
in the right state to accept it and so on. This helps not only to make
|
||||
tests atomic, self-contained but also makes test name self-descriptive
|
||||
(discussed in more details in [Test names](#test-names)).
|
||||
|
||||
### Repeatability
|
||||
|
||||
Tests have to be repeatable.
|
||||
|
||||
Reproducibility is very crucial for a test. No one likes sporadic test
|
||||
failures, they are hard to investigate, fix and verify a fix.
|
||||
|
||||
In some cases, it is quite hard to write a 100% repeatable test, since
|
||||
besides a test there can be other moving parts, e.g. in case of
|
||||
`TEST_VM` there are several concurrently running threads. Despite this,
|
||||
we should try to make a test as reproducible as possible.
|
||||
|
||||
### Informativeness
|
||||
|
||||
In case of a failure, a test should be as *informative* as possible.
|
||||
|
||||
Having more information about a test failure than just compared values
|
||||
can be very useful for failure troubleshooting, it can reduce or even
|
||||
completely eliminate debugging hours. This is even more important in
|
||||
case of not 100% reproducible failures.
|
||||
|
||||
Achieving this property, one can easily make a test too verbose, so it
|
||||
will be really hard to find useful information in the ocean of useless
|
||||
information. Hence they should not only think about how to provide
|
||||
[good information](#error-messages), but also
|
||||
[when to do it](#uncluttered-output).
|
||||
|
||||
### Testing instead of visiting
|
||||
|
||||
Tests should *test*.
|
||||
|
||||
It is not enough just to "visit" some code, a test should check that
|
||||
code does that it has to do, compare return values with expected
|
||||
values, check that desired side effects are done, and undesired are
|
||||
not, and so on. In other words, a test should contain at least one
|
||||
GoogleTest assertion and do not rely on JVM asserts.
|
||||
|
||||
Generally speaking to write a good test, one should create a model of
|
||||
the system under tests, a model of possible bugs (or bugs which one
|
||||
wants to find) and design tests using those models.
|
||||
|
||||
### Nearness
|
||||
|
||||
Prefer having checks inside test code.
|
||||
|
||||
Not only does having test logic outside, e.g. verification method,
|
||||
depending on asserts in product code contradict with several items
|
||||
above but also decreases test’s readability and stability. It is much
|
||||
easier to understand that a test is testing when all testing logic is
|
||||
located inside a test or nearby in shared test libraries. As a rule of
|
||||
thumb, the closer a check to a test, the better.
|
||||
|
||||
## Asserts
|
||||
|
||||
### Several checks
|
||||
|
||||
Prefer `EXPECT` over `ASSERT` if possible.
|
||||
|
||||
This is related to the [informativeness](#informativeness) property of
|
||||
tests, information for other checks can help to better localize a
|
||||
defect’s root-cause. One should use `ASSERT` if it is impossible to
|
||||
continue test execution or if it does not make much sense. Later in
|
||||
the text, `EXPECT` forms will be used to refer to both
|
||||
`ASSERT/EXPECT`.
|
||||
|
||||
When it is possible to make several different checks, but impossible
|
||||
to continue test execution if at least one check fails, you can
|
||||
use `::testing::Test::HasNonfatalFailure()` function. The recommended
|
||||
way to express that is
|
||||
`ASSERT_FALSE(::testing::Test::HasNonfatalFailure())`. Besides making it
|
||||
clear why a test is aborted, it also allows you to provide more
|
||||
information about a failure.
|
||||
|
||||
### First parameter is expected value
|
||||
|
||||
In all equality assertions, expected values should be passed as the
|
||||
first parameter.
|
||||
|
||||
This convention is adopted by GoogleTest, and there is a slight
|
||||
difference in how GoogleTest treats parameters, the most important one
|
||||
is `null` detection. Due to different reasons, `null` detection is enabled
|
||||
only for the first parameter, that is to said `EXPECT_EQ(NULL, object)`
|
||||
checks that object is `null`, while `EXPECT_EQ(object, NULL)` checks that
|
||||
object equals to `NULL`, GoogleTest is very strict regarding types of
|
||||
compared values so the latter will generates a compile-time error.
|
||||
|
||||
### Floating-point comparison
|
||||
|
||||
Use floating-point special macros to compare `float/double` values.
|
||||
|
||||
Because of floating-point number representations and round-off errors,
|
||||
regular equality comparison will not return true in most cases. There
|
||||
are special `EXPECT_FLOAT_EQ/EXPECT_DOUBLE_EQ` assertions which check
|
||||
that the distance between compared values is not more than 4 ULPs,
|
||||
there is also `EXPECT_NEAR(v1, v2, eps)` which checks that the absolute
|
||||
value of the difference between `v1` and `v2` is not greater than `eps`.
|
||||
|
||||
### C string comparison
|
||||
|
||||
Use string special macros for C strings comparisons.
|
||||
|
||||
`EXPECT_EQ` just compares pointers’ values, which is hardly what one
|
||||
wants comparing C strings. GoogleTest provides `EXPECT_STREQ` and
|
||||
`EXPECT_STRNE` macros to compare C string contents. There are also
|
||||
case-insensitive versions `EXPECT_STRCASEEQ`, `EXPECT_STRCASENE`.
|
||||
|
||||
### Error messages
|
||||
|
||||
Provide informative, but not too verbose error messages.
|
||||
|
||||
All GoogleTest asserts print compared expressions and their values, so
|
||||
there is no need to have them in error messages. Asserts print only
|
||||
compared values, they do not print any of interim variables, e.g.
|
||||
`ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18)` prints only
|
||||
one value. If you use some complex predicates, please consider
|
||||
`EXPECT_PRED*` or `EXPECT_FORMAT_PRED` assertions family, they check that
|
||||
a predicate returns true/success and print out all parameters values.
|
||||
|
||||
However in some cases, default information is not enough, a commonly
|
||||
used example is an assert inside a loop, GoogleTest will not print
|
||||
iteration values (unless it is an assert's parameter). Other
|
||||
demonstrative examples are printing error code and a corresponding
|
||||
error message; printing internal states which might have an impact on
|
||||
results. One should add this information to assert message using `<<`
|
||||
operator.
|
||||
|
||||
### Uncluttered output
|
||||
|
||||
Print information only if it is needed.
|
||||
|
||||
Too verbose tests which print all information even if they pass are
|
||||
very bad practice. They just pollute output, so it becomes harder to
|
||||
find useful information. In order not print information till it is
|
||||
really needed, one should consider saving it to a temporary buffer and
|
||||
pass to an assert.
|
||||
<https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp>
|
||||
has a good example how to do that.
|
||||
|
||||
### Failures propagation
|
||||
|
||||
Wrap a subroutine call into `EXPECT_NO_FATAL_FAILURE` macro to
|
||||
propagate failures.
|
||||
|
||||
`ASSERT` and `FAIL` abort only the current function, so if you have them
|
||||
in a subroutine, a test will not be aborted after the subroutine even
|
||||
if `ASSERT` or `FAIL` fails. You should call such subroutines in
|
||||
`ASSERT_NO_FATAL_FAILURE` macro to propagate fatal failures and abort a
|
||||
test. `(EXPECT|ASSERT)_NO_FATAL_FAILURE` can also be used to provide
|
||||
more information.
|
||||
|
||||
Due to obvious reasons, there are no
|
||||
`(EXPECT|ASSERT)_NO_NONFATAL_FAILURE` macros. However, if you need to
|
||||
check if a subroutine generated a nonfatal failure (failed an `EXPECT`),
|
||||
you can use `::testing::Test::HasNonfatalFailure` function,
|
||||
or `::testing::Test::HasFailure` function to check if a subroutine
|
||||
generated any failures, see [Several checks](#several-checks).
|
||||
|
||||
## Naming and Grouping
|
||||
|
||||
### Test group names
|
||||
|
||||
Test group names should be in CamelCase, start and end with a letter.
|
||||
A test group should be named after tested class, functionality,
|
||||
subsystem, etc.
|
||||
|
||||
This naming scheme helps to find tests, filter them and simplifies
|
||||
test failure analysis. For example, class `Foo` - test group `Foo`,
|
||||
compiler logging subsystem - test group `CompilerLogging`, G1 GC — test
|
||||
group `G1GC`, and so forth.
|
||||
|
||||
### Filename
|
||||
|
||||
A test file must have `test_` prefix and `.cpp` suffix.
|
||||
|
||||
Both are actually requirements from the current build system to
|
||||
recognize your tests.
|
||||
|
||||
### File location
|
||||
|
||||
Test file location should reflect a location of the tested part of the product.
|
||||
|
||||
* All unit tests for a class from `foo/bar/baz.cpp` should be placed
|
||||
`foo/bar/test_baz.cpp` in `hotspot/test/native/` directory. Having all
|
||||
tests for a class in one file is a common practice for unit tests, it
|
||||
helps to see all existing tests at once, share functions and/or
|
||||
resources without losing encapsulation.
|
||||
|
||||
* For tests which test more than one class, directory hierarchy should
|
||||
be the same as product hierarchy, and file name should reflect the
|
||||
name of the tested subsystem/functionality. For example, if a
|
||||
sub-system under tests belongs to `gc/g1`, tests should be placed in
|
||||
`gc/g1` directory.
|
||||
|
||||
Please note that framework prepends directory name to a test group
|
||||
name. For example, if `TEST(foo, check_this)` and `TEST(bar, check_that)`
|
||||
are defined in `hotspot/test/native/gc/shared/test_foo.cpp` file, they
|
||||
will be reported as `gc/shared/foo::check_this` and
|
||||
`gc/shared/bar::check_that`.
|
||||
|
||||
### Test names
|
||||
|
||||
Test names should be in small_snake_case, start and end with a letter.
|
||||
A test name should reflect that a test checks.
|
||||
|
||||
Such naming makes tests self-descriptive and helps a lot during the
|
||||
whole test life cycle. It is easy to do test planning, test inventory,
|
||||
to see what things are not tested, to review tests, to analyze test
|
||||
failures, to evolve a test, etc. For example
|
||||
`foo_return_0_if_name_is_null` is better than `foo_sanity` or `foo_basic` or
|
||||
just `foo`, `humongous_objects_can_not_be_moved_by_young_gc` is better
|
||||
than `ho_young_gc`.
|
||||
|
||||
Actually using underscore is against GoogleTest project convention,
|
||||
because it can lead to illegal identifiers, however, this is too
|
||||
strict. Restricting usage of underscore for test names only and
|
||||
prohibiting test name starts or ends with an underscore are enough to
|
||||
be safe.
|
||||
|
||||
### Fixture classes
|
||||
|
||||
Fixture classes should be named after tested classes, subsystems, etc
|
||||
(follow [Test group names rule](#test-group-names)) and have
|
||||
`Test` suffix to prevent class name conflicts.
|
||||
|
||||
### Friend classes
|
||||
|
||||
All test purpose friends should have either `Test` or `Testable` suffix.
|
||||
|
||||
It greatly simplifies understanding of friendship’s purpose and allows
|
||||
statically check that private members are not exposed unexpectedly.
|
||||
Having `FooTest` as a friend of `Foo` without any comments will be
|
||||
understood as a necessary evil to get testability.
|
||||
|
||||
### OS/CPU specific tests
|
||||
|
||||
Guard OS/CPU specific tests by `#ifdef` and have OS/CPU name in filename.
|
||||
|
||||
For the time being, we do not support separate directories for OS,
|
||||
CPU, OS-CPU specific tests, in case we will have lots of such tests,
|
||||
we will change directory layout and build system to support that in
|
||||
the same way it is done in hotspot.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### Hotspot style
|
||||
|
||||
Abide the norms and rules accepted in Hotspot style guide.
|
||||
|
||||
Tests are a part of Hotspot, so everything (if applicable) we use for
|
||||
Hotspot, should be used for tests as well. Those guidelines cover
|
||||
test-specific things.
|
||||
|
||||
### Code/test metrics
|
||||
|
||||
Coverage information and other code/test metrics are quite useful to
|
||||
decide what tests should be written, what tests should be improved and
|
||||
what can be removed.
|
||||
|
||||
For unit tests, widely used and well-known coverage metric is branch
|
||||
coverage, which provides good quality of tests with relatively easy
|
||||
test development process. For other levels of testing, branch coverage
|
||||
is not as good, and one should consider others metrics, e.g.
|
||||
transaction flow coverage, data flow coverage.
|
||||
|
||||
### Access to non-public members
|
||||
|
||||
Use explicit friend class to get access to non-public members.
|
||||
|
||||
We do not use GoogleTest macro to declare friendship relation,
|
||||
because, from our point of view, it is less clear than an explicit
|
||||
declaration.
|
||||
|
||||
Declaring a test fixture class as a friend class of a tested test is
|
||||
the easiest and the clearest way to get access. However, it has some
|
||||
disadvantages, here is some of them:
|
||||
|
||||
* Each test has to be declared as a friend
|
||||
* Subclasses do not inheritance friendship relation
|
||||
|
||||
In other words, it is harder to share code between tests. Hence if you
|
||||
want to share code or expect it to be useful in other tests, you
|
||||
should consider making members in a tested class protected and
|
||||
introduce a shared test-only class which expose those members via
|
||||
public functions, or even making members publicly accessible right
|
||||
away in a product class. If it is not an option to change members
|
||||
visibility, one can create a friend class which exposes members.
|
||||
|
||||
### Death tests
|
||||
|
||||
You can not use death tests inside `TEST_OTHER_VM` and `TEST_VM_ASSERT*`.
|
||||
|
||||
We tried to make Hotspot-GoogleTest integration as transparent as
|
||||
possible, however, due to the current implementation of `TEST_OTHER_VM`
|
||||
and `TEST_VM_ASSERT*` tests, you cannot use death test functionality in
|
||||
them. These tests are implemented as GoogleTest death tests, and
|
||||
GoogleTest does not allow to have a death test inside another death
|
||||
test.
|
||||
|
||||
### External flags
|
||||
|
||||
Passing external flags to a tested JVM is not supported.
|
||||
|
||||
The rationality of such design decision is to simplify both tests and
|
||||
a test framework and to avoid failures related to incompatible flags
|
||||
combination till there is a good solution for that. However there are
|
||||
cases when one wants to test a JVM with specific flags combination,
|
||||
`_JAVA_OPTIONS` environment variable can be used to do that. Flags from
|
||||
`_JAVA_OPTIONS` will be used in `TEST_VM`, `TEST_OTHER_VM` and
|
||||
`TEST_VM_ASSERT*` tests.
|
||||
|
||||
### Test-specific flags
|
||||
|
||||
Passing flags to a tested JVM in `TEST_OTHER_VM` and `TEST_VM_ASSERT*`
|
||||
should be possible, but is not implemented yet.
|
||||
|
||||
Facility to pass test-specific flags is needed for system, regression
|
||||
or other types of tests which require a fully initialized JVM in some
|
||||
particular configuration, e.g. with Serial GC selected. There is no
|
||||
support for such tests now, however, there is a plan to add that in
|
||||
upcoming releases.
|
||||
|
||||
For now, if a test depends on flags values, it should have `if
|
||||
(!<flag>) { return }` guards in the very beginning and `@requires`
|
||||
comment similar to jtreg `@requires` directive right before test macros.
|
||||
<https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp>
|
||||
ha an example of this temporary workaround. It is important to follow
|
||||
that pattern as it allows us to easily find all such tests and update
|
||||
them as soon as there is an implementation of flag passing facility.
|
||||
|
||||
In long-term, we expect jtreg to support GoogleTest tests as first
|
||||
class citizens, that is to say, jtreg will parse @requires comments
|
||||
and filter out inapplicable tests.
|
||||
|
||||
### Flag restoring
|
||||
|
||||
Restore changed flags.
|
||||
|
||||
It is quite common for tests to configure JVM in a certain way
|
||||
changing flags’ values. GoogleTest provides two ways to set up
|
||||
environment before a test and restore it afterward: using either
|
||||
constructor and destructor or `SetUp` and `TearDown` functions. Both ways
|
||||
require to use a test fixture class, which sometimes is too wordy. The
|
||||
simpler facilities like `FLAG_GUARD` macro or `*FlagSetting` classes could
|
||||
be used in such cases to restore/set values.
|
||||
|
||||
Caveats:
|
||||
|
||||
* Changing a flag’s value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state.
|
||||
|
||||
* `FLAG_SET_*` macros can change more than one flag (in order to
|
||||
maintain invariants) so it is hard to predict what flags will be
|
||||
changed and it makes restoring all changed flags a nontrivial task.
|
||||
Thus in case one uses `FLAG_SET_*` macros, they should use `TEST_OTHER_VM`
|
||||
test type.
|
||||
|
||||
### GoogleTest documentation
|
||||
|
||||
In case you have any questions regarding GoogleTest itself, its
|
||||
asserts, test declaration macros, other macros, etc, please consult
|
||||
its documentation.
|
||||
|
||||
## TODO
|
||||
|
||||
Although this document provides guidelines on the most important parts
|
||||
of test development using GTest, it still misses a few items:
|
||||
|
||||
* Examples, esp for [access to non-public members](#access-to-non-public-members)
|
||||
|
||||
* test types: purpose, drawbacks, limitation
|
||||
* `TEST_VM`
|
||||
* `TEST_VM_F`
|
||||
* `TEST_OTHER_VM`
|
||||
* `TEST_VM_ASSERT`
|
||||
* `TEST_VM_ASSERT_MSG`
|
||||
|
||||
* Miscellaneous
|
||||
* Test libraries
|
||||
* where to place
|
||||
* how to write
|
||||
* how to use
|
||||
* test your tests
|
||||
* how to run tests in random order
|
||||
* how to run only specific tests
|
||||
* how to run each test separately
|
||||
* check that a test can find bugs it is supposed to by introducing them
|
||||
* mocks/stubs/dependency injection
|
||||
* setUp/tearDown
|
||||
* vs c-tor/d-tor
|
||||
* empty test to test them
|
||||
* internal (declared in .cpp) struct/classes
|
||||
@@ -137,8 +137,6 @@ TEST FAILURE</code></pre>
|
||||
<h4 id="timeout_factor-1">TIMEOUT_FACTOR</h4>
|
||||
<p>The timeout factor (<code>-timeoutFactor</code>).</p>
|
||||
<p>Defaults to 4.</p>
|
||||
<h4 id="failure_handler_timeout">FAILURE_HANDLER_TIMEOUT</h4>
|
||||
<p>Sets the argument <code>-timeoutHandlerTimeout</code> for JTReg. The default value is 0. This is only valid if the failure handler is built.</p>
|
||||
<h4 id="test_mode">TEST_MODE</h4>
|
||||
<p>The test mode (<code>agentvm</code> or <code>othervm</code>).</p>
|
||||
<p>Defaults to <code>agentvm</code>.</p>
|
||||
@@ -155,10 +153,8 @@ TEST FAILURE</code></pre>
|
||||
<p>Limit memory consumption (<code>-Xmx</code> and <code>-vmoption:-Xmx</code>, or none).</p>
|
||||
<p>Limit memory consumption for JTReg test framework and VM under test. Set to 0 to disable the limits.</p>
|
||||
<p>Defaults to 512m, except for hotspot, where it defaults to 0 (no limit).</p>
|
||||
<h4 id="max_output">MAX_OUTPUT</h4>
|
||||
<p>Set the property <code>javatest.maxOutputSize</code> for the launcher, to change the default JTReg log limit.</p>
|
||||
<h4 id="keywords">KEYWORDS</h4>
|
||||
<p>JTReg keywords sent to JTReg using <code>-k</code>. Please be careful in making sure that spaces and special characters (like <code>!</code>) are properly quoted. To avoid some issues, the special value <code>%20</code> can be used instead of space.</p>
|
||||
<p>JTReg kewords sent to JTReg using <code>-k</code>. Please be careful in making sure that spaces and special characters (like <code>!</code>) are properly quoted. To avoid some issues, the special value <code>%20</code> can be used instead of space.</p>
|
||||
<h4 id="extra_problem_lists">EXTRA_PROBLEM_LISTS</h4>
|
||||
<p>Use additional problem lists file or files, in addition to the default ProblemList.txt located at the JTReg test roots.</p>
|
||||
<p>If multiple file names are specified, they should be separated by space (or, to help avoid quoting issues, the special value <code>%20</code>).</p>
|
||||
@@ -174,8 +170,6 @@ TEST FAILURE</code></pre>
|
||||
<h4 id="vm_options-1">VM_OPTIONS</h4>
|
||||
<p>Additional Java options to be used when compiling and running classes (sent to JTReg as <code>-vmoption</code>).</p>
|
||||
<p>This option is only needed in special circumstances. To pass Java options to your test classes, use <code>JAVA_OPTIONS</code>.</p>
|
||||
<h4 id="launcher_options">LAUNCHER_OPTIONS</h4>
|
||||
<p>Additional Java options that are sent to the java launcher that starts the JTReg harness.</p>
|
||||
<h4 id="aot_modules-1">AOT_MODULES</h4>
|
||||
<p>Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value <code>%20</code>).</p>
|
||||
<h4 id="retry_count">RETRY_COUNT</h4>
|
||||
@@ -211,19 +205,14 @@ TEST FAILURE</code></pre>
|
||||
<p>Docker tests with default parameters may fail on systems with glibc versions not compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:</p>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"</code></pre>
|
||||
<p>To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using <code>JAVA_OPTIONS</code>.</p>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" \
|
||||
JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu
|
||||
-Djdk.test.docker.image.version=latest"</code></pre>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"</code></pre>
|
||||
<h3 id="non-us-locale">Non-US locale</h3>
|
||||
<p>If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting <code>LANG="en_US"</code> in the environment before running tests should work. On Windows, setting <code>JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"</code> helps for most, but not all test cases.</p>
|
||||
<p>For example:</p>
|
||||
<p>If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting <code>LANG="en_US"</code> in the environment before running tests should work. On Windows, setting <code>JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"</code> helps for most, but not all test cases. For example:</p>
|
||||
<pre><code>$ export LANG="en_US" && make test TEST=...
|
||||
$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...</code></pre>
|
||||
<h3 id="pkcs11-tests">PKCS11 Tests</h3>
|
||||
<p>It is highly recommended to use the latest NSS version when running PKCS11 tests. Improper NSS version may lead to unexpected failures which are hard to diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu 18.04 with the default NSS version in the system. To run these tests correctly, the system property <code>test.nss.lib.paths</code> is required on Ubuntu 18.04 to specify the alternative NSS lib directories.</p>
|
||||
<p>For example:</p>
|
||||
<pre><code>$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" \
|
||||
JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"</code></pre>
|
||||
<p>It is highly recommended to use the latest NSS version when running PKCS11 tests. Improper NSS version may lead to unexpected failures which are hard to diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu 18.04 with the default NSS version in the system. To run these tests correctly, the system property <code>test.nss.lib.paths</code> is required on Ubuntu 18.04 to specify the alternative NSS lib directories. For example:</p>
|
||||
<pre><code>$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"</code></pre>
|
||||
<p>For more notes about the PKCS11 tests, please refer to test/jdk/sun/security/pkcs11/README.</p>
|
||||
<h3 id="client-ui-tests">Client UI Tests</h3>
|
||||
<p>Some Client UI tests use key sequences which may be reserved by the operating system. Usually that causes the test failure. So it is highly recommended to disable system key shortcuts prior testing. The steps to access and disable system key shortcuts for various platforms are provided below.</p>
|
||||
|
||||
158
doc/testing.md
158
doc/testing.md
@@ -37,11 +37,11 @@ Note that this option should point to the JTReg home, i.e. the top directory,
|
||||
containing `lib/jtreg.jar` etc. (An alternative is to set the `JT_HOME`
|
||||
environment variable to point to the JTReg home before running `configure`.)
|
||||
|
||||
To be able to run microbenchmarks, `configure` needs to know where to find the
|
||||
JMH dependency. Use `--with-jmh=<path to JMH jars>` to point to a directory
|
||||
containing the core JMH and transitive dependencies. The recommended
|
||||
dependencies can be retrieved by running `sh make/devkit/createJMHBundle.sh`,
|
||||
after which `--with-jmh=build/jmh/jars` should work.
|
||||
To be able to run microbenchmarks, `configure` needs to know where to find
|
||||
the JMH dependency. Use `--with-jmh=<path to JMH jars>` to point to a directory
|
||||
containing the core JMH and transitive dependencies. The recommended dependencies
|
||||
can be retrieved by running `sh make/devkit/createJMHBundle.sh`, after which
|
||||
`--with-jmh=build/jmh/jars` should work.
|
||||
|
||||
## Test selection
|
||||
|
||||
@@ -182,10 +182,10 @@ variables.
|
||||
These variables use a keyword=value approach to allow multiple values to be
|
||||
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_FACTOR=8`, but using the keyword format
|
||||
means that the `JTREG` variable is parsed and verified for correctness, so
|
||||
`JTREG="TMIEOUT_FACTOR=8"` would give an error, while `JTREG_TMIEOUT_FACTOR=8`
|
||||
would just pass unnoticed.
|
||||
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_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
|
||||
normally eats `;`, the recommended usage is to write the assignment inside
|
||||
@@ -203,10 +203,9 @@ test suites.
|
||||
|
||||
### General keywords (TEST_OPTS)
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
There are also some keywords that applies globally to the test runner system,
|
||||
not to any specific test suites. These are also available as TEST_OPTS keywords.
|
||||
@@ -253,13 +252,12 @@ for only recently changed code. JCOV_DIFF_CHANGESET specifies a source
|
||||
revision. A textual report will be generated showing coverage of the diff
|
||||
between the specified revision and the repository tip.
|
||||
|
||||
The report is stored in
|
||||
`build/$BUILD/test-results/jcov-output/diff_coverage_report` file.
|
||||
The report is stored in `build/$BUILD/test-results/jcov-output/diff_coverage_report`
|
||||
file.
|
||||
|
||||
### JTReg keywords
|
||||
|
||||
#### JOBS
|
||||
|
||||
The test concurrency (`-concurrency`).
|
||||
|
||||
Defaults to TEST_JOBS (if set by `--with-test-jobs=`), otherwise it defaults to
|
||||
@@ -267,43 +265,32 @@ JOBS, except for Hotspot, where the default is *number of CPU cores/2*,
|
||||
but never more than *memory size in GB/2*.
|
||||
|
||||
#### TIMEOUT_FACTOR
|
||||
|
||||
The timeout factor (`-timeoutFactor`).
|
||||
|
||||
Defaults to 4.
|
||||
|
||||
#### FAILURE_HANDLER_TIMEOUT
|
||||
|
||||
Sets the argument `-timeoutHandlerTimeout` for JTReg. The default value is 0.
|
||||
This is only valid if the failure handler is built.
|
||||
|
||||
#### TEST_MODE
|
||||
|
||||
The test mode (`agentvm` or `othervm`).
|
||||
|
||||
Defaults to `agentvm`.
|
||||
|
||||
#### ASSERT
|
||||
|
||||
Enable asserts (`-ea -esa`, or none).
|
||||
|
||||
Set to `true` or `false`. If true, adds `-ea -esa`. Defaults to true, except
|
||||
for hotspot.
|
||||
|
||||
#### VERBOSE
|
||||
|
||||
The verbosity level (`-verbose`).
|
||||
|
||||
Defaults to `fail,error,summary`.
|
||||
|
||||
#### RETAIN
|
||||
|
||||
What test data to retain (`-retain`).
|
||||
|
||||
Defaults to `fail,error`.
|
||||
|
||||
#### MAX_MEM
|
||||
|
||||
Limit memory consumption (`-Xmx` and `-vmoption:-Xmx`, or none).
|
||||
|
||||
Limit memory consumption for JTReg test framework and VM under test. Set to 0
|
||||
@@ -311,14 +298,9 @@ to disable the limits.
|
||||
|
||||
Defaults to 512m, except for hotspot, where it defaults to 0 (no limit).
|
||||
|
||||
#### MAX_OUTPUT
|
||||
|
||||
Set the property `javatest.maxOutputSize` for the launcher, to change the
|
||||
default JTReg log limit.
|
||||
|
||||
#### KEYWORDS
|
||||
|
||||
JTReg keywords sent to JTReg using `-k`. Please be careful in making sure that
|
||||
JTReg kewords sent to JTReg using `-k`. Please be careful in making sure that
|
||||
spaces and special characters (like `!`) are properly quoted. To avoid some
|
||||
issues, the special value `%20` can be used instead of space.
|
||||
|
||||
@@ -341,30 +323,23 @@ Set to `true` or `false`.
|
||||
If `true`, JTReg will use `-match:` option, otherwise `-exclude:` will be used.
|
||||
Default is `false`.
|
||||
|
||||
#### OPTIONS
|
||||
|
||||
#### OPTIONS
|
||||
Additional options to the JTReg test framework.
|
||||
|
||||
Use `JTREG="OPTIONS=--help all"` to see all available JTReg options.
|
||||
|
||||
#### JAVA_OPTIONS
|
||||
|
||||
Additional Java options for running test classes (sent to JTReg as
|
||||
`-javaoption`).
|
||||
|
||||
#### VM_OPTIONS
|
||||
|
||||
Additional Java options to be used when compiling and running classes (sent to
|
||||
JTReg as `-vmoption`).
|
||||
|
||||
This option is only needed in special circumstances. To pass Java options to
|
||||
your test classes, use `JAVA_OPTIONS`.
|
||||
|
||||
#### LAUNCHER_OPTIONS
|
||||
|
||||
Additional Java options that are sent to the java launcher that starts the
|
||||
JTReg harness.
|
||||
|
||||
#### AOT_MODULES
|
||||
|
||||
Generate AOT modules before testing for the specified module, or set of
|
||||
@@ -378,7 +353,6 @@ Retry failed tests up to a set number of times. Defaults to 0.
|
||||
### Gtest keywords
|
||||
|
||||
#### REPEAT
|
||||
|
||||
The number of times to repeat the tests (`--gtest_repeat`).
|
||||
|
||||
Default is 1. Set to -1 to repeat indefinitely. This can be especially useful
|
||||
@@ -386,7 +360,6 @@ combined with `OPTIONS=--gtest_break_on_failure` to reproduce an intermittent
|
||||
problem.
|
||||
|
||||
#### OPTIONS
|
||||
|
||||
Additional options to the Gtest test framework.
|
||||
|
||||
Use `GTEST="OPTIONS=--help"` to see all available Gtest options.
|
||||
@@ -400,127 +373,98 @@ modules. If multiple modules are specified, they should be separated by space
|
||||
### Microbenchmark keywords
|
||||
|
||||
#### FORK
|
||||
|
||||
Override the number of benchmark forks to spawn. Same as specifying `-f <num>`.
|
||||
|
||||
#### ITER
|
||||
|
||||
Number of measurement iterations per fork. Same as specifying `-i <num>`.
|
||||
|
||||
#### TIME
|
||||
|
||||
Amount of time to spend in each measurement iteration, in seconds. Same as
|
||||
specifying `-r <num>`
|
||||
|
||||
#### WARMUP_ITER
|
||||
|
||||
Number of warmup iterations to run before the measurement phase in each fork.
|
||||
Same as specifying `-wi <num>`.
|
||||
|
||||
#### WARMUP_TIME
|
||||
|
||||
Amount of time to spend in each warmup iteration. Same as specifying `-w <num>`.
|
||||
|
||||
#### RESULTS_FORMAT
|
||||
|
||||
Specify to have the test run save a log of the values. Accepts the same values
|
||||
as `-rff`, i.e., `text`, `csv`, `scsv`, `json`, or `latex`.
|
||||
|
||||
#### VM_OPTIONS
|
||||
|
||||
Additional VM arguments to provide to forked off VMs. Same as `-jvmArgs <args>`
|
||||
|
||||
#### OPTIONS
|
||||
|
||||
Additional arguments to send to JMH.
|
||||
|
||||
## Notes for Specific Tests
|
||||
|
||||
### Docker Tests
|
||||
|
||||
Docker tests with default parameters may fail on systems with glibc versions
|
||||
not compatible with the one used in the default docker image (e.g., Oracle
|
||||
Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu
|
||||
18.04 if run like this on x86:
|
||||
Docker tests with default parameters may fail on systems with glibc versions not
|
||||
compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86).
|
||||
For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:
|
||||
|
||||
```
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"
|
||||
```
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"
|
||||
|
||||
To run these tests correctly, additional parameters for the correct docker
|
||||
image are required on Ubuntu 18.04 by using `JAVA_OPTIONS`.
|
||||
To run these tests correctly, additional parameters for the correct docker image are
|
||||
required on Ubuntu 18.04 by using `JAVA_OPTIONS`.
|
||||
|
||||
```
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" \
|
||||
JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu
|
||||
-Djdk.test.docker.image.version=latest"
|
||||
```
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
|
||||
|
||||
### Non-US locale
|
||||
|
||||
If your locale is non-US, some tests are likely to fail. To work around this
|
||||
you can set the locale to US. On Unix platforms simply setting `LANG="en_US"`
|
||||
in the environment before running tests should work. On Windows, setting
|
||||
`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but
|
||||
not all test cases.
|
||||
|
||||
If your locale is non-US, some tests are likely to fail. To work around this you can
|
||||
set the locale to US. On Unix platforms simply setting `LANG="en_US"` in the
|
||||
environment before running tests should work. On Windows, setting
|
||||
`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but not all test cases.
|
||||
For example:
|
||||
|
||||
```
|
||||
$ export LANG="en_US" && make test TEST=...
|
||||
$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...
|
||||
```
|
||||
$ export LANG="en_US" && make test TEST=...
|
||||
$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...
|
||||
|
||||
### PKCS11 Tests
|
||||
|
||||
It is highly recommended to use the latest NSS version when running PKCS11
|
||||
tests. Improper NSS version may lead to unexpected failures which are hard to
|
||||
diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail
|
||||
on Ubuntu 18.04 with the default NSS version in the system. To run these tests
|
||||
correctly, the system property `test.nss.lib.paths` is required on Ubuntu 18.04
|
||||
to specify the alternative NSS lib directories.
|
||||
|
||||
It is highly recommended to use the latest NSS version when running PKCS11 tests.
|
||||
Improper NSS version may lead to unexpected failures which are hard to diagnose.
|
||||
For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu
|
||||
18.04 with the default NSS version in the system.
|
||||
To run these tests correctly, the system property `test.nss.lib.paths` is required
|
||||
on Ubuntu 18.04 to specify the alternative NSS lib directories.
|
||||
For example:
|
||||
|
||||
```
|
||||
$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" \
|
||||
JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"
|
||||
```
|
||||
$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"
|
||||
|
||||
For more notes about the PKCS11 tests, please refer to
|
||||
test/jdk/sun/security/pkcs11/README.
|
||||
For more notes about the PKCS11 tests, please refer to test/jdk/sun/security/pkcs11/README.
|
||||
|
||||
### Client UI Tests
|
||||
|
||||
Some Client UI tests use key sequences which may be reserved by the operating
|
||||
system. Usually that causes the test failure. So it is highly recommended to
|
||||
disable system key shortcuts prior testing. The steps to access and disable
|
||||
system key shortcuts for various platforms are provided below.
|
||||
system. Usually that causes the test failure. So it is highly recommended to disable
|
||||
system key shortcuts prior testing. The steps to access and disable system key shortcuts
|
||||
for various platforms are provided below.
|
||||
|
||||
#### MacOS
|
||||
|
||||
Choose Apple menu; System Preferences, click Keyboard, then click Shortcuts;
|
||||
select or deselect desired shortcut.
|
||||
|
||||
For example,
|
||||
test/jdk/javax/swing/TooltipManager/JMenuItemToolTipKeyBindingsTest/JMenuItemToolTipKeyBindingsTest.java
|
||||
fails on MacOS because it uses `CTRL + F1` key sequence to show or hide tooltip
|
||||
message but the key combination is reserved by the operating system. To run the
|
||||
test correctly the default global key shortcut should be disabled using the
|
||||
steps described above, and then deselect "Turn keyboard access on or off"
|
||||
option which is responsible for `CTRL + F1` combination.
|
||||
For example, test/jdk/javax/swing/TooltipManager/JMenuItemToolTipKeyBindingsTest/JMenuItemToolTipKeyBindingsTest.java fails
|
||||
on MacOS because it uses `CTRL + F1` key sequence to show or hide tooltip message
|
||||
but the key combination is reserved by the operating system. To run the test correctly
|
||||
the default global key shortcut should be disabled using the steps described above, and then deselect
|
||||
"Turn keyboard access on or off" option which is responsible for `CTRL + F1` combination.
|
||||
|
||||
#### Linux
|
||||
|
||||
Open the Activities overview and start typing Settings; Choose Settings, click
|
||||
Devices, then click Keyboard; set or override desired shortcut.
|
||||
Open the Activities overview and start typing Settings; Choose Settings, click Devices,
|
||||
then click Keyboard; set or override desired shortcut.
|
||||
|
||||
#### Windows
|
||||
|
||||
Type `gpedit` in the Search and then click Edit group policy; navigate to User
|
||||
Configuration -> Administrative Templates -> Windows Components -> File
|
||||
Explorer; in the right-side pane look for "Turn off Windows key hotkeys" and
|
||||
double click on it; enable or disable hotkeys.
|
||||
Type `gpedit` in the Search and then click Edit group policy; navigate to
|
||||
User Configuration -> Administrative Templates -> Windows Components -> File Explorer;
|
||||
in the right-side pane look for "Turn off Windows key hotkeys" and double click on it;
|
||||
enable or disable hotkeys.
|
||||
|
||||
Note: restart is required to make the settings take effect.
|
||||
|
||||
|
||||
10
jb/project/docker/x86/Dockerfile
Normal file
10
jb/project/docker/x86/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM i386/ubuntu:xenial
|
||||
|
||||
RUN linux32 apt-get update && apt-get install -y --no-install-recommends apt-utils
|
||||
RUN linux32 apt-get -y install file build-essential zip unzip tar wget curl libx11-dev libxext-dev \
|
||||
libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libasound2-data \
|
||||
libpng12-0 libasound2 libfreetype6 libfontconfig1-dev libasound2-dev autoconf git
|
||||
# Install Java 15
|
||||
RUN wget https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_i686.tar.gz \
|
||||
-O - | tar xz -C /
|
||||
RUN mv /zulu15.27.17-ca-jdk15.0.0-linux_i686 /jdk15.0.0
|
||||
2958
jb/project/hotspot-cmake/CMakeLists.txt
Normal file
2958
jb/project/hotspot-cmake/CMakeLists.txt
Normal file
File diff suppressed because it is too large
Load Diff
49
jb/project/tools/common/scripts/common.sh
Normal file
49
jb/project/tools/common/scripts/common.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
VENDOR_NAME="JetBrains s.r.o."
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}"
|
||||
[ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}"
|
||||
|
||||
do_reset_changes=0
|
||||
function do_exit() {
|
||||
exit_code=$1
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
function update_jsdk_mods() {
|
||||
__jsdk=$1
|
||||
__jcef_mods=$2
|
||||
__orig_jsdk_mods=$3
|
||||
__updated_jsdk_mods=$4
|
||||
|
||||
# re-create java.desktop.jmod with updated module-info.class
|
||||
tmp=.java.desktop.$$.tmp
|
||||
mkdir "$tmp" || exit $?
|
||||
"$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.desktop.jmod || exit $?
|
||||
"$__jsdk"/bin/javac \
|
||||
--patch-module java.desktop="$__orig_jsdk_mods"/java.desktop.jmod \
|
||||
--module-path "$__jcef_mods" -d "$tmp"/classes src/java.desktop/share/classes/module-info.java || exit $?
|
||||
"$__jsdk"/bin/jmod \
|
||||
create --class-path "$tmp"/classes --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \
|
||||
java.desktop.jmod || exit $?
|
||||
mv java.desktop.jmod "$__updated_jsdk_mods" || exit $?
|
||||
rm -rf "$tmp"
|
||||
|
||||
# re-create java.base.jmod with updated hashes
|
||||
tmp=.java.base.$$.tmp
|
||||
mkdir "$tmp" || exit $?
|
||||
hash_modules=$("$JSDK"/bin/jmod describe "$__orig_jsdk_mods"/java.base.jmod | grep hashes | awk '{print $2}' | tr '\n' '|' | sed s/\|$//) || exit $?
|
||||
"$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.base.jmod || exit $?
|
||||
rm "$__updated_jsdk_mods"/java.base.jmod || exit $? # temp exclude from path
|
||||
"$__jsdk"/bin/jmod \
|
||||
create --module-path "$__updated_jsdk_mods" --hash-modules "$hash_modules" \
|
||||
--class-path "$tmp"/classes --cmds "$tmp"/bin --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \
|
||||
java.base.jmod || exit $?
|
||||
mv java.base.jmod "$__updated_jsdk_mods" || exit $?
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
function get_mods_list() {
|
||||
__mods=$1
|
||||
|
||||
return `ls "$__mods"` | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/linux/scripts
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
@@ -4,9 +4,6 @@
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -21,22 +18,29 @@ JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?)
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-boot-jdk=amazon-corretto-11.0.5.10.1-linux-aarch64 \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-aarch64-normal-server-release || exit $?
|
||||
make images CONF=linux-aarch64-normal-server-release test-image || exit $?
|
||||
make clean CONF=linux-aarch64-server-release || exit $?
|
||||
make images CONF=linux-aarch64-server-release test-image || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number}
|
||||
BASE_DIR=build/linux-aarch64-normal-server-release/images
|
||||
BASE_DIR=build/linux-aarch64-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
@@ -47,6 +51,9 @@ rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
|
||||
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
|
||||
|
||||
tar -pcf $JBSDK.tar \
|
||||
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -16,124 +17,109 @@
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
# Environment variables:
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_linux_x64
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64}
|
||||
|
||||
function create_jbr {
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx_jcef")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__arch_name=$2
|
||||
__modules_path=$3
|
||||
__modules=$4
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x64-b$build_number
|
||||
[ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-"
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number}
|
||||
|
||||
echo Running jlink....
|
||||
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
|
||||
$JSDK/bin/jlink \
|
||||
--module-path $JSDK/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE
|
||||
--module-path "$__modules_path" --no-man-pages --compress=2 \
|
||||
--add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name"
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -R $BASE_DIR/$JBR_BUNDLE $BASE_DIR/jbr
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $?
|
||||
fi
|
||||
grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release
|
||||
# jmod does not preserve file permissions (JDK-8173610)
|
||||
[ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
tar -pcf "$JBR".tar -C "$IMAGES_DIR" "$__arch_name" || do_exit $?
|
||||
[ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz"
|
||||
gzip "$JBR".tar || do_exit $?
|
||||
rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=linux-x86_64-server-release
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
;;
|
||||
"fd")
|
||||
do_reset_changes=1
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
|
||||
RELEASE_NAME=linux-x86_64-server-fastdebug
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--enable-cds=yes || exit $?
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--enable-cds=yes || exit $?
|
||||
fi
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-version-pre= \
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--enable-cds=yes || do_exit $?
|
||||
|
||||
make images CONF=linux-x86_64-server-release || exit $?
|
||||
make clean CONF=$RELEASE_NAME || exit $?
|
||||
make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
JSDK=build/linux-x86_64-server-release/images/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-linux-x64-b$build_number
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
BASE_DIR=build/linux-x86_64-server-release/images
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $?
|
||||
update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $?
|
||||
cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $?
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR $JBRSDK_BUNDLE || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
create_jbr ${bundle_type}
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make test-image || exit $?
|
||||
# create sdk image bundle
|
||||
modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $?
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number}
|
||||
echo Creating "$JBRSDK_TEST" ...
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
gzip "$JBRSDK_TEST".tar || do_exit $?
|
||||
fi
|
||||
|
||||
echo Creating $JBSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
fi
|
||||
do_exit 0
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=fastdebug \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-x86_64-normal-server-fastdebug || exit $?
|
||||
make images CONF=linux-x86_64-normal-server-fastdebug || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number}
|
||||
BASE_DIR=build/linux-x86_64-normal-server-fastdebug/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar \
|
||||
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x64-fastdebug-b$build_number
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list | sed s/" "//g | sed s/,$//g) \
|
||||
--output ${BASE_DIR}/${JBR_BUNDLE} || exit $?
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
tar -czf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
@@ -4,9 +4,6 @@
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -21,21 +18,29 @@ JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?)
|
||||
|
||||
linux32 bash configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-boot-jdk=/jbrsdk-11.0.5-b1 \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-x86-normal-server-release || exit $?
|
||||
make images CONF=linux-x86-normal-server-release test-image || exit $?
|
||||
make clean CONF=linux-x86-server-release || exit $?
|
||||
make images CONF=linux-x86-server-release test-image || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number}
|
||||
BASE_DIR=build/linux-x86-normal-server-release/images
|
||||
BASE_DIR=build/linux-x86-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
@@ -46,6 +51,9 @@ rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
|
||||
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
|
||||
|
||||
tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/mac/scripts
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -16,133 +17,110 @@
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
# Environment variables:
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_mac
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo "$JBSDK_VERSION" | sed 's/_/\./g')
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_mac}
|
||||
MAJOR_JBSDK_VERSION=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}')
|
||||
BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 14)}
|
||||
|
||||
function create_jbr {
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx_jcef")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__modules_path=$2
|
||||
__modules=$3
|
||||
|
||||
JRE_CONTENTS=${BASE_DIR}/${JBR_BUNDLE}/Contents
|
||||
JRE_HOME=${JRE_CONTENTS}/Home
|
||||
if [ -d "${JRE_CONTENTS}" ]; then
|
||||
rm -rf ${JRE_CONTENTS}
|
||||
fi
|
||||
mkdir -p ${JRE_CONTENTS}
|
||||
tmp=.bundle.$$.tmp
|
||||
mkdir "$tmp" || do_exit $?
|
||||
|
||||
JBR=${JBR_BASE_NAME}-osx-x64-b${build_number}
|
||||
[ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-"
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-osx-x64-${fastdebug_infix}b${build_number}
|
||||
|
||||
${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \
|
||||
--module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || exit $?
|
||||
grep -v "^JAVA_VERSION" ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release | grep -v "^MODULES" >> ${JRE_HOME}/release
|
||||
cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS}
|
||||
cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS}
|
||||
JRE_CONTENTS=$tmp/$__bundle_name/Contents
|
||||
mkdir -p "$JRE_CONTENTS" || do_exit $?
|
||||
|
||||
if [[ "${bundle_type}" == *jcef* ]]; then
|
||||
rm -rf ${JRE_CONTENTS}/Frameworks || exit $?
|
||||
rm -rf ${JRE_CONTENTS}/Helpers || exit $?
|
||||
cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?
|
||||
cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $?
|
||||
fi
|
||||
echo Running jlink...
|
||||
"$JSDK"/bin/jlink \
|
||||
--module-path "$__modules_path" --no-man-pages --compress=2 \
|
||||
--add-modules "$__modules" --output "$JRE_CONTENTS/Home" || do_exit $?
|
||||
|
||||
echo Creating ${JBR}.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $?
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
|
||||
cp "$JSDK"/../Info.plist "$JRE_CONTENTS"
|
||||
[ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?)
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__bundle_name" || do_exit $?
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=macosx-x86_64-server-release
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
;;
|
||||
"fd")
|
||||
do_reset_changes=1
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
|
||||
RELEASE_NAME=macosx-x86_64-server-fastdebug
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
sh configure \
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v $BOOT_JDK` \
|
||||
--enable-cds=yes || exit $?
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v $BOOT_JDK` \
|
||||
--enable-cds=yes || exit $?
|
||||
fi
|
||||
make images CONF=macosx-x86_64-server-release || exit $?
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--enable-cds=yes || do_exit $?
|
||||
|
||||
JSDK=build/macosx-x86_64-server-release/images/jdk-bundle
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number}
|
||||
make clean CONF=$RELEASE_NAME || do_exit $?
|
||||
make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
BASE_DIR=jre
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk-bundle/jdk-$MAJOR_JBSDK_VERSION.jdk/Contents/Home
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf $BASE_DIR
|
||||
mkdir $BASE_DIR || exit $?
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $?
|
||||
update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $?
|
||||
cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ || exit $?
|
||||
cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ || exit $?
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \
|
||||
--exclude='._*' --exclude='.DS_Store' --exclude='*~' \
|
||||
--exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \
|
||||
$JBRSDK_BUNDLE || exit $?
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
create_jbr "${bundle_type}" || exit $?
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make test-image || exit $?
|
||||
# create sdk image bundle
|
||||
modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $?
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-x64-b${build_number}
|
||||
echo Creating "$JBRSDK_TEST" ...
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
fi
|
||||
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \
|
||||
--exclude='test/jdk/demos' test || exit $?
|
||||
fi
|
||||
do_exit 0
|
||||
@@ -1,83 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=fastdebug \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v 11` \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=macosx-x86_64-normal-server-fastdebug || exit $?
|
||||
make images CONF=macosx-x86_64-normal-server-fastdebug || exit $?
|
||||
|
||||
JSDK=build/macosx-x86_64-normal-server-fastdebug/images/jdk-bundle
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number}
|
||||
|
||||
BASE_DIR=jre
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf $BASE_DIR
|
||||
mkdir $BASE_DIR || exit $?
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/
|
||||
cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents
|
||||
|
||||
COPYFILE_DISABLE=1 \
|
||||
tar -pczf ${JBSDK}.tar.gz -C ${BASE_DIR} \
|
||||
--exclude='._*' --exclude='.DS_Store' --exclude='*~' \
|
||||
--exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \
|
||||
${JBRSDK_BUNDLE} || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents
|
||||
JRE_HOME=$JRE_CONTENTS/Home
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
mkdir -p $JRE_CONTENTS
|
||||
|
||||
if [ -d "$JRE_HOME" ]; then
|
||||
rm -rf $JRE_HOME
|
||||
fi
|
||||
|
||||
JBR=${JBR_BASE_NAME}-osx-x64-fastdebug-b${build_number}
|
||||
|
||||
$BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \
|
||||
--module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list | sed s/" "//g) --output $JRE_HOME || exit $?
|
||||
grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release
|
||||
cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS
|
||||
cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS
|
||||
cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?
|
||||
cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $?
|
||||
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $?
|
||||
@@ -26,7 +26,8 @@ log "Signing libraries and executables..."
|
||||
# -perm +111 searches for executables
|
||||
for f in \
|
||||
"Contents/Home/bin" \
|
||||
"Contents/Home/lib"; do
|
||||
"Contents/Home/lib" \
|
||||
"Contents/Frameworks"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
|
||||
@@ -37,14 +37,13 @@ BUILD_NAME="$(ls "$EXPLODED")"
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/Home/jmods $BACKUP_JMODS
|
||||
fi
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS
|
||||
fi
|
||||
if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS
|
||||
fi
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS
|
||||
fi
|
||||
|
||||
#log "$INPUT_FILE unzipped and removed"
|
||||
log "$INPUT_FILE extracted and removed"
|
||||
|
||||
APPLICATION_PATH="$EXPLODED/$BUILD_NAME"
|
||||
@@ -128,15 +127,9 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..."
|
||||
(
|
||||
#cd "$EXPLODED"
|
||||
#ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE"
|
||||
if test ! -z $(ls $BACKUP_JMODS/libjli.dylib); then
|
||||
mv $BACKUP_JMODS/libjli.dylib $EXPLODED/$BUILD_NAME/Contents/MacOS
|
||||
fi
|
||||
if test -d $BACKUP_JMODS/jmods; then
|
||||
mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
fi
|
||||
if test -d $BACKUP_JMODS/Frameworks; then
|
||||
mv $BACKUP_JMODS/Frameworks $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
fi
|
||||
|
||||
COPYFILE_DISABLE=1 tar -pczf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME
|
||||
log "Finished zipping"
|
||||
|
||||
30
jb/project/tools/patches/add_jcef_module.patch
Normal file
30
jb/project/tools/patches/add_jcef_module.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
diff --git modules.list modules.list
|
||||
index 7c4b3e9cb6d..5ed60349ca7 100644
|
||||
--- modules.list
|
||||
+++ modules.list
|
||||
@@ -53,4 +53,7 @@ jdk.security.jgss,
|
||||
jdk.unsupported,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
-jdk.hotspot.agent
|
||||
+jdk.hotspot.agent,
|
||||
+jcef,
|
||||
+gluegen.rt,
|
||||
+jogl.all
|
||||
diff --git src/java.desktop/share/classes/module-info.java src/java.desktop/share/classes/module-info.java
|
||||
index b663b382f52..3e9acdc0c27 100644
|
||||
--- src/java.desktop/share/classes/module-info.java
|
||||
+++ src/java.desktop/share/classes/module-info.java
|
||||
@@ -109,7 +109,11 @@ module java.desktop {
|
||||
// see make/GensrcModuleInfo.gmk
|
||||
exports sun.awt to
|
||||
jdk.accessibility,
|
||||
- jdk.unsupported.desktop;
|
||||
+ jdk.unsupported.desktop,
|
||||
+ jcef,
|
||||
+ jogl.all;
|
||||
+
|
||||
+ exports java.awt.peer to jcef;
|
||||
|
||||
exports java.awt.dnd.peer to jdk.unsupported.desktop;
|
||||
exports sun.awt.dnd to jdk.unsupported.desktop;
|
||||
5066
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
5066
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
From 095315ce3f66bcf14ae1d06d84bbeb24bb068ae8 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:18:22 +0100
|
||||
Subject: [PATCH 02/48] We need to set classRedefinitionCount on new class, not
|
||||
old class.
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 83c0952de37..83cf0be090b 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1904,7 +1904,7 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
oop class_mirror = ik->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
- java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
|
||||
+ java_lang_Class::set_classRedefinedCount(ik->new_version()->java_mirror(), new_count);
|
||||
|
||||
if (class_oop != _the_class_oop) {
|
||||
// _the_class_oop count is printed at end of redefine_single_class()
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
From 9ddbbcdc73e653af7807ead68705c1c9267c9192 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:22:01 +0100
|
||||
Subject: [PATCH 03/48] Fix crashes in MetadataOnStackMark::~MetadataOnSta
|
||||
|
||||
MetadataOnStackMark shoukld not remove dcevm stuff. It was added
|
||||
accidentaly in dcevm9,
|
||||
and never was part of doit() in previous versions.
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 83cf0be090b..61af07d0f86 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -470,7 +470,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
|
||||
// Mark methods seen on stack and everywhere else so old methods are not
|
||||
// cleaned up if they're on the stack.
|
||||
- MetadataOnStackMark md_on_stack(true);
|
||||
+
|
||||
+ // FIXME: fails in enhanced redefinition
|
||||
+ // MetadataOnStackMark md_on_stack(true);
|
||||
HandleMark hm(thread); // make sure any handles created are deleted
|
||||
// before the stack walk again.
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From bb3eb4931818c3ef43c48d0781d73b8e2eb6dea9 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 3 Dec 2018 19:34:53 +0100
|
||||
Subject: [PATCH 04/48] Fix problem with nested members
|
||||
|
||||
Reported at : https://stackoverflow.com/questions/53370380/hotswapagent-incompatibleclasschangeerror-type-headerpanel1-is-not-a-nest-mem
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 8a262bc3735..9b6ba7e9304 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -178,6 +178,7 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
|
||||
}
|
||||
|
||||
Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
|
||||
+ k2 = k2->newest_version();
|
||||
if (k2 == k) {
|
||||
log_trace(class, nestmates)("- class is listed as a nest member");
|
||||
return true;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
26
jb/project/tools/patches/dcevm/0005-Use-init_mark_raw.patch
Normal file
26
jb/project/tools/patches/dcevm/0005-Use-init_mark_raw.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 90746a0267b2de4063667f5423093115f814bf08 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 10 Dec 2018 20:12:07 +0100
|
||||
Subject: [PATCH 05/48] Use init_mark_raw()
|
||||
|
||||
method changed since j8 - it used init_mark()
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 4394eff00c5..75d7e685edf 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -371,7 +371,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
} else {
|
||||
MarkSweep::update_fields(oop(cur_obj), oop(compaction_top));
|
||||
}
|
||||
- oop(compaction_top)->init_mark();
|
||||
+ oop(compaction_top)->init_mark_raw();
|
||||
assert(oop(compaction_top)->klass() != NULL, "should have a class");
|
||||
|
||||
debug_only(prev_obj = cur_obj);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
25
jb/project/tools/patches/dcevm/0006-Fix-methodHandles.patch
Normal file
25
jb/project/tools/patches/dcevm/0006-Fix-methodHandles.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 026346bfb72eaaae53e8998900d9f520da5ef74d Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 13 Dec 2018 20:51:09 +0100
|
||||
Subject: [PATCH 06/48] Fix methodHandles
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 61af07d0f86..1c7595787a1 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -248,7 +248,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
|
||||
if (MethodHandles::ref_kind_is_method(ref_kind)) {
|
||||
Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj);
|
||||
- if (m != NULL && m->method_holder()->new_version() != NULL) {
|
||||
+ if (m != NULL && m->method_holder()->is_redefining()) {
|
||||
// Let's try to re-resolve method
|
||||
InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version());
|
||||
Method* new_method = newest->find_method(m->name(), m->signature());
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
58
jb/project/tools/patches/dcevm/0007-Fix-field-method.patch
Normal file
58
jb/project/tools/patches/dcevm/0007-Fix-field-method.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From b99ebb71bce6119cd800d69848f84281f2fd2b16 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 15 Dec 2018 18:23:30 +0100
|
||||
Subject: [PATCH 07/48] Fix field method
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 19 ++++++++++++-------
|
||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 1c7595787a1..a3b65b273e5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -264,21 +264,26 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
}
|
||||
}
|
||||
} else if (MethodHandles::ref_kind_is_field(ref_kind)) {
|
||||
- Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj);
|
||||
+ oop clazz = java_lang_invoke_MemberName::clazz(obj);
|
||||
+ if (clazz == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
if (k == NULL) {
|
||||
return false; // Was cleared before, this MemberName is invalid.
|
||||
}
|
||||
|
||||
- if (k != NULL && k->new_version() != NULL) {
|
||||
+ if (k->is_redefining()) {
|
||||
// Let's try to re-resolve field
|
||||
+ InstanceKlass* old = InstanceKlass::cast(k->old_version());
|
||||
fieldDescriptor fd;
|
||||
int offset = java_lang_invoke_MemberName::vmindex(obj);
|
||||
bool is_static = MethodHandles::ref_kind_is_static(ref_kind);
|
||||
- InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
- if (ik->find_local_field_from_offset(offset, is_static, &fd)) {
|
||||
- InstanceKlass* newest = InstanceKlass::cast(k->newest_version());
|
||||
+ InstanceKlass* ik_old = InstanceKlass::cast(old);
|
||||
+ if (ik_old->find_local_field_from_offset(offset, is_static, &fd)) {
|
||||
+ InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version());
|
||||
fieldDescriptor fd_new;
|
||||
- if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
+ if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
Handle objHandle(Thread::current(), obj); // TODO : review thread
|
||||
MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind));
|
||||
} else {
|
||||
@@ -288,7 +293,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// Eventually, we probably want to replace them with something more meaningful,
|
||||
// like instance throwing NoSuchFieldError or DMH that will resort to dynamic
|
||||
// field resolution (with possibility of type conversion)
|
||||
- java_lang_invoke_MemberName::set_method(obj, NULL);
|
||||
+ java_lang_invoke_MemberName::set_clazz(obj, NULL);
|
||||
java_lang_invoke_MemberName::set_vmindex(obj, 0);
|
||||
return false;
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From dd57a1b40a83f7691c0fb9aa960f77c4428c0eec Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 15 Dec 2018 20:16:37 +0100
|
||||
Subject: [PATCH 08/48] Fix nonstatic field handles
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a3b65b273e5..c64d6bb1bb5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -337,6 +337,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (obj == NULL) {
|
||||
return;
|
||||
}
|
||||
+ bool oop_updated = false;
|
||||
if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) {
|
||||
Klass* klass = java_lang_Class::as_Klass(obj);
|
||||
if (klass != NULL && klass->is_instance_klass()) {
|
||||
@@ -344,13 +345,17 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (klass->new_version() != NULL) {
|
||||
obj = InstanceKlass::cast(klass->new_version())->java_mirror();
|
||||
S::oop_store(p, obj);
|
||||
+ oop_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
// JSR 292 support, uptade java.lang.invoke.MemberName instances
|
||||
if (java_lang_invoke_MemberName::is_instance(obj)) {
|
||||
- update_member_name(obj);
|
||||
+ if (oop_updated) {
|
||||
+ update_member_name(obj);
|
||||
+ }
|
||||
} else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) {
|
||||
if (!update_direct_method_handle(obj)) {
|
||||
// DMH is no longer valid, replace it with null reference.
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
From 333c0c639e12296d05a547b015c948516c8c504e Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 12 Dec 2018 19:38:28 +0100
|
||||
Subject: [PATCH 09/48] Support for Concurrent Mark Sweep (CMS) collector
|
||||
|
||||
---
|
||||
.../share/gc/cms/compactibleFreeListSpace.cpp | 139 ++++++++++++------
|
||||
.../share/gc/cms/compactibleFreeListSpace.hpp | 5 +-
|
||||
.../gc/cms/concurrentMarkSweepThread.cpp | 10 +-
|
||||
src/hotspot/share/gc/serial/markSweep.cpp | 2 +-
|
||||
src/hotspot/share/gc/shared/gcConfig.cpp | 2 +-
|
||||
src/hotspot/share/gc/shared/space.cpp | 16 +-
|
||||
src/hotspot/share/gc/shared/space.hpp | 6 +-
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 16 +-
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 12 +-
|
||||
src/hotspot/share/runtime/arguments.cpp | 6 +-
|
||||
10 files changed, 135 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
index a93f764f1b9..efaa09473a9 100644
|
||||
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
@@ -376,55 +376,58 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, M
|
||||
_used_stable = 0;
|
||||
}
|
||||
|
||||
+#define forward_compact_top_DEFN() \
|
||||
+ assert(this == cp->space, "'this' should be current compaction space."); \
|
||||
+ size_t compaction_max_size = pointer_delta(end(), compact_top); \
|
||||
+ assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), \
|
||||
+ "virtual adjustObjectSize_v() method is not correct"); \
|
||||
+ size_t adjusted_size = adjustObjectSize(size); \
|
||||
+ assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, \
|
||||
+ "no small fragments allowed"); \
|
||||
+ assert(minimum_free_block_size() == MinChunkSize, \
|
||||
+ "for de-virtualized reference below"); \
|
||||
+ /* Can't leave a nonzero size, residual fragment smaller than MinChunkSize */ \
|
||||
+ if (adjusted_size + MinChunkSize > compaction_max_size && \
|
||||
+ adjusted_size != compaction_max_size) { \
|
||||
+ do { \
|
||||
+ /* switch to next compaction space*/ \
|
||||
+ cp->space->set_compaction_top(compact_top); \
|
||||
+ cp->space = cp->space->next_compaction_space(); \
|
||||
+ if (cp->space == NULL) { \
|
||||
+ cp->gen = CMSHeap::heap()->young_gen(); \
|
||||
+ assert(cp->gen != NULL, "compaction must succeed"); \
|
||||
+ cp->space = cp->gen->first_compaction_space(); \
|
||||
+ assert(cp->space != NULL, "generation must have a first compaction space"); \
|
||||
+ } \
|
||||
+ compact_top = cp->space->bottom(); \
|
||||
+ cp->space->set_compaction_top(compact_top); \
|
||||
+ /* The correct adjusted_size may not be the same as that for this method */ \
|
||||
+ /* (i.e., cp->space may no longer be "this" so adjust the size again. */ \
|
||||
+ /* Use the virtual method which is not used above to save the virtual */ \
|
||||
+ /* dispatch. */ \
|
||||
+ adjusted_size = cp->space->adjust_object_size_v(size); \
|
||||
+ compaction_max_size = pointer_delta(cp->space->end(), compact_top); \
|
||||
+ assert(cp->space->minimum_free_block_size() == 0, "just checking"); \
|
||||
+ } while (adjusted_size > compaction_max_size); \
|
||||
+ }
|
||||
+
|
||||
+
|
||||
HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size,
|
||||
CompactPoint* cp, HeapWord* compact_top) {
|
||||
- ShouldNotReachHere();
|
||||
- return NULL;
|
||||
+ forward_compact_top_DEFN()
|
||||
+ return compact_top;
|
||||
}
|
||||
|
||||
// Like CompactibleSpace forward() but always calls cross_threshold() to
|
||||
// update the block offset table. Removed initialize_threshold call because
|
||||
// CFLS does not use a block offset array for contiguous spaces.
|
||||
HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
- // q is alive
|
||||
- // First check if we should switch compaction space
|
||||
- assert(this == cp->space, "'this' should be current compaction space.");
|
||||
- size_t compaction_max_size = pointer_delta(end(), compact_top);
|
||||
- assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size),
|
||||
- "virtual adjustObjectSize_v() method is not correct");
|
||||
- size_t adjusted_size = adjustObjectSize(size);
|
||||
- assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0,
|
||||
- "no small fragments allowed");
|
||||
- assert(minimum_free_block_size() == MinChunkSize,
|
||||
- "for de-virtualized reference below");
|
||||
- // Can't leave a nonzero size, residual fragment smaller than MinChunkSize
|
||||
- if (adjusted_size + MinChunkSize > compaction_max_size &&
|
||||
- adjusted_size != compaction_max_size) {
|
||||
- do {
|
||||
- // switch to next compaction space
|
||||
- cp->space->set_compaction_top(compact_top);
|
||||
- cp->space = cp->space->next_compaction_space();
|
||||
- if (cp->space == NULL) {
|
||||
- cp->gen = CMSHeap::heap()->young_gen();
|
||||
- assert(cp->gen != NULL, "compaction must succeed");
|
||||
- cp->space = cp->gen->first_compaction_space();
|
||||
- assert(cp->space != NULL, "generation must have a first compaction space");
|
||||
- }
|
||||
- compact_top = cp->space->bottom();
|
||||
- cp->space->set_compaction_top(compact_top);
|
||||
- // The correct adjusted_size may not be the same as that for this method
|
||||
- // (i.e., cp->space may no longer be "this" so adjust the size again.
|
||||
- // Use the virtual method which is not used above to save the virtual
|
||||
- // dispatch.
|
||||
- adjusted_size = cp->space->adjust_object_size_v(size);
|
||||
- compaction_max_size = pointer_delta(cp->space->end(), compact_top);
|
||||
- assert(cp->space->minimum_free_block_size() == 0, "just checking");
|
||||
- } while (adjusted_size > compaction_max_size);
|
||||
- }
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
+ forward_compact_top_DEFN()
|
||||
|
||||
// store the forwarding pointer into the mark word
|
||||
- if ((HeapWord*)q != compact_top) {
|
||||
+ // the size of object changed for: new_version() != NULL
|
||||
+ if (force_forward || (HeapWord*)q != compact_top || q->klass()->new_version() != NULL) {
|
||||
q->forward_to(oop(compact_top));
|
||||
assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
|
||||
} else {
|
||||
@@ -2196,13 +2199,60 @@ CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
|
||||
|
||||
// Support for compaction
|
||||
void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
|
||||
- scan_and_forward(this, cp, false);
|
||||
- // of the free lists doesn't work after.
|
||||
+ if (!Universe::is_redefining_gc_run()) {
|
||||
+ scan_and_forward(this, cp, false);
|
||||
+ } else {
|
||||
+ // Redefinition run
|
||||
+ scan_and_forward(this, cp, true);
|
||||
+ }
|
||||
// Prepare_for_compaction() uses the space between live objects
|
||||
// so that later phase can skip dead space quickly. So verification
|
||||
// of the free lists doesn't work after.
|
||||
}
|
||||
|
||||
+bool CompactibleFreeListSpace::must_rescue(oop old_obj, oop new_obj) {
|
||||
+ // Only redefined objects can have the need to be rescued.
|
||||
+ if (oop(old_obj)->klass()->new_version() == NULL) return false;
|
||||
+
|
||||
+ int new_size = adjustObjectSize(old_obj->size_given_klass(oop(old_obj)->klass()->new_version()));
|
||||
+ int original_size = adjustObjectSize(old_obj->size());
|
||||
+
|
||||
+ Generation* tenured_gen = CMSHeap::heap()->old_gen();
|
||||
+ bool old_in_tenured = tenured_gen->is_in_reserved(old_obj);
|
||||
+ bool new_in_tenured = tenured_gen->is_in_reserved(new_obj);
|
||||
+ if (old_in_tenured == new_in_tenured) {
|
||||
+ // Rescue if object may overlap with a higher memory address.
|
||||
+ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size);
|
||||
+ if (old_in_tenured) {
|
||||
+ // Old and new address are in same space, so just compare the address.
|
||||
+ // Must rescue if object moves towards the top of the space.
|
||||
+ assert(space_index(old_obj) == space_index(new_obj), "old_obj and new_obj must be in same space");
|
||||
+ } else {
|
||||
+ // In the new generation, eden is located before the from space, so a
|
||||
+ // simple pointer comparison is sufficient.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration");
|
||||
+ assert(overlap == (space_index(old_obj) < space_index(new_obj)), "slow and fast computation must yield same result");
|
||||
+ }
|
||||
+ return overlap;
|
||||
+
|
||||
+ } else {
|
||||
+ assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces");
|
||||
+ if (new_in_tenured) {
|
||||
+ // Must never rescue when moving from the new into the old generation.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
+ assert(space_index(old_obj) > space_index(new_obj), "must be");
|
||||
+ return false;
|
||||
+
|
||||
+ } else /* if (tenured_gen->is_in_reserved(old_obj)) */ {
|
||||
+ // Must always rescue when moving from the old into the new generation.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration");
|
||||
+ assert(space_index(old_obj) < space_index(new_obj), "must be");
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void CompactibleFreeListSpace::adjust_pointers() {
|
||||
// In other versions of adjust_pointers(), a bail out
|
||||
// based on the amount of live data in the generation
|
||||
@@ -2215,7 +2265,12 @@ void CompactibleFreeListSpace::adjust_pointers() {
|
||||
}
|
||||
|
||||
void CompactibleFreeListSpace::compact() {
|
||||
- scan_and_compact(this, false);
|
||||
+ if(!Universe::is_redefining_gc_run()) {
|
||||
+ scan_and_compact(this, false);
|
||||
+ } else {
|
||||
+ // Redefinition run
|
||||
+ scan_and_compact(this, true);
|
||||
+ }
|
||||
}
|
||||
|
||||
// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2]
|
||||
diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
index 9fd2ea58320..d29b81f6fca 100644
|
||||
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
@@ -201,7 +201,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||
// Support for compacting cms
|
||||
HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
|
||||
HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top);
|
||||
- HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top);
|
||||
+ HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top, bool force_forward);
|
||||
|
||||
// Initialization helpers.
|
||||
void initializeIndexedFreeListArray();
|
||||
@@ -576,6 +576,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||
|
||||
// Support for compaction.
|
||||
void prepare_for_compaction(CompactPoint* cp);
|
||||
+
|
||||
+ bool must_rescue(oop old_obj, oop new_obj);
|
||||
+
|
||||
void adjust_pointers();
|
||||
void compact();
|
||||
// Reset the space to reflect the fact that a compaction of the
|
||||
diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
index 3ada5755875..b6e930922d7 100644
|
||||
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
@@ -78,10 +78,12 @@ void ConcurrentMarkSweepThread::run_service() {
|
||||
while (!should_terminate()) {
|
||||
sleepBeforeNextCycle();
|
||||
if (should_terminate()) break;
|
||||
- GCIdMark gc_id_mark;
|
||||
- GCCause::Cause cause = _collector->_full_gc_requested ?
|
||||
- _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
|
||||
- _collector->collect_in_background(cause);
|
||||
+ if (!Universe::is_redefining_gc_run()) {
|
||||
+ GCIdMark gc_id_mark;
|
||||
+ GCCause::Cause cause = _collector->_full_gc_requested ?
|
||||
+ _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
|
||||
+ _collector->collect_in_background(cause);
|
||||
+ }
|
||||
}
|
||||
|
||||
// Check that the state of any protocol for synchronization
|
||||
diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
index d0ff86c8215..b4ed59f020c 100644
|
||||
--- a/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
+++ b/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
@@ -247,7 +247,7 @@ void MarkSweep::copy_rescued_objects_back() {
|
||||
|
||||
FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size);
|
||||
|
||||
- new_obj->init_mark();
|
||||
+ new_obj->init_mark_raw();
|
||||
assert(oopDesc::is_oop(new_obj), "must be a valid oop");
|
||||
}
|
||||
_rescued_oops->clear();
|
||||
diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
index 8aac2b39e1e..39364a64cb2 100644
|
||||
--- a/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
@@ -101,7 +101,7 @@ void GCConfig::fail_if_unsupported_gc_is_selected() {
|
||||
}
|
||||
|
||||
void GCConfig::select_gc_ergonomically() {
|
||||
- if (AllowEnhancedClassRedefinition) {
|
||||
+ if (AllowEnhancedClassRedefinition && !UseConcMarkSweepGC) {
|
||||
// Enhanced class redefinition only supports serial GC at the moment
|
||||
FLAG_SET_ERGO(bool, UseSerialGC, true);
|
||||
} else if (os::is_server_class_machine()) {
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 763abc91a39..947dff8ae0c 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -388,11 +388,11 @@ HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, H
|
||||
}
|
||||
|
||||
HeapWord* CompactibleSpace::forward(oop q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
compact_top = forward_compact_top(size, cp, compact_top);
|
||||
|
||||
// store the forwarding pointer into the mark word
|
||||
- if ((HeapWord*)q != compact_top || (size_t)q->size() != size) {
|
||||
+ if (force_forward || (HeapWord*)q != compact_top || (size_t)q->size() != size) {
|
||||
q->forward_to(oop(compact_top));
|
||||
assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
|
||||
} else {
|
||||
@@ -514,7 +514,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) {
|
||||
|
||||
} else {
|
||||
assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces");
|
||||
- if (tenured_gen->is_in_reserved(new_obj)) {
|
||||
+ if (new_in_tenured) {
|
||||
// Must never rescue when moving from the new into the old generation.
|
||||
assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
assert(space_index(old_obj) > space_index(new_obj), "must be");
|
||||
@@ -858,14 +858,14 @@ void OffsetTableContigSpace::verify() const {
|
||||
// Compute the forward sizes and leave out objects whose position could
|
||||
// possibly overlap other objects.
|
||||
HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
size_t forward_size = size;
|
||||
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) {
|
||||
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
- assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
forward_size = new_size;
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
return compact_top;
|
||||
}
|
||||
|
||||
- return forward(oop(q), forward_size, cp, compact_top);
|
||||
+ return forward(oop(q), forward_size, cp, compact_top, force_forward);
|
||||
}
|
||||
|
||||
// Compute the forwarding addresses for the objects that need to be rescued.
|
||||
@@ -895,11 +895,11 @@ HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
if (oop(q)->klass()->new_version() != NULL) {
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
- assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
size = new_size;
|
||||
}
|
||||
|
||||
- compact_top = cp->space->forward(oop(q), size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward(oop(q), size, cp, compact_top, true);
|
||||
assert(compact_top <= end(), "must not write over end of space!");
|
||||
}
|
||||
MarkSweep::_rescued_oops->clear();
|
||||
diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp
|
||||
index 8eb5669fb79..901c89d8a30 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.hpp
|
||||
@@ -421,7 +421,7 @@ public:
|
||||
virtual void prepare_for_compaction(CompactPoint* cp) = 0;
|
||||
// MarkSweep support phase3
|
||||
DEBUG_ONLY(int space_index(oop obj));
|
||||
- bool must_rescue(oop old_obj, oop new_obj);
|
||||
+ virtual bool must_rescue(oop old_obj, oop new_obj);
|
||||
HeapWord* rescue(HeapWord* old_obj);
|
||||
virtual void adjust_pointers();
|
||||
// MarkSweep support phase4
|
||||
@@ -452,11 +452,11 @@ public:
|
||||
// function of the then-current compaction space, and updates "cp->threshold
|
||||
// accordingly".
|
||||
virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp,
|
||||
- HeapWord* compact_top);
|
||||
+ HeapWord* compact_top, bool force_forward);
|
||||
// (DCEVM) same as forwad, but can rescue objects. Invoked only during
|
||||
// redefinition runs
|
||||
HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp,
|
||||
- HeapWord* compact_top);
|
||||
+ HeapWord* compact_top, bool force_forward);
|
||||
|
||||
HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top);
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 75d7e685edf..26e56ae6f7e 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -163,6 +163,8 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
HeapWord* cur_obj = space->bottom();
|
||||
HeapWord* scan_limit = space->scan_limit();
|
||||
|
||||
+ bool force_forward = false;
|
||||
+
|
||||
while (cur_obj < scan_limit) {
|
||||
assert(!space->scanned_block_is_obj(cur_obj) ||
|
||||
oop(cur_obj)->mark_raw()->is_marked() || oop(cur_obj)->mark_raw()->is_unlocked() ||
|
||||
@@ -174,14 +176,15 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
size_t size = space->scanned_block_size(cur_obj);
|
||||
|
||||
if (redefinition_run) {
|
||||
- compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top, force_forward);
|
||||
if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) {
|
||||
/* Was moved (otherwise, forward would reset mark),
|
||||
set first_dead to here */
|
||||
first_dead = cur_obj;
|
||||
+ force_forward = true;
|
||||
}
|
||||
} else {
|
||||
- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top, false);
|
||||
}
|
||||
|
||||
cur_obj += size;
|
||||
@@ -197,9 +200,9 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
|
||||
// see if we might want to pretend this object is alive so that
|
||||
// we don't have to compact quite as often.
|
||||
- if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) {
|
||||
+ if (!redefinition_run && cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) {
|
||||
oop obj = oop(cur_obj);
|
||||
- compact_top = cp->space->forward(obj, obj->size(), cp, compact_top);
|
||||
+ compact_top = cp->space->forward(obj, obj->size(), cp, compact_top, force_forward);
|
||||
end_of_live = end;
|
||||
} else {
|
||||
// otherwise, it really is a free region.
|
||||
@@ -351,7 +354,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
HeapWord* compaction_top = (HeapWord*)oop(cur_obj)->forwardee();
|
||||
|
||||
if (redefinition_run && space->must_rescue(oop(cur_obj), oop(cur_obj)->forwardee())) {
|
||||
- space->rescue(cur_obj);
|
||||
+ space->rescue(cur_obj);
|
||||
debug_only(Copy::fill_to_words(cur_obj, size, 0));
|
||||
cur_obj += size;
|
||||
continue;
|
||||
@@ -361,8 +364,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
Prefetch::write(compaction_top, copy_interval);
|
||||
|
||||
// copy object and reinit its mark
|
||||
- assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL,
|
||||
- "everything in this pass should be moving");
|
||||
+ assert(redefinition_run || cur_obj != compaction_top, "everything in this pass should be moving");
|
||||
if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) {
|
||||
Klass* new_version = oop(cur_obj)->klass()->new_version();
|
||||
if (new_version->update_information() == NULL) {
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index c64d6bb1bb5..9b8678a53fb 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "oops/constantPool.inline.hpp"
|
||||
+#include "gc/cms/cmsHeap.hpp"
|
||||
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_old_methods = NULL;
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_new_methods = NULL;
|
||||
@@ -420,13 +421,11 @@ public:
|
||||
Klass* new_klass = obj->klass()->new_version();
|
||||
|
||||
if (new_klass->update_information() != NULL) {
|
||||
- int size_diff = obj->size() - obj->size_given_klass(new_klass);
|
||||
-
|
||||
- // Either new size is bigger or gap is to small to be filled
|
||||
- if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) {
|
||||
+ if (obj->size() - obj->size_given_klass(new_klass) != 0) {
|
||||
// We need an instance update => set back to old klass
|
||||
_needs_instance_update = true;
|
||||
} else {
|
||||
+ // Either new size is bigger or gap is to small to be filled
|
||||
oop src = obj;
|
||||
if (new_klass->is_copying_backwards()) {
|
||||
copy_to_tmp(obj);
|
||||
@@ -436,11 +435,6 @@ public:
|
||||
// FIXME: instance updates...
|
||||
//guarantee(false, "instance updates!");
|
||||
MarkSweep::update_fields(obj, src, new_klass->update_information());
|
||||
-
|
||||
- if (size_diff > 0) {
|
||||
- HeapWord* dead_space = ((HeapWord *)obj) + obj->size();
|
||||
- CollectedHeap::fill_with_object(dead_space, size_diff);
|
||||
- }
|
||||
}
|
||||
} else {
|
||||
obj->set_klass(obj->klass()->new_version());
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index ca57b524593..2ca6dde069d 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -2047,14 +2047,14 @@ bool Arguments::check_gc_consistency() {
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
// Must use serial GC. This limitation applies because the instance size changing GC modifications
|
||||
// are only built into the mark and compact algorithm.
|
||||
- if (!UseSerialGC && i >= 1) {
|
||||
+ if ((!UseSerialGC && !UseConcMarkSweepGC) && i >= 1) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
- "Must use the serial GC with enhanced class redefinition\n");
|
||||
+ "Must use the serial or concurrent mark sweep GC with enhanced class redefinition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
- if (i > 1) {
|
||||
+ if (i > 2) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Conflicting collector combinations in option list; "
|
||||
"please refer to the release notes for the combinations "
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
257
jb/project/tools/patches/dcevm/0010-Code-cleanup.patch
Normal file
257
jb/project/tools/patches/dcevm/0010-Code-cleanup.patch
Normal file
@@ -0,0 +1,257 @@
|
||||
From b9ceda6f7c230750a87e8a686d833ce853d84712 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 13:22:29 +0100
|
||||
Subject: [PATCH 10/48] Code cleanup
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 125 ++++++------------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 3 -
|
||||
2 files changed, 40 insertions(+), 88 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 9b8678a53fb..0aa1ac4ff80 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
-#include "gc/serial/markSweep.hpp" // FIXME: other GC?
|
||||
+#include "gc/serial/markSweep.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "oops/klassVtable.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
@@ -485,7 +485,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
|
||||
// Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache)
|
||||
- flush_dependent_code(NULL, thread);
|
||||
+ //if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
+ flush_dependent_code(NULL, thread);
|
||||
+ //}
|
||||
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
@@ -593,17 +595,28 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// See jvmtiExport.hpp for detailed explanation.
|
||||
JvmtiExport::set_has_redefined_a_class();
|
||||
|
||||
- // check_class() is optionally called for product bits, but is
|
||||
- // always called for non-product bits.
|
||||
#ifdef PRODUCT
|
||||
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
#endif
|
||||
- log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
- CheckClass check_class(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&check_class);
|
||||
+ for (int i=0; i<_affected_klasses->length(); i++) {
|
||||
+ Klass* the_class = _affected_klasses->at(i);
|
||||
+ assert(the_class->new_version() != NULL, "Must have been redefined");
|
||||
+ Klass* new_version = the_class->new_version();
|
||||
+ assert(new_version->new_version() == NULL, "Must be newest version");
|
||||
+
|
||||
+ if (!(new_version->super() == NULL || new_version->super()->new_version() == NULL)) {
|
||||
+ new_version->print();
|
||||
+ new_version->super()->print();
|
||||
+ }
|
||||
+ assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version");
|
||||
+ }
|
||||
+ log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
+ CheckClass check_class(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&check_class);
|
||||
#ifdef PRODUCT
|
||||
}
|
||||
#endif
|
||||
+
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1279,24 +1292,23 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
GrowableArray<int> result = cl.finish();
|
||||
ik->store_update_information(result);
|
||||
ik->set_copying_backwards(cl.does_copy_backwards());
|
||||
-/* TODO logging
|
||||
- if (RC_TRACE_ENABLED(0x00000001)) {
|
||||
- RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string()));
|
||||
+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
+ log_trace(redefine, class, obsolete, metadata)("Instance update information for %s:", new_version->name()->as_C_string());
|
||||
if (cl.does_copy_backwards()) {
|
||||
- RC_TRACE(0x00000001, ("\tDoes copy backwards!"));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\tDoes copy backwards!");
|
||||
}
|
||||
for (int i=0; i<result.length(); i++) {
|
||||
int curNum = result.at(i);
|
||||
if (curNum < 0) {
|
||||
- RC_TRACE(0x00000001, ("\t%d CLEAN", curNum));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\t%d CLEAN", curNum);
|
||||
} else if (curNum > 0) {
|
||||
- RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1)));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\t%d COPY from %d", curNum, result.at(i + 1));
|
||||
i++;
|
||||
} else {
|
||||
- RC_TRACE(0x00000001, ("\tEND"));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\tEND");
|
||||
}
|
||||
}
|
||||
- }*/
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1813,6 +1825,7 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
/**
|
||||
FIXME - swap_annotations is never called, check that annotations work
|
||||
*/
|
||||
+// TODO : delete it
|
||||
void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
InstanceKlass* new_class) {
|
||||
// FIXME - probably original implementation only
|
||||
@@ -1822,7 +1835,6 @@ void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
new_class->set_annotations(old_annotations);
|
||||
}
|
||||
|
||||
-
|
||||
// Install the redefinition of a class:
|
||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||
// dependent compiled code)
|
||||
@@ -1853,7 +1865,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
|
||||
// DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined
|
||||
// Deoptimize all compiled code that depends on this class
|
||||
- // flush_dependent_code(the_class, THREAD);
|
||||
+ //if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
+ //flush_dependent_code(the_class, THREAD);
|
||||
+ //}
|
||||
|
||||
_old_methods = the_class->methods();
|
||||
_new_methods = new_class->methods();
|
||||
@@ -1928,64 +1942,15 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
}
|
||||
}
|
||||
|
||||
-// FIXME - class check is currently disabled
|
||||
void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
- return;
|
||||
- bool no_old_methods = true; // be optimistic
|
||||
-
|
||||
- // Both array and instance classes have vtables.
|
||||
- // a vtable should never contain old or obsolete methods
|
||||
- ResourceMark rm(_thread);
|
||||
- if (k->vtable_length() > 0 &&
|
||||
- !k->vtable().check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- k->signature_name());
|
||||
- k->vtable().dump_vtable();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
-
|
||||
- if (k->is_instance_klass()) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
+ HandleMark hm(_thread);
|
||||
+ InstanceKlass *ik = (InstanceKlass *) k;
|
||||
+ assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
|
||||
- // an itable should never contain old or obsolete methods
|
||||
- if (ik->itable_length() > 0 &&
|
||||
- !ik->itable().check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- ik->signature_name());
|
||||
- ik->itable().dump_itable();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
-
|
||||
- // the constant pool cache should never contain non-deleted old or obsolete methods
|
||||
- if (ik->constants() != NULL &&
|
||||
- ik->constants()->cache() != NULL &&
|
||||
- !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- ik->signature_name());
|
||||
- ik->constants()->cache()->dump_cache();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // print and fail guarantee if old methods are found.
|
||||
- if (!no_old_methods) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- dump_methods();
|
||||
- } else {
|
||||
- log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option "
|
||||
- "to see more info about the following guarantee() failure.");
|
||||
- }
|
||||
- guarantee(false, "OLD and/or OBSOLETE method(s) found");
|
||||
+ if (ik->vtable_length() > 0) {
|
||||
+ ResourceMark rm(_thread);
|
||||
+ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
+ ik->vtable().verify(tty, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2051,15 +2016,6 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
}
|
||||
|
||||
-// TODO - is it called anywhere?
|
||||
-void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const {
|
||||
- VM_Operation::print_on_error(st);
|
||||
- if (_the_class_oop != NULL) {
|
||||
- ResourceMark rm;
|
||||
- st->print_cr(", redefining class %s", _the_class_oop->external_name());
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/**
|
||||
Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
*/
|
||||
@@ -2093,7 +2049,7 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string());
|
||||
klass->set_redefinition_flag(Klass::MarkedAsAffected);
|
||||
_affected_klasses->append(klass);
|
||||
- return;
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2125,7 +2081,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
|
||||
// Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined)
|
||||
AffectedKlassClosure closure(_affected_klasses);
|
||||
- // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure);
|
||||
+ // Updated in j10, from original SystemDictionary::classes_do
|
||||
ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
@@ -2160,7 +2116,6 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
-
|
||||
For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
|
||||
TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index b712d69a193..37e63a1810f 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -195,8 +195,5 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// Modifiable test must be shared between IsModifiableClass query
|
||||
// and redefine implementation
|
||||
static bool is_modifiable_class(oop klass_mirror);
|
||||
-
|
||||
- // Error printing
|
||||
- void print_on_error(outputStream* st) const;
|
||||
};
|
||||
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
118
jb/project/tools/patches/dcevm/0011-Fix-check_class.patch
Normal file
118
jb/project/tools/patches/dcevm/0011-Fix-check_class.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 1d147a5db94b531fa027d5e13e4dd5cbaef62952 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 16:05:25 +0100
|
||||
Subject: [PATCH 11/48] Fix check_class
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 39 +++++++------------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 5 +--
|
||||
2 files changed, 16 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 0aa1ac4ff80..c08b3e82b2e 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1,4 +1,4 @@
|
||||
-/*
|
||||
+ /*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/verifier.hpp"
|
||||
+#include "classfile/dictionary.hpp"
|
||||
#include "interpreter/oopMapCache.hpp"
|
||||
#include "interpreter/rewriter.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@@ -611,8 +612,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version");
|
||||
}
|
||||
log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
- CheckClass check_class(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&check_class);
|
||||
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do(check_class, thread);
|
||||
#ifdef PRODUCT
|
||||
}
|
||||
#endif
|
||||
@@ -1822,19 +1822,6 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity");
|
||||
}
|
||||
|
||||
-/**
|
||||
- FIXME - swap_annotations is never called, check that annotations work
|
||||
-*/
|
||||
-// TODO : delete it
|
||||
-void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
- InstanceKlass* new_class) {
|
||||
- // FIXME - probably original implementation only
|
||||
- // Swap annotation fields values
|
||||
- Annotations* old_annotations = the_class->annotations();
|
||||
- the_class->set_annotations(new_class->annotations());
|
||||
- new_class->set_annotations(old_annotations);
|
||||
-}
|
||||
-
|
||||
// Install the redefinition of a class:
|
||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||
// dependent compiled code)
|
||||
@@ -1942,15 +1929,17 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
}
|
||||
}
|
||||
|
||||
-void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = (InstanceKlass *) k;
|
||||
- assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
+void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
+ if (ik->is_instance_klass() && ik->old_version() != NULL) {
|
||||
+ HandleMark hm(THREAD);
|
||||
+
|
||||
+ assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
|
||||
- if (ik->vtable_length() > 0) {
|
||||
- ResourceMark rm(_thread);
|
||||
- assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
- ik->vtable().verify(tty, true);
|
||||
+ if (ik->vtable_length() > 0) {
|
||||
+ ResourceMark rm(THREAD);
|
||||
+ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
+ ik->vtable().verify(tty, true);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2017,7 +2006,7 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
|
||||
/**
|
||||
- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
+ Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
*/
|
||||
class AffectedKlassClosure : public KlassClosure {
|
||||
private:
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 37e63a1810f..5b3ebc13661 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -144,15 +144,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// Install the redefinition of a class
|
||||
void redefine_single_class(InstanceKlass* new_class_oop, TRAPS);
|
||||
|
||||
- void swap_annotations(InstanceKlass* new_class,
|
||||
- InstanceKlass* scratch_class);
|
||||
-
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
||||
|
||||
void flush_dependent_code(InstanceKlass* k_h, TRAPS);
|
||||
|
||||
+ static void check_class(InstanceKlass* k_oop, TRAPS);
|
||||
+
|
||||
static void dump_methods();
|
||||
|
||||
// Check that there are no old or obsolete methods
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 84777c09ddbbbbd6a90de5b1f17a4101c8f076b8 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 17:58:39 +0100
|
||||
Subject: [PATCH 12/48] Fix force_forward in dead space
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 26e56ae6f7e..8c255d6d428 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -213,6 +213,7 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
// see if this is the first dead region.
|
||||
if (first_dead == NULL) {
|
||||
first_dead = cur_obj;
|
||||
+ force_forward = true;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
25
jb/project/tools/patches/dcevm/0013-Cleanup.patch
Normal file
25
jb/project/tools/patches/dcevm/0013-Cleanup.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 4d973861fbcd13dc50bd603f731c75d2013034c6 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 1 Mar 2019 18:45:13 +0100
|
||||
Subject: [PATCH 13/48] Cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 947dff8ae0c..56b144b46f1 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -862,7 +862,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
size_t forward_size = size;
|
||||
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
- if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) {
|
||||
+ if (oop(q)->klass()->new_version() != NULL) {
|
||||
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
// assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From 5f31460556d86fa0233e7998112a65483034fd45 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 17:38:27 +0100
|
||||
Subject: [PATCH 14/48] Add codecache flush optimization, but just flush all
|
||||
cache.
|
||||
|
||||
Redefined class can define a new method that overrides
|
||||
method in superclass which is already used in codecache for
|
||||
optimized non-virtual calls, etc...
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++++------
|
||||
1 file changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index c08b3e82b2e..4ca638548dc 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -486,9 +486,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
|
||||
// Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache)
|
||||
- //if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
+ // if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
flush_dependent_code(NULL, thread);
|
||||
- //}
|
||||
+ // }
|
||||
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
@@ -1736,8 +1736,14 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
// All dependencies have been recorded from startup or this is a second or
|
||||
// subsequent use of RedefineClasses
|
||||
// FIXME: for now, deoptimize all!
|
||||
- if (0 && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
+ if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
CodeCache::flush_evol_dependents_on(k_h);
|
||||
+ Klass* superCl = k_h->super();
|
||||
+ // Deoptimize super classes since redefined class can has a new method override
|
||||
+ while (superCl != NULL && !superCl->is_redefining()) {
|
||||
+ CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl));
|
||||
+ superCl = superCl->super();
|
||||
+ }
|
||||
} else {
|
||||
CodeCache::mark_all_nmethods_for_deoptimization();
|
||||
|
||||
@@ -1852,9 +1858,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
|
||||
// DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined
|
||||
// Deoptimize all compiled code that depends on this class
|
||||
- //if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
- //flush_dependent_code(the_class, THREAD);
|
||||
- //}
|
||||
+// if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
+// flush_dependent_code(the_class, THREAD);
|
||||
+// }
|
||||
|
||||
_old_methods = the_class->methods();
|
||||
_new_methods = new_class->methods();
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
From d457702275bc47f3f9ea416dc794be403bc6eb94 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:20:08 +0100
|
||||
Subject: [PATCH 15/48] HotswapAgent integration
|
||||
|
||||
It include:
|
||||
|
||||
- option to compile DCEVM only version with -DDCEVM_ONLY added
|
||||
to CFLAGS (bash configure --with-extra-cflags="-DDCEVM_ONLY"), by
|
||||
default compilation goes with HotswapAgent
|
||||
|
||||
Add --add-opens for necessary modules/packages
|
||||
- java.base/java.lang - for reflection access to Proxy.proxyCache
|
||||
- java.base/jdk.internal.loader - for access proxyCache class
|
||||
- java.desktop/java.beans - for reflection access to Introspector
|
||||
|
||||
- be quiet if HotswapAgent is not found in lib/, it is compatible with
|
||||
old DCEVM
|
||||
- disable hotswapagent for -Xshare:dump
|
||||
- disable HotswapAgent in jvm tools
|
||||
---
|
||||
make/launcher/Launcher-java.rmi.gmk | 2 +
|
||||
make/launcher/Launcher-java.scripting.gmk | 3 +-
|
||||
make/launcher/Launcher-java.security.jgss.gmk | 3 +
|
||||
make/launcher/Launcher-jdk.aot.gmk | 2 +
|
||||
make/launcher/Launcher-jdk.compiler.gmk | 5 +-
|
||||
make/launcher/Launcher-jdk.hotspot.agent.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jartool.gmk | 2 +
|
||||
make/launcher/Launcher-jdk.javadoc.gmk | 3 +-
|
||||
make/launcher/Launcher-jdk.jcmd.gmk | 13 +++-
|
||||
make/launcher/Launcher-jdk.jconsole.gmk | 3 +-
|
||||
make/launcher/Launcher-jdk.jdeps.gmk | 3 +
|
||||
make/launcher/Launcher-jdk.jdi.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jlink.gmk | 5 +-
|
||||
make/launcher/Launcher-jdk.jshell.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jstatd.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.pack.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.rmic.gmk | 1 +
|
||||
.../Launcher-jdk.scripting.nashorn.shell.gmk | 3 +-
|
||||
src/hotspot/share/runtime/arguments.cpp | 59 +++++++++++++++++++
|
||||
src/hotspot/share/runtime/arguments.hpp | 3 +
|
||||
src/hotspot/share/runtime/globals.hpp | 12 +++-
|
||||
21 files changed, 117 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/make/launcher/Launcher-java.rmi.gmk b/make/launcher/Launcher-java.rmi.gmk
|
||||
index a69a90bcc81..07046232275 100644
|
||||
--- a/make/launcher/Launcher-java.rmi.gmk
|
||||
+++ b/make/launcher/Launcher-java.rmi.gmk
|
||||
@@ -27,8 +27,10 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmid, \
|
||||
MAIN_CLASS := sun.rmi.server.Activation, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmiregistry, \
|
||||
MAIN_CLASS := sun.rmi.registry.RegistryImpl, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-java.scripting.gmk b/make/launcher/Launcher-java.scripting.gmk
|
||||
index 057d2bf3aca..cf100e20789 100644
|
||||
--- a/make/launcher/Launcher-java.scripting.gmk
|
||||
+++ b/make/launcher/Launcher-java.scripting.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jrunscript, \
|
||||
MAIN_CLASS := com.sun.tools.script.shell.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-java.security.jgss.gmk b/make/launcher/Launcher-java.security.jgss.gmk
|
||||
index 7411e1a21c4..2b856bfccb4 100644
|
||||
--- a/make/launcher/Launcher-java.security.jgss.gmk
|
||||
+++ b/make/launcher/Launcher-java.security.jgss.gmk
|
||||
@@ -28,13 +28,16 @@ include LauncherCommon.gmk
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
$(eval $(call SetupBuildLauncher, kinit, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, klist, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, ktab, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
endif
|
||||
diff --git a/make/launcher/Launcher-jdk.aot.gmk b/make/launcher/Launcher-jdk.aot.gmk
|
||||
index 10717a5e1c5..2c52c31a555 100644
|
||||
--- a/make/launcher/Launcher-jdk.aot.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.aot.gmk
|
||||
@@ -31,6 +31,7 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, jaotc, \
|
||||
MAIN_CLASS := jdk.tools.jaotc.Main, \
|
||||
EXTRA_JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \
|
||||
+ -XX:+DisableHotswapAgent \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
@@ -40,6 +41,7 @@ $(eval $(call SetupBuildLauncher, jaotc, \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
, \
|
||||
JAVA_ARGS := --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
+ -XX:+DisableHotswapAgent \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
diff --git a/make/launcher/Launcher-jdk.compiler.gmk b/make/launcher/Launcher-jdk.compiler.gmk
|
||||
index f71c37adf74..744969546de 100644
|
||||
--- a/make/launcher/Launcher-jdk.compiler.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.compiler.gmk
|
||||
@@ -27,12 +27,14 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javac, \
|
||||
MAIN_CLASS := com.sun.tools.javac.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, serialver, \
|
||||
MAIN_CLASS := sun.tools.serialver.SerialVer, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
@@ -41,6 +43,7 @@ ifeq ($(ENABLE_SJAVAC), yes)
|
||||
# into any real images
|
||||
$(eval $(call SetupBuildLauncher, sjavac, \
|
||||
MAIN_CLASS := com.sun.tools.sjavac.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.hotspot.agent.gmk b/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
index 76da3600368..9f12b05b172 100644
|
||||
--- a/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jhsdb, \
|
||||
MAIN_CLASS := sun.jvm.hotspot.SALauncher, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jartool.gmk b/make/launcher/Launcher-jdk.jartool.gmk
|
||||
index f74e82bfdae..647d82b65b1 100644
|
||||
--- a/make/launcher/Launcher-jdk.jartool.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jartool.gmk
|
||||
@@ -27,8 +27,10 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jar, \
|
||||
MAIN_CLASS := sun.tools.jar.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jarsigner, \
|
||||
MAIN_CLASS := sun.security.tools.jarsigner.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.javadoc.gmk b/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
index 889028a2b17..c3d2093be04 100644
|
||||
--- a/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javadoc, \
|
||||
MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jcmd.gmk b/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
index 7117fa78059..761a52d8466 100644
|
||||
--- a/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
@@ -30,6 +30,7 @@ $(eval $(call SetupBuildLauncher, jinfo, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
-Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
@@ -37,28 +38,36 @@ $(eval $(call SetupBuildLauncher, jmap, \
|
||||
MAIN_CLASS := sun.tools.jmap.JMap, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
- -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jps, \
|
||||
MAIN_CLASS := sun.tools.jps.Jps, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstack, \
|
||||
MAIN_CLASS := sun.tools.jstack.JStack, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
- -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstat, \
|
||||
MAIN_CLASS := sun.tools.jstat.Jstat, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jcmd, \
|
||||
MAIN_CLASS := sun.tools.jcmd.JCmd, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
diff --git a/make/launcher/Launcher-jdk.jconsole.gmk b/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
index 6205ae63d16..5ca6a0c123b 100644
|
||||
--- a/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
@@ -28,7 +28,8 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, jconsole, \
|
||||
MAIN_CLASS := sun.tools.jconsole.JConsole, \
|
||||
JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \
|
||||
- -Djconsole.showOutputViewer, \
|
||||
+ -Djconsole.showOutputViewer \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS_windows := -DJAVAW, \
|
||||
LIBS_windows := user32.lib, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jdeps.gmk b/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
index 217523c48cc..5448278dae7 100644
|
||||
--- a/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
@@ -27,15 +27,18 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javap, \
|
||||
MAIN_CLASS := com.sun.tools.javap.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdeps, \
|
||||
MAIN_CLASS := com.sun.tools.jdeps.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdeprscan, \
|
||||
MAIN_CLASS := com.sun.tools.jdeprscan.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jdi.gmk b/make/launcher/Launcher-jdk.jdi.gmk
|
||||
index fcce98cf430..27bd448e3ae 100644
|
||||
--- a/make/launcher/Launcher-jdk.jdi.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jdi.gmk
|
||||
@@ -27,4 +27,5 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdb, \
|
||||
MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jlink.gmk b/make/launcher/Launcher-jdk.jlink.gmk
|
||||
index df2173996d7..9e61edeb2c8 100644
|
||||
--- a/make/launcher/Launcher-jdk.jlink.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jlink.gmk
|
||||
@@ -27,18 +27,21 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jimage,\
|
||||
MAIN_CLASS := jdk.tools.jimage.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jlink,\
|
||||
MAIN_CLASS := jdk.tools.jlink.internal.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES \
|
||||
-DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jmod,\
|
||||
MAIN_CLASS := jdk.tools.jmod.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES \
|
||||
-DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jshell.gmk b/make/launcher/Launcher-jdk.jshell.gmk
|
||||
index 349eb88e9eb..7287f8f998a 100644
|
||||
--- a/make/launcher/Launcher-jdk.jshell.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jshell.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jshell, \
|
||||
MAIN_CLASS := jdk.internal.jshell.tool.JShellToolProvider, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jstatd.gmk b/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
index e9286d63094..e1657910c67 100644
|
||||
--- a/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstatd, \
|
||||
MAIN_CLASS := sun.tools.jstatd.Jstatd, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk
|
||||
index a93fd2a9017..64bbbb7c949 100644
|
||||
--- a/make/launcher/Launcher-jdk.pack.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.pack.gmk
|
||||
@@ -28,6 +28,7 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, pack200, \
|
||||
MAIN_MODULE := java.base, \
|
||||
MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
diff --git a/make/launcher/Launcher-jdk.rmic.gmk b/make/launcher/Launcher-jdk.rmic.gmk
|
||||
index d60c3d9b60b..b8a55900b0e 100644
|
||||
--- a/make/launcher/Launcher-jdk.rmic.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.rmic.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmic, \
|
||||
MAIN_CLASS := sun.rmi.rmic.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
index 82311e69fd6..bd39f8595b2 100644
|
||||
--- a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jjs, \
|
||||
MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 2ca6dde069d..c75bb5d8f49 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -3937,6 +3937,8 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
||||
// Set object alignment values.
|
||||
set_object_alignment();
|
||||
|
||||
+ setup_hotswap_agent();
|
||||
+
|
||||
#if !INCLUDE_CDS
|
||||
if (DumpSharedSpaces || RequireSharedSpaces) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
@@ -4270,3 +4272,60 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen,
|
||||
*b = '\0';
|
||||
return (p == src_end); // return false if not all of the source was copied
|
||||
}
|
||||
+
|
||||
+void Arguments::setup_hotswap_agent() {
|
||||
+
|
||||
+ if (DumpSharedSpaces)
|
||||
+ return;
|
||||
+
|
||||
+ if (!AllowEnhancedClassRedefinition)
|
||||
+ return;
|
||||
+
|
||||
+ // Set HotswapAgent
|
||||
+ if (!DisableHotswapAgent) {
|
||||
+
|
||||
+ char ext_path_str[JVM_MAXPATHLEN];
|
||||
+
|
||||
+ os::jvm_path(ext_path_str, sizeof(ext_path_str));
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ char *end = strrchr(ext_path_str, *os::file_separator());
|
||||
+ if (end != NULL) *end = '\0';
|
||||
+ }
|
||||
+ size_t ext_path_length = strlen(ext_path_str);
|
||||
+ if (ext_path_length >= 3) {
|
||||
+ if (strcmp(ext_path_str + ext_path_length - 3, "lib") != 0) {
|
||||
+ if (ext_path_length < JVM_MAXPATHLEN - 4) {
|
||||
+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, "%slib", os::file_separator());
|
||||
+ ext_path_length += 4;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (ext_path_length < JVM_MAXPATHLEN - 10) {
|
||||
+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length,
|
||||
+ "%shotswap%shotswap-agent.jar", os::file_separator(), os::file_separator());
|
||||
+ }
|
||||
+
|
||||
+ int fd = ::open(ext_path_str, O_RDONLY);
|
||||
+ if (fd >= 0) {
|
||||
+ os::close(fd);
|
||||
+ size_t length = strlen(ext_path_str) + 1;
|
||||
+ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
|
||||
+ jio_snprintf(options, length, "%s", ext_path_str);
|
||||
+ add_init_agent("instrument", ext_path_str, false);
|
||||
+ jio_fprintf(defaultStream::output_stream(), "Starting HotswapAgent '%s'\n", ext_path_str);
|
||||
+ }
|
||||
+// else
|
||||
+// {
|
||||
+// jio_fprintf(defaultStream::error_stream(), "HotswapAgent not found on path:'%s'\n", ext_path_str);
|
||||
+// }
|
||||
+ }
|
||||
+
|
||||
+ // TODO: open it only for org.hotswap.agent module
|
||||
+ // Use to access java.lang.reflect.Proxy/proxyCache
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
||||
+ // Class of field java.lang.reflect.Proxy/proxyCache
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
+ // java.beans.Introspector access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
+
|
||||
+}
|
||||
diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp
|
||||
index 46450cce5c9..3dc5b3d4bae 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.hpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.hpp
|
||||
@@ -506,6 +506,9 @@ class Arguments : AllStatic {
|
||||
|
||||
static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; }
|
||||
|
||||
+ // Initialize HotswapAgent
|
||||
+ static void setup_hotswap_agent();
|
||||
+
|
||||
// Return the maximum size a heap with compressed oops can take
|
||||
static size_t max_heap_for_compressed_oops();
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
|
||||
index f3cf08fffb6..5f6c7b8e388 100644
|
||||
--- a/src/hotspot/share/runtime/globals.hpp
|
||||
+++ b/src/hotspot/share/runtime/globals.hpp
|
||||
@@ -32,6 +32,12 @@
|
||||
|
||||
#include <float.h> // for DBL_MAX
|
||||
|
||||
+#ifdef DCEVM_ONLY
|
||||
+#define DISABLED_HOTSWAP_AGENT true
|
||||
+#else
|
||||
+#define DISABLED_HOTSWAP_AGENT false
|
||||
+#endif
|
||||
+
|
||||
// The larger HeapWordSize for 64bit requires larger heaps
|
||||
// for the same application running in 64bit. See bug 4967770.
|
||||
// The minimum alignment to a heap word size is done. Other
|
||||
@@ -2675,8 +2681,10 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
|
||||
\
|
||||
product(bool, AllowEnhancedClassRedefinition, true, \
|
||||
"Allow enhanced class redefinition beyond swapping method " \
|
||||
- "bodies")
|
||||
-
|
||||
+ "bodies") \
|
||||
+ \
|
||||
+ product(bool, DisableHotswapAgent, DISABLED_HOTSWAP_AGENT, \
|
||||
+ "Disable integrated Hotswap Agent (HotswapVM only)")
|
||||
#define VM_FLAGS(develop, \
|
||||
develop_pd, \
|
||||
product, \
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From 603b446449aa715aa3f409fb49ed00169b89fd91 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 16 Dec 2018 09:55:31 +0100
|
||||
Subject: [PATCH 16/48] Add dcevm distro name
|
||||
|
||||
---
|
||||
make/autoconf/version-numbers | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers
|
||||
index b5a23138213..5c0a3242c80 100644
|
||||
--- a/make/autoconf/version-numbers
|
||||
+++ b/make/autoconf/version-numbers
|
||||
@@ -43,7 +43,7 @@ PRODUCT_NAME=OpenJDK
|
||||
PRODUCT_SUFFIX="Runtime Environment"
|
||||
JDK_RC_PLATFORM_NAME=Platform
|
||||
COMPANY_NAME=N/A
|
||||
-HOTSPOT_VM_DISTRO="OpenJDK"
|
||||
+HOTSPOT_VM_DISTRO="Dynamic Code Evolution"
|
||||
|
||||
# Might need better names for these
|
||||
MACOSX_BUNDLE_NAME_BASE="OpenJDK"
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 6869b6f67f8c8db57d91ea0ef9f33aaf44def1db Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 Nov 2019 19:58:27 +0100
|
||||
Subject: [PATCH 17/48] java.desktop/com.sun.beans=ALL-UNNAMED
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index c75bb5d8f49..ba6e78d6daa 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4327,5 +4327,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
+ // java.beans.Introspector access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
From bbcbaa9d5814017565b8f7f0d86844e9f64905c1 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 Nov 2019 21:07:59 +0100
|
||||
Subject: [PATCH 18/48] increment_class_counter() using orig dcevm code
|
||||
|
||||
Probably it is cause of SISEGV on:
|
||||
_
|
||||
VM_EnhancedRedefineClasses::redefine_single_class->java_mirror()
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 39 ++++++-------------
|
||||
1 file changed, 12 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 4ca638548dc..efb9e806508 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1146,9 +1146,9 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
}
|
||||
|
||||
|
||||
-/**
|
||||
+/**
|
||||
Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
-
|
||||
+
|
||||
@param the_class definition of a class, either existing class or new_class
|
||||
@param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
@param class_byte_count - size of class_bytes
|
||||
@@ -1460,7 +1460,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
//
|
||||
// ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
// }
|
||||
-
|
||||
+
|
||||
constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
|
||||
// Update host klass of anonymous classes (for example, produced by lambdas) to newest version.
|
||||
@@ -1764,7 +1764,7 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
/**
|
||||
Compare _old_methods and _new_methods arrays and store the result into
|
||||
_matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
-
|
||||
+
|
||||
Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
*/
|
||||
void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
@@ -1898,13 +1898,13 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
ResourceMark rm(THREAD);
|
||||
// increment the classRedefinedCount field in the_class and in any
|
||||
// direct and indirect subclasses of the_class
|
||||
- increment_class_counter(the_class, THREAD);
|
||||
+ increment_class_counter(new_class, THREAD);
|
||||
log_info(redefine, class, load)
|
||||
("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
|
||||
- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10);
|
||||
+ new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), os::available_memory() >> 10);
|
||||
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
|
||||
- the_class->external_name(),
|
||||
- java_lang_Class::classRedefinedCount(the_class->java_mirror()));
|
||||
+ new_class->external_name(),
|
||||
+ java_lang_Class::classRedefinedCount(new_class->java_mirror()));
|
||||
|
||||
}
|
||||
_timer_rsc_phase2.stop();
|
||||
@@ -1914,25 +1914,10 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) {
|
||||
- oop class_mirror = ik->java_mirror();
|
||||
+ oop class_mirror = ik->old_version()->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
- java_lang_Class::set_classRedefinedCount(ik->new_version()->java_mirror(), new_count);
|
||||
-
|
||||
- if (class_oop != _the_class_oop) {
|
||||
- // _the_class_oop count is printed at end of redefine_single_class()
|
||||
- log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
|
||||
- }
|
||||
-
|
||||
- for (Klass *subk = ik->subklass(); subk != NULL;
|
||||
- subk = subk->next_sibling()) {
|
||||
- if (subk->is_instance_klass()) {
|
||||
- // Only update instanceKlasses
|
||||
- InstanceKlass *subik = InstanceKlass::cast(subk);
|
||||
- // recursively do subclasses of the current subclass
|
||||
- increment_class_counter(subik, THREAD);
|
||||
- }
|
||||
- }
|
||||
+ java_lang_Class::set_classRedefinedCount(ik->java_mirror(), new_count);
|
||||
}
|
||||
|
||||
void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
@@ -2063,7 +2048,7 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
|
||||
/**
|
||||
Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
- Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
+ Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
*/
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
for (int i = 0; i < _class_count; i++) {
|
||||
@@ -2112,7 +2097,7 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
-
|
||||
+
|
||||
TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
*/
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
From 62c65c226bbc4fadbc598db1a2ac7d05d17ae731 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 21 Nov 2019 19:30:07 +0100
|
||||
Subject: [PATCH 19/48] Allow 11715ha class initializer calls
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/vmSymbols.hpp | 1 +
|
||||
src/hotspot/share/interpreter/linkResolver.cpp | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
index e2bac31b27f..6eeda3b8f68 100644
|
||||
--- a/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
+++ b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
@@ -340,6 +340,7 @@
|
||||
/* common method and field names */ \
|
||||
template(object_initializer_name, "<init>") \
|
||||
template(class_initializer_name, "<clinit>") \
|
||||
+ template(ha_class_initializer_name, "$$ha$clinit") \
|
||||
template(println_name, "println") \
|
||||
template(printStackTrace_name, "printStackTrace") \
|
||||
template(main_name, "main") \
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index b9ccdee8cca..cb76d2ef50c 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -1009,7 +1009,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||
assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
|
||||
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
|
||||
fd.is_static() &&
|
||||
- !m()->is_static_initializer());
|
||||
+ !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name()));
|
||||
bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
|
||||
!fd.is_static() &&
|
||||
!m->is_object_initializer());
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 88b6f7a27e35d9ed3b82418b82c1cb1fe14f61e6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 26 Nov 2019 22:13:07 +0100
|
||||
Subject: [PATCH 20/48] Disable HA in keytool
|
||||
|
||||
---
|
||||
make/launcher/Launcher-java.base.gmk | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/make/launcher/Launcher-java.base.gmk b/make/launcher/Launcher-java.base.gmk
|
||||
index 5ee4530004b..88c1a14b2aa 100644
|
||||
--- a/make/launcher/Launcher-java.base.gmk
|
||||
+++ b/make/launcher/Launcher-java.base.gmk
|
||||
@@ -63,6 +63,7 @@ endif
|
||||
|
||||
$(eval $(call SetupBuildLauncher, keytool, \
|
||||
MAIN_CLASS := sun.security.tools.keytool.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 7fb12fc40a76a37ce67b051276a7ef582de1b04a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 28 Nov 2019 18:53:11 +0100
|
||||
Subject: [PATCH 21/48] Open jdk module to access ClassInfo.CACHE
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index ba6e78d6daa..0081f688120 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4329,5 +4329,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
+ // com.sun.beans.introspect.ClassInfo access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From d3d53f242337bd3bc79917f922ff569c0a112f3b Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 8 Dec 2019 17:55:01 +0100
|
||||
Subject: [PATCH 22/48] Open java.base/java.io module
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 0081f688120..0cdd8c88315 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4325,6 +4325,8 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
||||
// Class of field java.lang.reflect.Proxy/proxyCache
|
||||
create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
+ // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 833ef503677e066b3639e7418a22587992df1829 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Fri, 6 Mar 2020 09:28:24 +0100
|
||||
Subject: [PATCH 23/48] Fix fieldDescriptor.inline.hpp
|
||||
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index efb9e806508..a404fd3f016 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/relocator.hpp"
|
||||
+#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
@@ -490,6 +491,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
+
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1890,9 +1896,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
@@ -1905,7 +1908,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
|
||||
new_class->external_name(),
|
||||
java_lang_Class::classRedefinedCount(new_class->java_mirror()));
|
||||
-
|
||||
}
|
||||
_timer_rsc_phase2.stop();
|
||||
} // end redefine_single_class()
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
From 1af8b1f3f891388a37cc71076c324d3905ab2a46 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Fri, 6 Mar 2020 15:46:51 +0100
|
||||
Subject: [PATCH 24/48] Fix clear_cpool_cache
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a404fd3f016..1f5a67f8866 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -491,11 +491,6 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
-
|
||||
-
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1896,6 +1891,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
From def550828411b677ed2d7807e51cc5ffe70331fc Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Mon, 9 Mar 2020 09:54:04 +0100
|
||||
Subject: [PATCH 25/48] Refactor ClearCpoolCacheAndUnpatch
|
||||
|
||||
Call it after redefinition of all classes
|
||||
---
|
||||
make/common/MakeBase.gmk | 4 +-
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 98 ++++---------------
|
||||
2 files changed, 21 insertions(+), 81 deletions(-)
|
||||
|
||||
diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk
|
||||
index a040effe83a..c33a7d52ddb 100644
|
||||
--- a/make/common/MakeBase.gmk
|
||||
+++ b/make/common/MakeBase.gmk
|
||||
@@ -1044,7 +1044,9 @@ DependOnVariableHelper = \
|
||||
$(info NewVariable $1: >$(strip $($1))<) \
|
||||
$(info OldVariable $1: >$(strip $($1_old))<)) \
|
||||
$(call WriteFile, $1_old:=$(call DoubleDollar,$(call EscapeHash,$($1))), \
|
||||
- $($1_filename))) \
|
||||
+ $($1_filename)) \
|
||||
+ $(eval $($1_filename): ) \
|
||||
+ ) \
|
||||
$($1_filename) \
|
||||
)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 1f5a67f8866..24fb76b6de4 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -491,6 +491,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
+
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1383,86 +1388,23 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
||||
}
|
||||
}
|
||||
|
||||
-// Unevolving classes may point to methods of the_class directly
|
||||
+// Unevolving classes may point to old methods directly
|
||||
// from their constant pool caches, itables, and/or vtables. We
|
||||
-// use the ClassLoaderDataGraph::classes_do() facility and this helper
|
||||
-// to fix up these pointers.
|
||||
-// Adjust cpools and vtables closure
|
||||
+// use the SystemDictionary::classes_do() facility and this helper
|
||||
+// to fix up these pointers. Additional field offsets and vtable indices
|
||||
+// in the constant pool cache entries are fixed.
|
||||
+//
|
||||
+// Note: We currently don't support updating the vtable in
|
||||
+// arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp.
|
||||
void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
- // This is a very busy routine. We don't want too much tracing
|
||||
- // printed out.
|
||||
- bool trace_name_printed = false;
|
||||
- InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop);
|
||||
-
|
||||
- // If the class being redefined is java.lang.Object, we need to fix all
|
||||
- // array class vtables also
|
||||
- if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) {
|
||||
- k->vtable().adjust_method_entries(the_class, &trace_name_printed);
|
||||
- } else if (k->is_instance_klass()) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
+ if (!k->is_instance_klass()) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- // HotSpot specific optimization! HotSpot does not currently
|
||||
- // support delegation from the bootstrap class loader to a
|
||||
- // user-defined class loader. This means that if the bootstrap
|
||||
- // class loader is the initiating class loader, then it will also
|
||||
- // be the defining class loader. This also means that classes
|
||||
- // loaded by the bootstrap class loader cannot refer to classes
|
||||
- // loaded by a user-defined class loader. Note: a user-defined
|
||||
- // class loader can delegate to the bootstrap class loader.
|
||||
- //
|
||||
- // If the current class being redefined has a user-defined class
|
||||
- // loader as its defining class loader, then we can skip all
|
||||
- // classes loaded by the bootstrap class loader.
|
||||
- bool is_user_defined =
|
||||
- InstanceKlass::cast(_the_class_oop)->class_loader() != NULL;
|
||||
- if (is_user_defined && ik->class_loader() == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Fix the vtable embedded in the_class and subclasses of the_class,
|
||||
- // if one exists. We discard scratch_class and we don't keep an
|
||||
- // InstanceKlass around to hold obsolete methods so we don't have
|
||||
- // any other InstanceKlass embedded vtables to update. The vtable
|
||||
- // holds the Method*s for virtual (but not final) methods.
|
||||
- // Default methods, or concrete methods in interfaces are stored
|
||||
- // in the vtable, so if an interface changes we need to check
|
||||
- // adjust_method_entries() for every InstanceKlass, which will also
|
||||
- // adjust the default method vtable indices.
|
||||
- // We also need to adjust any default method entries that are
|
||||
- // not yet in the vtable, because the vtable setup is in progress.
|
||||
- // This must be done after we adjust the default_methods and
|
||||
- // default_vtable_indices for methods already in the vtable.
|
||||
- // If redefining Unsafe, walk all the vtables looking for entries.
|
||||
-// FIXME - code from standard redefine - if needed, it should switch to new_class
|
||||
-// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
|
||||
-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
|
||||
-// || ik->is_subtype_of(_the_class_oop))) {
|
||||
-// // ik->vtable() creates a wrapper object; rm cleans it up
|
||||
-// ResourceMark rm(_thread);
|
||||
-//
|
||||
-// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
-// ik->adjust_default_methods(the_class, &trace_name_printed);
|
||||
-// }
|
||||
-
|
||||
- // If the current class has an itable and we are either redefining an
|
||||
- // interface or if the current class is a subclass of the_class, then
|
||||
- // we potentially have to fix the itable. If we are redefining an
|
||||
- // interface, then we have to call adjust_method_entries() for
|
||||
- // every InstanceKlass that has an itable since there isn't a
|
||||
- // subclass relationship between an interface and an InstanceKlass.
|
||||
- // If redefining Unsafe, walk all the itables looking for entries.
|
||||
-// FIXME - code from standard redefine - if needed, it should switch to new_class
|
||||
-// if (ik->itable_length() > 0 && (_the_class_oop->is_interface()
|
||||
-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
|
||||
-// || ik->is_subclass_of(_the_class_oop))) {
|
||||
-// // ik->itable() creates a wrapper object; rm cleans it up
|
||||
-// ResourceMark rm(_thread);
|
||||
-//
|
||||
-// ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
-// }
|
||||
+ HandleMark hm(_thread);
|
||||
+ InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
|
||||
- constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
+ constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
|
||||
// Update host klass of anonymous classes (for example, produced by lambdas) to newest version.
|
||||
if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) {
|
||||
@@ -1491,7 +1433,6 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
if (RewriteBytecodes) {
|
||||
ik->methods_do(unpatch_bytecode);
|
||||
}
|
||||
- }
|
||||
}
|
||||
|
||||
// Clean method data for this class
|
||||
@@ -1891,9 +1832,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 5f416d7a25bd23399b9189cc94ab5d5887e6b4d4 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Wed, 11 Mar 2020 14:19:34 +0100
|
||||
Subject: [PATCH 26/48] Fix class cast exception on redefinition of class A,
|
||||
that is superclass of B that has anonymous class C
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 9b6ba7e9304..8cbd4b8edf2 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -788,7 +788,10 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
- {
|
||||
+ // In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
+ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
+ // on redefinition.
|
||||
+ if (!newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From 9a7abdf08bf207f5265a552500446c3178bf5794 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 23:28:07 +0200
|
||||
Subject: [PATCH 27/48] Update klass reference in Klass.implementor()
|
||||
|
||||
If interface X is removed from class Y then old reference to Y could be
|
||||
stored in X.implementor()
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 12 ++++++++++++
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.hpp | 11 -----------
|
||||
2 files changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 24fb76b6de4..f6d2d3a40fe 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1411,6 +1411,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version()));
|
||||
}
|
||||
|
||||
+ // Update implementor if there is only one, in this case implementor() can reference old class
|
||||
+ if (ik->is_interface()) {
|
||||
+ Klass* implKlass = ik->implementor();
|
||||
+ if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) {
|
||||
+ InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version());
|
||||
+ ik->init_implementor();
|
||||
+ if (newest_impl->implements_interface(ik)) {
|
||||
+ ik->add_implementor(newest_impl);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for (int i = 0; i < other_cp->length(); i++) {
|
||||
if (other_cp->tag_at(i).is_klass()) {
|
||||
Klass* klass = other_cp->resolved_klass_at(i);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 5b3ebc13661..2d114635ee5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -69,17 +69,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// RetransformClasses. Indicate which.
|
||||
JvmtiClassLoadKind _class_load_kind;
|
||||
|
||||
- // _index_map_count is just an optimization for knowing if
|
||||
- // _index_map_p contains any entries.
|
||||
- int _index_map_count;
|
||||
- intArray * _index_map_p;
|
||||
-
|
||||
- // _operands_index_map_count is just an optimization for knowing if
|
||||
- // _operands_index_map_p contains any entries.
|
||||
- int _operands_cur_length;
|
||||
- int _operands_index_map_count;
|
||||
- intArray * _operands_index_map_p;
|
||||
-
|
||||
GrowableArray<InstanceKlass*>* _new_classes;
|
||||
jvmtiError _res;
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
From 8f13d3b4ba9aecd847b7da306055ba53ee2e29d0 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 23:30:21 +0200
|
||||
Subject: [PATCH 28/48] Fix DirectMethodHandle accessors klasses
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/javaClasses.cpp | 28 +++++++++++++++------
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 4 +++
|
||||
2 files changed, 24 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
index a89443d22ea..ea0588e5388 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.cpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
@@ -3641,14 +3641,20 @@ void java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(oop d
|
||||
dmh->long_field_put(_static_offset_offset, static_offset);
|
||||
}
|
||||
|
||||
+#define DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(macro) \
|
||||
+ macro(_static_offset_offset, k, vmSymbols::static_offset_name(), long_signature, false)
|
||||
|
||||
void java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets() {
|
||||
- Klass* klass_oop = SystemDictionary::DirectMethodHandle_StaticAccessor_klass();
|
||||
- if (klass_oop != NULL) {
|
||||
- compute_offset(_static_offset_offset, InstanceKlass::cast(klass_oop), vmSymbols::static_offset_name(), vmSymbols::long_signature());
|
||||
- }
|
||||
+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_StaticAccessor_klass();
|
||||
+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
+void java_lang_invoke_DirectMethodHandle_StaticAccessor::serialize_offsets(SerializeClosure* f) {
|
||||
+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Support for java_lang_invoke_DirectMethodHandle$Accessor
|
||||
|
||||
int java_lang_invoke_DirectMethodHandle_Accessor::_field_offset_offset;
|
||||
@@ -3663,14 +3669,20 @@ void java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(oop dmh, int
|
||||
dmh->int_field_put(_field_offset_offset, field_offset);
|
||||
}
|
||||
|
||||
+#define DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(macro) \
|
||||
+ macro(_field_offset_offset, k, vmSymbols::field_offset_name(), int_signature, false)
|
||||
|
||||
void java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets() {
|
||||
- Klass* klass_oop = SystemDictionary::DirectMethodHandle_Accessor_klass();
|
||||
- if (klass_oop != NULL) {
|
||||
- compute_offset(_field_offset_offset, InstanceKlass::cast(klass_oop), vmSymbols::field_offset_name(), vmSymbols::int_signature());
|
||||
- }
|
||||
+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_Accessor_klass();
|
||||
+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
+void java_lang_invoke_DirectMethodHandle_Accessor::serialize_offsets(SerializeClosure* f) {
|
||||
+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Support for java_lang_invoke_MethodHandle
|
||||
|
||||
int java_lang_invoke_MethodHandle::_type_offset;
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index ceb1670df5d..55f9fa62e2b 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -67,6 +67,8 @@
|
||||
f(java_lang_invoke_LambdaForm) \
|
||||
f(java_lang_invoke_MethodType) \
|
||||
f(java_lang_invoke_CallSite) \
|
||||
+ f(java_lang_invoke_DirectMethodHandle_StaticAccessor) \
|
||||
+ f(java_lang_invoke_DirectMethodHandle_Accessor) \
|
||||
f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \
|
||||
f(java_security_AccessControlContext) \
|
||||
f(java_lang_reflect_AccessibleObject) \
|
||||
@@ -1077,6 +1079,7 @@ class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic {
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.DirectMethodHandle$Accessor objects
|
||||
@@ -1101,6 +1104,7 @@ class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic {
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From cbad9c34bf8920d772c646d041d4fc04fea203cc Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 11 Apr 2020 12:07:43 +0200
|
||||
Subject: [PATCH 29/48] cleanup direct method handles code
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 10 ++++------
|
||||
src/hotspot/share/classfile/javaClasses.inline.hpp | 8 ++++++++
|
||||
2 files changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index 55f9fa62e2b..da004d1b307 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -1076,9 +1076,8 @@ class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic {
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_StaticAccessor_klass());
|
||||
}
|
||||
- static bool is_instance(oop obj) {
|
||||
- return obj != NULL && is_subclass(obj->klass());
|
||||
- }
|
||||
+ static bool is_instance(oop obj);
|
||||
+
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
@@ -1101,9 +1100,8 @@ class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic {
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_Accessor_klass());
|
||||
}
|
||||
- static bool is_instance(oop obj) {
|
||||
- return obj != NULL && is_subclass(obj->klass());
|
||||
- }
|
||||
+ static bool is_instance(oop obj);
|
||||
+
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
index 6c5787f4b70..ba9cffa8c62 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
@@ -175,6 +175,14 @@ inline bool java_lang_invoke_DirectMethodHandle::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
+inline bool java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(oop obj) {
|
||||
+ return obj != NULL && is_subclass(obj->klass());
|
||||
+}
|
||||
+
|
||||
+inline bool java_lang_invoke_DirectMethodHandle_Accessor::is_instance(oop obj) {
|
||||
+ return obj != NULL && is_subclass(obj->klass());
|
||||
+}
|
||||
+
|
||||
inline bool java_lang_Module::is_instance(oop obj) {
|
||||
return obj != NULL && obj->klass() == SystemDictionary::Module_klass();
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
From e3b94671ce5108a91e3a3e92b01eea07731c7639 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 11 Apr 2020 17:52:13 +0200
|
||||
Subject: [PATCH 30/48] Add init_implementor_from_redefine, that skips compiler
|
||||
lock assert
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 10 +++++++++-
|
||||
src/hotspot/share/oops/instanceKlass.hpp | 1 +
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
3 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 8cbd4b8edf2..c04bdf5abfc 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -789,7 +789,7 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
// In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
- // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
+ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
// on redefinition.
|
||||
if (!newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
@@ -1139,6 +1139,14 @@ void InstanceKlass::init_implementor() {
|
||||
}
|
||||
}
|
||||
|
||||
+void InstanceKlass::init_implementor_from_redefine() {
|
||||
+ assert(is_interface(), "not interface");
|
||||
+ Klass** addr = adr_implementor();
|
||||
+ assert(addr != NULL, "null addr");
|
||||
+ if (addr != NULL) {
|
||||
+ *addr = NULL;
|
||||
+ }
|
||||
+}
|
||||
|
||||
void InstanceKlass::process_interfaces(Thread *thread) {
|
||||
// link this class into the implementors list of every interface it implements
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
index 2cc98b636f1..e8107a39813 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.hpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
@@ -1020,6 +1020,7 @@ public:
|
||||
int nof_implementors() const;
|
||||
void add_implementor(Klass* k); // k is a new class that implements this interface
|
||||
void init_implementor(); // initialize
|
||||
+ void init_implementor_from_redefine(); // initialize
|
||||
|
||||
// link this class into the implementors list of every interface it implements
|
||||
void process_interfaces(Thread *thread);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index f6d2d3a40fe..aac9ba0911f 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1416,7 +1416,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
Klass* implKlass = ik->implementor();
|
||||
if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) {
|
||||
InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version());
|
||||
- ik->init_implementor();
|
||||
+ ik->init_implementor_from_redefine();
|
||||
if (newest_impl->implements_interface(ik)) {
|
||||
ik->add_implementor(newest_impl);
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
From a95c3daf0a1db23e2dcc977f427faa7be41007c9 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 13 Apr 2020 20:59:35 +0200
|
||||
Subject: [PATCH 31/48] not nullable oop_store_not_null() method+handle NULL in
|
||||
mem_name in dmh
|
||||
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index aac9ba0911f..8d861ef43c9 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -225,13 +225,15 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
// TODO comment
|
||||
struct StoreBarrier {
|
||||
// TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store
|
||||
- template <class T> static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store_not_null(T* p, oop v) { HeapAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store(T* p) { HeapAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
|
||||
// TODO comment
|
||||
struct StoreNoBarrier {
|
||||
- template <class T> static void oop_store(T* p, oop v) { RawAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store_not_null(T* p, oop v) { RawAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -309,6 +311,9 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
bool update_direct_method_handle(oop obj) {
|
||||
// Always update member name first.
|
||||
oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj);
|
||||
+ if (mem_name == NULL) {
|
||||
+ return true;
|
||||
+ }
|
||||
if (!update_member_name(mem_name)) {
|
||||
return false;
|
||||
}
|
||||
@@ -347,7 +352,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking");
|
||||
if (klass->new_version() != NULL) {
|
||||
obj = InstanceKlass::cast(klass->new_version())->java_mirror();
|
||||
- S::oop_store(p, obj);
|
||||
+ S::oop_store_not_null(p, obj);
|
||||
oop_updated = true;
|
||||
}
|
||||
}
|
||||
@@ -363,7 +368,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (!update_direct_method_handle(obj)) {
|
||||
// DMH is no longer valid, replace it with null reference.
|
||||
// See note above. We probably want to replace this with something more meaningful.
|
||||
- S::oop_store(p, NULL);
|
||||
+ S::oop_store(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1430,8 +1435,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
// Constant pool entry points to redefined class -- update to the new version
|
||||
other_cp->klass_at_put(i, klass->newest_version());
|
||||
}
|
||||
- klass = other_cp->resolved_klass_at(i);
|
||||
- assert(klass->new_version() == NULL, "Must be new klass!");
|
||||
+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!");
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 15690197a276a86054e1ec9724c877d6d871ca01 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Khvastunov <artem.khvastunov@jetbrains.com>
|
||||
Date: Tue, 14 Apr 2020 19:11:35 +0200
|
||||
Subject: [PATCH 32/48] add jvmtiEnhancedRedefineClasses.* to CMakeLists.txt
|
||||
|
||||
---
|
||||
jb/project/hotspot-cmake/CMakeLists.txt | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/jb/project/hotspot-cmake/CMakeLists.txt b/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
index 8b552c27206..6516e39058f 100644
|
||||
--- a/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
+++ b/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
@@ -1663,6 +1663,7 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiAgentThread.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp
|
||||
+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
../../../src/hotspot/share/prims/stackwalk.cpp
|
||||
../../../src/hotspot/share/prims/privilegedStack.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiUtil.hpp
|
||||
@@ -1684,6 +1685,7 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/prims/stackwalk.hpp
|
||||
../../../src/hotspot/share/prims/privilegedStack.cpp
|
||||
../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.hpp
|
||||
+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiUtil.cpp
|
||||
../../../src/hotspot/share/prims/jvmtiEnvBase.cpp
|
||||
../../../src/hotspot/share/prims/methodHandles.cpp
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From dab6a53de4c25aae95667c78b8e1f1097ab47130 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Khvastunov <artem.khvastunov@jetbrains.com>
|
||||
Date: Sun, 19 Apr 2020 11:36:12 +0200
|
||||
Subject: [PATCH 33/48] migrate DCEVM to 11.0.7
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 2d114635ee5..6cabdca9c27 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
-#include "runtime/vm_operations.hpp"
|
||||
+#include "runtime/vmOperations.hpp"
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 70d53ce28f9df75d9e50819d2b6654855da0d533 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 8 May 2020 21:07:50 +0200
|
||||
Subject: [PATCH 34/48] Fix 11.0.7 compilation issues
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 6cabdca9c27..ed44f0e27ce 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -16,6 +16,8 @@
|
||||
* 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.
|
||||
@@ -30,7 +32,6 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
-#include "runtime/vmOperations.hpp"
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 805b588bc4bd45e61b81c90e23b71337072e9549 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 9 May 2020 10:08:17 +0200
|
||||
Subject: [PATCH 35/48] Use INCLUDE_CDS condition on "UseSharedSpaces" block
|
||||
from master
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 8d861ef43c9..660bf3a2e97 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -467,6 +467,7 @@ public:
|
||||
void VM_EnhancedRedefineClasses::doit() {
|
||||
Thread *thread = Thread::current();
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
if (UseSharedSpaces) {
|
||||
// Sharing is enabled so we remap the shared readonly space to
|
||||
// shared readwrite, private just in case we need to redefine
|
||||
@@ -478,6 +479,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
|
||||
// Mark methods seen on stack and everywhere else so old methods are not
|
||||
// cleaned up if they're on the stack.
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
From 78619004206d224b319d68493672bee2c97f0946 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 16 May 2020 15:11:40 +0200
|
||||
Subject: [PATCH 36/48] Access com.sun.beans.util - HotswapAgent patch
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
.../sun/beans/introspect/package-info.java | 26 +++++++++++++++++++
|
||||
.../classes/com/sun/beans/package-info.java | 26 +++++++++++++++++++
|
||||
.../com/sun/beans/util/package-info.java | 26 +++++++++++++++++++
|
||||
.../share/classes/module-info.java | 3 +++
|
||||
5 files changed, 83 insertions(+)
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 0cdd8c88315..72580b384dd 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4333,5 +4333,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
// com.sun.beans.introspect.ClassInfo access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
||||
+ // com.sun.beans.introspect.util.Cache access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..6636e4dd62a
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans.introspect;
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/package-info.java b/src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..5c097eeaa53
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans;
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/util/package-info.java b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..2d5d735ffa8
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans.util;
|
||||
diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java
|
||||
index f9cf021311f..e61ba7572cf 100644
|
||||
--- a/src/java.desktop/share/classes/module-info.java
|
||||
+++ b/src/java.desktop/share/classes/module-info.java
|
||||
@@ -104,6 +104,9 @@ module java.desktop {
|
||||
exports javax.swing.text.rtf;
|
||||
exports javax.swing.tree;
|
||||
exports javax.swing.undo;
|
||||
+ exports com.sun.beans;
|
||||
+ exports com.sun.beans.introspect;
|
||||
+ exports com.sun.beans.util;
|
||||
|
||||
// qualified exports may be inserted at build time
|
||||
// see make/GensrcModuleInfo.gmk
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From baf26456579eb0e560471d3bcb150005492f69f4 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 17 May 2020 12:19:18 +0200
|
||||
Subject: [PATCH 37/48] Skip verifier only in AllowEnhancedClassRedefinition
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index c04bdf5abfc..e14aaee21c4 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -788,10 +788,10 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
- // In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
+ // (DCEVM): If class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
// then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
// on redefinition.
|
||||
- if (!newest_version()->is_redefining()) {
|
||||
+ if (!AllowEnhancedClassRedefinition || !newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
From 46dc38a58ac8afafab4e04ee47a1ed2b9e65c1e1 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 17 May 2020 18:18:52 +0200
|
||||
Subject: [PATCH 38/48] Use original code for adjust_method_entries in standard
|
||||
redefinition
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
.../share/prims/resolvedMethodTable.cpp | 46 ++++++++++++++++++-
|
||||
.../share/prims/resolvedMethodTable.hpp | 1 +
|
||||
3 files changed, 47 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 660bf3a2e97..0ca675e8ee6 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -506,7 +506,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
- ResolvedMethodTable::adjust_method_entries(&trace_name_printed);
|
||||
+ ResolvedMethodTable::adjust_method_entries_dcevm(&trace_name_printed);
|
||||
}
|
||||
|
||||
ChangePointersOopClosure<StoreNoBarrier> oopClosureNoBarrier;
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index a9057893368..af2ec48c2e1 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -197,8 +197,52 @@ void ResolvedMethodTable::print() {
|
||||
#endif // PRODUCT
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
-// It is called at safepoint only for RedefineClasses
|
||||
+
|
||||
void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
+ // For each entry in RMT, change to new method
|
||||
+ for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
+ for (ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
+ entry != NULL;
|
||||
+ entry = entry->next()) {
|
||||
+
|
||||
+ oop mem_name = entry->object_no_keepalive();
|
||||
+ // except ones removed
|
||||
+ if (mem_name == NULL) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
+
|
||||
+ if (old_method->is_old()) {
|
||||
+
|
||||
+ Method* new_method;
|
||||
+ if (old_method->is_deleted()) {
|
||||
+ new_method = Universe::throw_no_such_method_error();
|
||||
+ } else {
|
||||
+ InstanceKlass* holder = old_method->method_holder();
|
||||
+ new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
+ assert(holder == new_method->method_holder(), "call after swapping redefined guts");
|
||||
+ assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
+ assert(old_method != new_method, "sanity check");
|
||||
+ }
|
||||
+
|
||||
+ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
|
||||
+
|
||||
+ ResourceMark rm;
|
||||
+ if (!(*trace_name_printed)) {
|
||||
+ log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
+ *trace_name_printed = true;
|
||||
+ }
|
||||
+ log_debug(redefine, class, update, constantpool)
|
||||
+ ("ResolvedMethod method update: %s(%s)",
|
||||
+ new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// (DCEVM) It is called at safepoint only for RedefineClasses
|
||||
+void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
// For each entry in RMT, change to new method
|
||||
GrowableArray<oop>* oops_to_add = new GrowableArray<oop>();
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.hpp b/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
index 841ae4ae585..543d4ffa485 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
#if INCLUDE_JVMTI
|
||||
// It is called at safepoint only for RedefineClasses
|
||||
static void adjust_method_entries(bool * trace_name_printed);
|
||||
+ static void adjust_method_entries_dcevm(bool * trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Cleanup cleared entries
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 6ac099d1b07fcc0d3c17ebd5d3335bcb6ceaedc9 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 09:41:36 +0200
|
||||
Subject: [PATCH 39/48] Revert code for !AllowEnhancedClassRedefinition
|
||||
|
||||
---
|
||||
.../share/classfile/classLoaderData.cpp | 23 ++++++++++---------
|
||||
1 file changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index 25103fff2c0..f5b877b432b 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -1387,12 +1387,13 @@ bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
|
||||
// Klassesoto delete.
|
||||
|
||||
// FIXME: dcevm - block asserts in MetadataOnStackMark
|
||||
- /*
|
||||
- bool walk_all_metadata = clean_previous_versions &&
|
||||
- JvmtiExport::has_redefined_a_class() &&
|
||||
- InstanceKlass::has_previous_versions_and_reset();
|
||||
- MetadataOnStackMark md_on_stack(walk_all_metadata);
|
||||
- */
|
||||
+ bool walk_all_metadata = false;
|
||||
+ if (!AllowEnhancedClassRedefinition) {
|
||||
+ walk_all_metadata = clean_previous_versions &&
|
||||
+ JvmtiExport::has_redefined_a_class() &&
|
||||
+ InstanceKlass::has_previous_versions_and_reset();
|
||||
+ MetadataOnStackMark md_on_stack(walk_all_metadata);
|
||||
+ }
|
||||
|
||||
// Save previous _unloading pointer for CMS which may add to unloading list before
|
||||
// purging and we don't want to rewalk the previously unloaded class loader data.
|
||||
@@ -1402,12 +1403,12 @@ bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
|
||||
while (data != NULL) {
|
||||
if (data->is_alive()) {
|
||||
// clean metaspace
|
||||
- /*
|
||||
- if (walk_all_metadata) {
|
||||
- data->classes_do(InstanceKlass::purge_previous_versions);
|
||||
+ if (!AllowEnhancedClassRedefinition) {
|
||||
+ if (walk_all_metadata) {
|
||||
+ data->classes_do(InstanceKlass::purge_previous_versions);
|
||||
+ }
|
||||
+ data->free_deallocate_list();
|
||||
}
|
||||
- data->free_deallocate_list();
|
||||
- */
|
||||
prev = data;
|
||||
data = data->next();
|
||||
loaders_processed++;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
278
jb/project/tools/patches/dcevm/0040-Code-cleanup.patch
Normal file
278
jb/project/tools/patches/dcevm/0040-Code-cleanup.patch
Normal file
@@ -0,0 +1,278 @@
|
||||
From de04154ee21d33c1ac1b74b2740f2fda117c0430 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 09:29:39 +0200
|
||||
Subject: [PATCH 40/48] Code cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/classFileParser.cpp | 4 +++-
|
||||
src/hotspot/share/classfile/classFileParser.hpp | 2 +-
|
||||
src/hotspot/share/classfile/classLoaderData.cpp | 2 ++
|
||||
src/hotspot/share/classfile/dictionary.cpp | 4 ++++
|
||||
src/hotspot/share/classfile/dictionary.hpp | 1 +
|
||||
src/hotspot/share/classfile/loaderConstraints.cpp | 3 ++-
|
||||
src/hotspot/share/classfile/systemDictionary.cpp | 8 +++++---
|
||||
src/hotspot/share/interpreter/linkResolver.cpp | 1 +
|
||||
src/hotspot/share/memory/universe.cpp | 4 ++--
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 13 ++++++++-----
|
||||
10 files changed, 29 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
|
||||
index ea150df9104..c2cd35da4e6 100644
|
||||
--- a/src/hotspot/share/classfile/classFileParser.cpp
|
||||
+++ b/src/hotspot/share/classfile/classFileParser.cpp
|
||||
@@ -954,6 +954,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
CHECK);
|
||||
}
|
||||
|
||||
+ // (DCEVM) pick newest
|
||||
interf = (Klass *) maybe_newest(interf);
|
||||
|
||||
if (!interf->is_interface()) {
|
||||
@@ -3749,6 +3750,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp,
|
||||
// However, make sure it is not an array type.
|
||||
bool is_array = false;
|
||||
if (cp->tag_at(super_class_index).is_klass()) {
|
||||
+ // (DCEVM) pick newest
|
||||
super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index)));
|
||||
if (need_verify)
|
||||
is_array = super_klass->is_array_klass();
|
||||
@@ -4417,7 +4419,7 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
|
||||
if (!_has_empty_finalizer) {
|
||||
if (_has_finalizer ||
|
||||
(super != NULL && super->has_finalizer())) {
|
||||
- // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active
|
||||
+ // FIXME - (DCEVM) this is condition from previous DCEVM version, however after reload a new finalize() method is not active
|
||||
if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) {
|
||||
ik->set_has_finalizer();
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
index 3db14b678f3..93ed54d8f70 100644
|
||||
--- a/src/hotspot/share/classfile/classFileParser.hpp
|
||||
+++ b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
@@ -499,7 +499,7 @@ class ClassFileParser {
|
||||
FieldLayoutInfo* info,
|
||||
TRAPS);
|
||||
|
||||
- // Enhanced class redefinition
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; }
|
||||
|
||||
public:
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index f5b877b432b..ab2615da0ed 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -1242,6 +1242,7 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) - iterate over dict classes
|
||||
void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->classes_do(klass_closure);
|
||||
@@ -1257,6 +1258,7 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS),
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) rollback redefined classes
|
||||
void ClassLoaderDataGraph::rollback_redefinition() {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->rollback_redefinition();
|
||||
diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp
|
||||
index 118730f1b83..dda5188c370 100644
|
||||
--- a/src/hotspot/share/classfile/dictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/dictionary.cpp
|
||||
@@ -245,6 +245,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) {
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
+// (DCEVM) iterate over dict entry
|
||||
void Dictionary::classes_do(KlassClosure* closure) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
@@ -342,6 +344,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+// (DCEVM) replace old_class by new class in dictionary
|
||||
bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) {
|
||||
// There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class.
|
||||
bool found = false;
|
||||
@@ -356,6 +359,7 @@ bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData*
|
||||
return found;
|
||||
}
|
||||
|
||||
+// (DCEVM) rollback redefinition
|
||||
void Dictionary::rollback_redefinition() {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* entry = bucket(index);
|
||||
diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp
|
||||
index fd4b134d7a7..5eaa741d500 100644
|
||||
--- a/src/hotspot/share/classfile/dictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/dictionary.hpp
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
|
||||
void rollback_redefinition();
|
||||
|
||||
+ // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k"
|
||||
static InstanceKlass* old_if_redefined(InstanceKlass* k) {
|
||||
return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k;
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
index e4a23e8a27c..bca73b5e0dc 100644
|
||||
--- a/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
+++ b/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 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.
|
||||
+ * published by the Free Software Foundation) replace old_class by new class in dictionary.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
@@ -87,6 +87,7 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
|
||||
return pp;
|
||||
}
|
||||
|
||||
+// (DCEVM) update constraint entries to new classes, called from dcevm redefinition code only
|
||||
void LoaderConstraintTable::update_after_redefinition() {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
LoaderConstraintEntry** p = bucket_addr(index);
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index 9dbd6cc9c12..e70865109dd 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -876,7 +876,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
ClassLoaderData* loader_data = k->class_loader_data();
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
Klass* kk = find_class(name, loader_data);
|
||||
- // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version())
|
||||
+ // FIXME: (DCEVM)
|
||||
+ // assert(kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version())
|
||||
assert(kk == k, "should be present in dictionary");
|
||||
}
|
||||
#endif
|
||||
@@ -1083,7 +1084,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
InstanceKlass* k = NULL;
|
||||
|
||||
#if INCLUDE_CDS
|
||||
- // FIXME: what to do during redefinition?
|
||||
+ // FIXME: (DCEVM) what to do during redefinition?
|
||||
if (!DumpSharedSpaces) {
|
||||
k = SystemDictionaryShared::lookup_from_stream(class_name,
|
||||
class_loader,
|
||||
@@ -1836,7 +1837,7 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||
CodeCache::flush_dependents_on(k);
|
||||
}
|
||||
|
||||
-// Enhanced class redefinition
|
||||
+// (DCEVM) - remove from klass hierarchy
|
||||
void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
assert(k != NULL, "just checking");
|
||||
|
||||
@@ -1844,6 +1845,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
k->remove_from_sibling_list();
|
||||
}
|
||||
|
||||
+// (DCEVM)
|
||||
void SystemDictionary::update_constraints_after_redefinition() {
|
||||
constraints()->update_after_redefinition();
|
||||
}
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index cb76d2ef50c..9dc184d02f5 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -1384,6 +1384,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
|
||||
assert(resolved_method->can_be_statically_bound(), "cannot override this method");
|
||||
selected_method = resolved_method;
|
||||
} else {
|
||||
+ // TODO: (DCEVM) explain
|
||||
assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent");
|
||||
selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
|
||||
}
|
||||
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
|
||||
index 7ecb950b231..d0a6d665aa0 100644
|
||||
--- a/src/hotspot/share/memory/universe.cpp
|
||||
+++ b/src/hotspot/share/memory/universe.cpp
|
||||
@@ -176,7 +176,7 @@ void Universe::basic_type_classes_do(void f(Klass*)) {
|
||||
f(doubleArrayKlassObj());
|
||||
}
|
||||
|
||||
-// FIXME: This method should iterate all pointers that are not within heap objects.
|
||||
+// FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects.
|
||||
void Universe::root_oops_do(OopClosure *oopClosure) {
|
||||
|
||||
class AlwaysTrueClosure: public BoolObjectClosure {
|
||||
@@ -203,7 +203,7 @@ void Universe::root_oops_do(OopClosure *oopClosure) {
|
||||
CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations);
|
||||
CodeCache::blobs_do(&blobClosure);
|
||||
StringTable::oops_do(oopClosure);
|
||||
-
|
||||
+
|
||||
// (DCEVM) TODO: Check if this is correct?
|
||||
//CodeCache::scavenge_root_nmethods_oops_do(oopClosure);
|
||||
//Management::oops_do(oopClosure);
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index e14aaee21c4..c860371d2fc 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -1139,6 +1139,7 @@ void InstanceKlass::init_implementor() {
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) - init_implementor() for dcevm
|
||||
void InstanceKlass::init_implementor_from_redefine() {
|
||||
assert(is_interface(), "not interface");
|
||||
Klass** addr = adr_implementor();
|
||||
@@ -1209,6 +1210,8 @@ bool InstanceKlass::implements_interface(Klass* k) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
+
|
||||
+// (DCEVM)
|
||||
bool InstanceKlass::implements_interface_any_version(Klass* k) const {
|
||||
k = k->newest_version();
|
||||
if (this->newest_version() == k) return true;
|
||||
@@ -1491,10 +1494,8 @@ void InstanceKlass::methods_do(void f(Method* method)) {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Update information contains mapping of fields from old class to the new class.
|
||||
- Info is stored on HEAP, you need to call clear_update_information to free the space.
|
||||
-*/
|
||||
+// (DCEVM) Update information contains mapping of fields from old class to the new class.
|
||||
+// Info is stored on HEAP, you need to call clear_update_information to free the space.
|
||||
void InstanceKlass::store_update_information(GrowableArray<int> &values) {
|
||||
int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass);
|
||||
for (int i = 0; i < values.length(); i++) {
|
||||
@@ -2162,6 +2163,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
|
||||
dependencies().add_dependent_nmethod(nm);
|
||||
}
|
||||
|
||||
+// DCEVM - update jmethod ids
|
||||
bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) {
|
||||
size_t idnum = (size_t)method->method_idnum();
|
||||
jmethodID* jmeths = methods_jmethod_ids_acquire();
|
||||
@@ -2177,7 +2179,7 @@ bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) {
|
||||
|
||||
void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
|
||||
dependencies().remove_dependent_nmethod(nm, delete_immediately);
|
||||
- // (DCEVM) Hack as dependencies get wrong version of Klass*
|
||||
+ // FIXME: (DCEVM) Hack as dependencies get wrong version of Klass*
|
||||
// if (this->old_version() != NULL) {
|
||||
// InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true);
|
||||
// return;
|
||||
@@ -3594,6 +3596,7 @@ void InstanceKlass::verify_on(outputStream* st) {
|
||||
}
|
||||
|
||||
guarantee(sib->is_klass(), "should be klass");
|
||||
+ // TODO: (DCEVM) explain
|
||||
guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass");
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From ab8888737eaed76776b41b28af93a0c47826b8d6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 10:31:15 +0200
|
||||
Subject: [PATCH 41/48] Activate cpCache definition asserts for !dcevm
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/cpCache.cpp | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
|
||||
index 47040d51f0c..4318df227d1 100644
|
||||
--- a/src/hotspot/share/oops/cpCache.cpp
|
||||
+++ b/src/hotspot/share/oops/cpCache.cpp
|
||||
@@ -436,8 +436,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
|
||||
if (has_appendix) {
|
||||
const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
|
||||
assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
|
||||
- // FIXME (DCEVM) relaxing for now...
|
||||
- //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
|
||||
+ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(appendix_index) == NULL, "init just once");
|
||||
resolved_references->obj_at_put(appendix_index, appendix());
|
||||
}
|
||||
|
||||
@@ -445,8 +444,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
|
||||
if (has_method_type) {
|
||||
const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset;
|
||||
assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob");
|
||||
- // FIXME (DCEVM) relaxing for now...
|
||||
- //assert(resolved_references->obj_at(method_type_index) == NULL, "init just once");
|
||||
+ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(method_type_index) == NULL, "init just once");
|
||||
resolved_references->obj_at_put(method_type_index, method_type());
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 8596cf8b677eadcd18b527dd61c891475758bbaa Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 10:54:38 +0200
|
||||
Subject: [PATCH 42/48] iterate old method version only in dcevm
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiImpl.cpp | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
index 2a92ece916e..d2044541d38 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
@@ -294,8 +294,10 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
|
||||
Symbol* m_signature = _method->signature();
|
||||
|
||||
// (DCEVM) Go through old versions of method
|
||||
- for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) {
|
||||
- (m->*meth_act)(_bci);
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) {
|
||||
+ (m->*meth_act)(_bci);
|
||||
+ }
|
||||
}
|
||||
|
||||
// search previous versions if they exist
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
From f3c1667fc04abdd9aa556b2c00a23239eba14287 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 22 May 2020 21:23:01 +0200
|
||||
Subject: [PATCH 43/48] Support for Lambda class redefinition
|
||||
|
||||
---
|
||||
.../share/classfile/classLoaderData.cpp | 9 +++
|
||||
.../share/classfile/classLoaderData.hpp | 1 +
|
||||
.../share/classfile/systemDictionary.cpp | 12 +++-
|
||||
.../share/classfile/systemDictionary.hpp | 2 +
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 65 +++++++++++++++++--
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 1 +
|
||||
.../share/prims/resolvedMethodTable.cpp | 4 +-
|
||||
src/hotspot/share/prims/unsafe.cpp | 1 +
|
||||
8 files changed, 85 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index ab2615da0ed..1bc67adf5a7 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -663,6 +663,15 @@ Dictionary* ClassLoaderData::create_dictionary() {
|
||||
return new Dictionary(this, size, resizable);
|
||||
}
|
||||
|
||||
+void ClassLoaderData::exchange_holders(ClassLoaderData* cld) {
|
||||
+ oop holder_oop = _holder.peek();
|
||||
+ _holder.replace(cld->_holder.peek());
|
||||
+ cld->_holder.replace(holder_oop);
|
||||
+ WeakHandle<vm_class_loader_data> exchange = _holder;
|
||||
+ _holder = cld->_holder;
|
||||
+ cld->_holder = exchange;
|
||||
+}
|
||||
+
|
||||
// Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph
|
||||
oop ClassLoaderData::holder_phantom() const {
|
||||
// A klass that was previously considered dead can be looked up in the
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
index 7e357929971..00a84610b43 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
@@ -292,6 +292,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = true; }
|
||||
void clear_accumulated_modified_oops() { _accumulated_modified_oops = false; }
|
||||
bool has_accumulated_modified_oops() { return _accumulated_modified_oops; }
|
||||
+ void exchange_holders(ClassLoaderData* cld);
|
||||
private:
|
||||
|
||||
void unload();
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index e70865109dd..cc9f1fa7831 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -971,12 +971,16 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const InstanceKlass* host_klass,
|
||||
+ InstanceKlass* old_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS) {
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
|
||||
ClassLoaderData* loader_data;
|
||||
+
|
||||
+ bool is_redefining = (old_klass != NULL);
|
||||
+
|
||||
if (host_klass != NULL) {
|
||||
// Create a new CLD for anonymous class, that uses the same class loader
|
||||
// as the host_klass
|
||||
@@ -1000,8 +1004,12 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
protection_domain,
|
||||
host_klass,
|
||||
cp_patches,
|
||||
- false, // pick_newest
|
||||
+ is_redefining, // pick_newest
|
||||
CHECK_NULL);
|
||||
+ if (is_redefining && k != NULL) {
|
||||
+ k->set_redefining(true);
|
||||
+ k->set_old_version(old_klass);
|
||||
+ }
|
||||
|
||||
if (host_klass != NULL && k != NULL) {
|
||||
// Anonymous classes must update ClassLoaderData holder (was host_klass loader)
|
||||
@@ -1845,7 +1853,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
k->remove_from_sibling_list();
|
||||
}
|
||||
|
||||
-// (DCEVM)
|
||||
+// (DCEVM)
|
||||
void SystemDictionary::update_constraints_after_redefinition() {
|
||||
constraints()->update_after_redefinition();
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
index 717f34ce9a0..dc111846c12 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
@@ -301,6 +301,7 @@ public:
|
||||
protection_domain,
|
||||
st,
|
||||
NULL, // host klass
|
||||
+ NULL, // old class
|
||||
NULL, // cp_patches
|
||||
THREAD);
|
||||
}
|
||||
@@ -309,6 +310,7 @@ public:
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const InstanceKlass* host_klass,
|
||||
+ InstanceKlass* old_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS);
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 0ca675e8ee6..08fe42d5c28 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -503,6 +503,8 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
|
||||
+ // SystemDictionary::methods_do(fix_invoke_method);
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -774,12 +776,34 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
// load hook event.
|
||||
state->set_class_being_redefined(the_class, _class_load_kind);
|
||||
|
||||
- InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym,
|
||||
- the_class_loader,
|
||||
- protection_domain,
|
||||
- &st,
|
||||
- the_class,
|
||||
- THREAD);
|
||||
+ InstanceKlass* k;
|
||||
+
|
||||
+ if (InstanceKlass::cast(the_class)->is_anonymous()) {
|
||||
+ const InstanceKlass* host_class = the_class->host_klass();
|
||||
+
|
||||
+ // Make sure it's the real host class, not another anonymous class.
|
||||
+ while (host_class != NULL && host_class->is_anonymous()) {
|
||||
+ host_class = host_class->host_klass();
|
||||
+ }
|
||||
+
|
||||
+ k = SystemDictionary::parse_stream(the_class_sym,
|
||||
+ the_class_loader,
|
||||
+ protection_domain,
|
||||
+ &st,
|
||||
+ host_class,
|
||||
+ the_class,
|
||||
+ NULL,
|
||||
+ THREAD);
|
||||
+ k->class_loader_data()->exchange_holders(the_class->class_loader_data());
|
||||
+ the_class->class_loader_data()->inc_keep_alive();
|
||||
+ } else {
|
||||
+ k = SystemDictionary::resolve_from_stream(the_class_sym,
|
||||
+ the_class_loader,
|
||||
+ protection_domain,
|
||||
+ &st,
|
||||
+ the_class,
|
||||
+ THREAD);
|
||||
+ }
|
||||
// Clear class_being_redefined just to be sure.
|
||||
state->clear_class_being_redefined();
|
||||
|
||||
@@ -1469,6 +1493,30 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
|
||||
}
|
||||
}
|
||||
|
||||
+void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) {
|
||||
+
|
||||
+ constantPoolHandle other_cp = constantPoolHandle(method->constants());
|
||||
+
|
||||
+ for (int i = 0; i < other_cp->length(); i++) {
|
||||
+ if (other_cp->tag_at(i).is_klass()) {
|
||||
+ Klass* klass = other_cp->resolved_klass_at(i);
|
||||
+ if (klass->new_version() != NULL) {
|
||||
+ // Constant pool entry points to redefined class -- update to the new version
|
||||
+ other_cp->klass_at_put(i, klass->newest_version());
|
||||
+ }
|
||||
+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ConstantPoolCache* cp_cache = other_cp->cache();
|
||||
+ if (cp_cache != NULL) {
|
||||
+ cp_cache->clear_entries();
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
||||
for (int j = 0; j < _matching_methods_length; ++j) {
|
||||
Method* old_method = _matching_old_methods[j];
|
||||
@@ -2018,7 +2066,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
// Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined)
|
||||
AffectedKlassClosure closure(_affected_klasses);
|
||||
// Updated in j10, from original SystemDictionary::classes_do
|
||||
- ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
+
|
||||
+ ClassLoaderDataGraph::classes_do(&closure);
|
||||
+ //ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
+
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
// Sort the affected klasses such that a supertype is always on a smaller array index than its subtype.
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index ed44f0e27ce..7e2afd49650 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -119,6 +119,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
void rollback();
|
||||
static void mark_as_scavengable(nmethod* nm);
|
||||
static void unpatch_bytecode(Method* method);
|
||||
+ static void fix_invoke_method(Method* method);
|
||||
|
||||
// Figure out which new methods match old methods in name and signature,
|
||||
// which methods have been added, and which are no longer present
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index af2ec48c2e1..7741328979f 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -200,7 +200,7 @@ void ResolvedMethodTable::print() {
|
||||
|
||||
void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
- // For each entry in RMT, change to new method
|
||||
+ // For each entry in RMT, change to new methodadjust_method_entries_dcevm
|
||||
for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
for (ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
entry != NULL;
|
||||
@@ -271,6 +271,8 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
+
|
||||
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != newer_method, "sanity check");
|
||||
diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp
|
||||
index 2f14e01ce0d..d0e0367d8eb 100644
|
||||
--- a/src/hotspot/share/prims/unsafe.cpp
|
||||
+++ b/src/hotspot/share/prims/unsafe.cpp
|
||||
@@ -818,6 +818,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
|
||||
host_domain,
|
||||
&st,
|
||||
InstanceKlass::cast(host_klass),
|
||||
+ NULL,
|
||||
cp_patches,
|
||||
CHECK_NULL);
|
||||
if (anonk == NULL) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From b8a3d4249eb97613f796edc709e414900c9a0828 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 22 May 2020 21:43:22 +0200
|
||||
Subject: [PATCH 44/48] Skip GC runs for redefinitions without instance size
|
||||
change
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 08fe42d5c28..a785a43d352 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -578,14 +578,14 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
}
|
||||
|
||||
-// if (objectClosure.needs_instance_update()) {
|
||||
+ if (objectClosure.needs_instance_update()) {
|
||||
// Do a full garbage collection to update the instance sizes accordingly
|
||||
Universe::set_redefining_gc_run(true);
|
||||
notify_gc_begin(true);
|
||||
Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection);
|
||||
notify_gc_end();
|
||||
Universe::set_redefining_gc_run(false);
|
||||
-// }
|
||||
+ }
|
||||
|
||||
// Unmark Klass*s as "redefining"
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
From 77bdf6253c457ed88436fb4da6a53c7c0c361a1c Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 23 May 2020 10:02:15 +0200
|
||||
Subject: [PATCH 45/48] Fix "no original bytecode found" error if method with
|
||||
bkp is missing
|
||||
|
||||
Sometimes IDE can deploy class with erroneous method, such method has
|
||||
no bytecode, but breakpoint position can still exist.
|
||||
---
|
||||
src/hotspot/share/interpreter/bytecodes.cpp | 2 +-
|
||||
.../share/interpreter/interpreterRuntime.cpp | 2 +-
|
||||
src/hotspot/share/oops/method.cpp | 8 ++++----
|
||||
src/hotspot/share/oops/method.hpp | 4 ++--
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++--------
|
||||
5 files changed, 18 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/interpreter/bytecodes.cpp b/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
index e377e36b88c..262ecc021b2 100644
|
||||
--- a/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
+++ b/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
@@ -84,7 +84,7 @@ Bytecodes::Code Bytecodes::code_at(Method* method, int bci) {
|
||||
Bytecodes::Code Bytecodes::non_breakpoint_code_at(const Method* method, address bcp) {
|
||||
assert(method != NULL, "must have the method for breakpoint conversion");
|
||||
assert(method->contains(bcp), "must be valid bcp in method");
|
||||
- return method->orig_bytecode_at(method->bci_from(bcp));
|
||||
+ return method->orig_bytecode_at(method->bci_from(bcp), false);
|
||||
}
|
||||
|
||||
int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) {
|
||||
diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
index f367e658879..71bbd15a4f5 100644
|
||||
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
@@ -834,7 +834,7 @@ IRT_END
|
||||
// Invokes
|
||||
|
||||
IRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp))
|
||||
- return method->orig_bytecode_at(method->bci_from(bcp));
|
||||
+ return method->orig_bytecode_at(method->bci_from(bcp), false);
|
||||
IRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code))
|
||||
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
|
||||
index bee69f9cec6..f1e22db70d6 100644
|
||||
--- a/src/hotspot/share/oops/method.cpp
|
||||
+++ b/src/hotspot/share/oops/method.cpp
|
||||
@@ -1747,14 +1747,14 @@ bool CompressedLineNumberReadStream::read_pair() {
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
|
||||
-Bytecodes::Code Method::orig_bytecode_at(int bci) const {
|
||||
+Bytecodes::Code Method::orig_bytecode_at(int bci, bool no_fatal) const {
|
||||
BreakpointInfo* bp = method_holder()->breakpoints();
|
||||
for (; bp != NULL; bp = bp->next()) {
|
||||
if (bp->match(this, bci)) {
|
||||
return bp->orig_bytecode();
|
||||
}
|
||||
}
|
||||
- {
|
||||
+ if (!no_fatal) {
|
||||
ResourceMark rm;
|
||||
fatal("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci);
|
||||
}
|
||||
@@ -1900,7 +1900,7 @@ BreakpointInfo::BreakpointInfo(Method* m, int bci) {
|
||||
_signature_index = m->signature_index();
|
||||
_orig_bytecode = (Bytecodes::Code) *m->bcp_from(_bci);
|
||||
if (_orig_bytecode == Bytecodes::_breakpoint)
|
||||
- _orig_bytecode = m->orig_bytecode_at(_bci);
|
||||
+ _orig_bytecode = m->orig_bytecode_at(_bci, false);
|
||||
_next = NULL;
|
||||
}
|
||||
|
||||
@@ -1909,7 +1909,7 @@ void BreakpointInfo::set(Method* method) {
|
||||
{
|
||||
Bytecodes::Code code = (Bytecodes::Code) *method->bcp_from(_bci);
|
||||
if (code == Bytecodes::_breakpoint)
|
||||
- code = method->orig_bytecode_at(_bci);
|
||||
+ code = method->orig_bytecode_at(_bci, false);
|
||||
assert(orig_bytecode() == code, "original bytecode must be the same");
|
||||
}
|
||||
#endif
|
||||
diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp
|
||||
index 4533476ff8f..193e1845b23 100644
|
||||
--- a/src/hotspot/share/oops/method.hpp
|
||||
+++ b/src/hotspot/share/oops/method.hpp
|
||||
@@ -230,7 +230,7 @@ class Method : public Metadata {
|
||||
|
||||
// JVMTI breakpoints
|
||||
#if !INCLUDE_JVMTI
|
||||
- Bytecodes::Code orig_bytecode_at(int bci) const {
|
||||
+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const {
|
||||
ShouldNotReachHere();
|
||||
return Bytecodes::_shouldnotreachhere;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class Method : public Metadata {
|
||||
};
|
||||
u2 number_of_breakpoints() const {return 0;}
|
||||
#else // !INCLUDE_JVMTI
|
||||
- Bytecodes::Code orig_bytecode_at(int bci) const;
|
||||
+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const;
|
||||
void set_orig_bytecode_at(int bci, Bytecodes::Code code);
|
||||
void set_breakpoint(int bci);
|
||||
void clear_breakpoint(int bci);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a785a43d352..2321483dcbd 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1389,14 +1389,16 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
||||
|
||||
if (code == Bytecodes::_breakpoint) {
|
||||
int bci = method->bci_from(bcp);
|
||||
- code = method->orig_bytecode_at(bci);
|
||||
- java_code = Bytecodes::java_code(code);
|
||||
- if (code != java_code &&
|
||||
- (java_code == Bytecodes::_getfield ||
|
||||
- java_code == Bytecodes::_putfield ||
|
||||
- java_code == Bytecodes::_aload_0)) {
|
||||
- // Let breakpoint table handling unpatch bytecode
|
||||
- method->set_orig_bytecode_at(bci, java_code);
|
||||
+ code = method->orig_bytecode_at(bci, true);
|
||||
+ if (code != Bytecodes::_shouldnotreachhere) {
|
||||
+ java_code = Bytecodes::java_code(code);
|
||||
+ if (code != java_code &&
|
||||
+ (java_code == Bytecodes::_getfield ||
|
||||
+ java_code == Bytecodes::_putfield ||
|
||||
+ java_code == Bytecodes::_aload_0)) {
|
||||
+ // Let breakpoint table handling unpatch bytecode
|
||||
+ method->set_orig_bytecode_at(bci, java_code);
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
java_code = Bytecodes::java_code(code);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
From d3371d7d52bd4dc66efd4f6a946d5045b8bc8b2b Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 23 May 2020 10:17:56 +0200
|
||||
Subject: [PATCH 46/48] Fix comments according hotspot formatting conventions
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 191 +++++++-----------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 41 ++--
|
||||
2 files changed, 90 insertions(+), 142 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 2321483dcbd..8d00203fd9a 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -67,21 +67,19 @@ int VM_EnhancedRedefineClasses::_deleted_methods_length = 0;
|
||||
int VM_EnhancedRedefineClasses::_added_methods_length = 0;
|
||||
Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL;
|
||||
|
||||
-/**
|
||||
- * Create new instance of enhanced class redefiner.
|
||||
- *
|
||||
- * This class implements VM_GC_Operation - the usual usage should be:
|
||||
- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
- * VMThread::execute(&op);
|
||||
- * Which
|
||||
- *
|
||||
- * @param class_count size of class_defs
|
||||
- * @param class_defs class definition - either new class or redefined class
|
||||
- * note that this is not the final array of classes to be redefined
|
||||
- * we need to scan for all affected classes (e.g. subclasses) and
|
||||
- * caculcate redefinition for them as well.
|
||||
- * @param class_load_kind always jvmti_class_load_kind_redefine
|
||||
- */
|
||||
+//
|
||||
+// Create new instance of enhanced class redefiner.
|
||||
+//
|
||||
+// This class implements VM_GC_Operation - the usual usage should be:
|
||||
+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
+// VMThread::execute(&op);
|
||||
+// Which
|
||||
+// - class_count size of class_defs
|
||||
+// - class_defs class definition - either new class or redefined class
|
||||
+// note that this is not the final array of classes to be redefined
|
||||
+// we need to scan for all affected classes (e.g. subclasses) and
|
||||
+// caculcate redefinition for them as well.
|
||||
+// @param class_load_kind always jvmti_class_load_kind_redefine
|
||||
VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) :
|
||||
VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) {
|
||||
_affected_klasses = NULL;
|
||||
@@ -97,12 +95,10 @@ static inline InstanceKlass* get_ik(jclass def) {
|
||||
return InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Start the redefinition:
|
||||
- * - Load new class definitions - @see load_new_class_versions
|
||||
- * - Start mark&sweep GC.
|
||||
- * @return true if success, otherwise all chnages are rollbacked.
|
||||
- */
|
||||
+// Start the redefinition:
|
||||
+// - Load new class definitions - @see load_new_class_versions
|
||||
+// - Start mark&sweep GC.
|
||||
+// - true if success, otherwise all chnages are rollbacked.
|
||||
bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
|
||||
if (_class_count == 0) {
|
||||
@@ -175,9 +171,7 @@ bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Closer for static fields - copy value from old class to the new class.
|
||||
- */
|
||||
+// Closer for static fields - copy value from old class to the new class.
|
||||
class FieldCopier : public FieldClosure {
|
||||
public:
|
||||
void do_field(fieldDescriptor* fd) {
|
||||
@@ -236,9 +230,7 @@ struct StoreNoBarrier {
|
||||
template <class T> static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
-/**
|
||||
- Closure to scan all heap objects and update method handles
|
||||
-*/
|
||||
+// Closure to scan all heap objects and update method handles
|
||||
template <class S>
|
||||
class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// import java_lang_invoke_MemberName.*
|
||||
@@ -247,7 +239,6 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
|
||||
};
|
||||
|
||||
-
|
||||
bool update_member_name(oop obj) {
|
||||
int flags = java_lang_invoke_MemberName::flags(obj);
|
||||
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
|
||||
@@ -382,14 +373,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
}
|
||||
};
|
||||
|
||||
-/**
|
||||
- * Closure to scan all objects on heap for objects of changed classes
|
||||
- * - if the fields are compatible, only update class definition reference
|
||||
- * - otherwise if the new object size is smaller then old size, reshufle
|
||||
- * the fields and fill the gap with "dead_space"
|
||||
- * - otherwise set the _needs_instance_update flag, we need to do full GC
|
||||
- * and reshuffle object positions durring mark&sweep
|
||||
- */
|
||||
+// Closure to scan all objects on heap for objects of changed classes
|
||||
+// - if the fields are compatible, only update class definition reference
|
||||
+// - otherwise if the new object size is smaller then old size, reshufle
|
||||
+// the fields and fill the gap with "dead_space"
|
||||
+// - otherwise set the _needs_instance_update flag, we need to do full GC
|
||||
+// and reshuffle object positions durring mark&sweep
|
||||
class ChangePointersObjectClosure : public ObjectClosure {
|
||||
private:
|
||||
|
||||
@@ -451,19 +440,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
-/**
|
||||
- Main transformation method - runs in VM thread.
|
||||
-
|
||||
- - UseSharedSpaces - TODO what does it mean?
|
||||
- - for each sratch class call redefine_single_class
|
||||
- - clear code cache (flush_dependent_code)
|
||||
- - iterate the heap and update object defintions, check it old/new class fields
|
||||
- are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
- - iterate the heap and update method handles to new version
|
||||
- - Swap marks to have same hashcodes
|
||||
- - copy static fields
|
||||
- - notify JVM of the modification
|
||||
-*/
|
||||
+// Main transformation method - runs in VM thread.
|
||||
+// - UseSharedSpaces - TODO what does it mean?
|
||||
+// - for each sratch class call redefine_single_class
|
||||
+// - clear code cache (flush_dependent_code)
|
||||
+// - iterate the heap and update object defintions, check it old/new class fields
|
||||
+// are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
+// - iterate the heap and update method handles to new version
|
||||
+// - Swap marks to have same hashcodes
|
||||
+// - copy static fields
|
||||
+// - notify JVM of the modification
|
||||
void VM_EnhancedRedefineClasses::doit() {
|
||||
Thread *thread = Thread::current();
|
||||
|
||||
@@ -634,11 +620,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Cleanup - runs in JVM thread
|
||||
- * - free used memory
|
||||
- * - end GC
|
||||
- */
|
||||
+// Cleanup - runs in JVM thread
|
||||
+// - free used memory
|
||||
+// - end GC
|
||||
void VM_EnhancedRedefineClasses::doit_epilogue() {
|
||||
VM_GC_Operation::doit_epilogue();
|
||||
|
||||
@@ -670,11 +654,9 @@ void VM_EnhancedRedefineClasses::doit_epilogue() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Exclude java primitives and arrays from redefinition
|
||||
- * @param klass_mirror pointer to the klass
|
||||
- * @return true if is modifiable
|
||||
- */
|
||||
+// Exclude java primitives and arrays from redefinition
|
||||
+// - klass_mirror pointer to the klass
|
||||
+// - true if is modifiable
|
||||
bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
// classes for primitives cannot be redefined
|
||||
if (java_lang_Class::is_primitive(klass_mirror)) {
|
||||
@@ -693,17 +675,12 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
-
|
||||
- - find sorted affected classes
|
||||
- - resolve new class
|
||||
- - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
- - calculate modified fields and mapping to old fields
|
||||
- - link new classes
|
||||
-
|
||||
- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
-*/
|
||||
+// Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
+// - find sorted affected classes
|
||||
+// - resolve new class
|
||||
+// - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
+// - calculate modified fields and mapping to old fields
|
||||
+// - link new classes
|
||||
jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
|
||||
_affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(_class_count, true);
|
||||
@@ -898,9 +875,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Calculated the difference between new and old class (field change, method change, supertype change, ...).
|
||||
-*/
|
||||
+ // Calculated the difference between new and old class (field change, method change, supertype change, ...).
|
||||
int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) {
|
||||
int result = Klass::NoRedefinition;
|
||||
log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string());
|
||||
@@ -1183,14 +1158,11 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
}
|
||||
|
||||
|
||||
-/**
|
||||
- Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
-
|
||||
- @param the_class definition of a class, either existing class or new_class
|
||||
- @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
- @param class_byte_count - size of class_bytes
|
||||
- @param not_changed - new_class not available or same as current class
|
||||
-*/
|
||||
+// Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
+// - the_class definition of a class, either existing class or new_class
|
||||
+// - class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
+// - class_byte_count - size of class_bytes
|
||||
+// - not_changed - new_class not available or same as current class
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) {
|
||||
|
||||
*not_changed = false;
|
||||
@@ -1233,11 +1205,9 @@ jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Calculate difference between non static fields of old and new class and store the info into new class:
|
||||
- instanceKlass->store_update_information
|
||||
- instanceKlass->copy_backwards
|
||||
-*/
|
||||
+// Calculate difference between non static fields of old and new class and store the info into new class:
|
||||
+// instanceKlass->store_update_information
|
||||
+// instanceKlass->copy_backwards
|
||||
void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) {
|
||||
|
||||
class CalculateFieldUpdates : public FieldClosure {
|
||||
@@ -1348,9 +1318,7 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory.
|
||||
-*/
|
||||
+// Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory.
|
||||
void VM_EnhancedRedefineClasses::rollback() {
|
||||
log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res);
|
||||
ClassLoaderDataGraph::rollback_redefinition();
|
||||
@@ -1547,9 +1515,7 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Set method as obsolete / old / deleted.
|
||||
-*/
|
||||
+// Set method as obsolete / old / deleted.
|
||||
void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() {
|
||||
for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) {
|
||||
Method* old_method = _matching_old_methods[j];
|
||||
@@ -1771,12 +1737,9 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Compare _old_methods and _new_methods arrays and store the result into
|
||||
- _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
-
|
||||
- Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
-*/
|
||||
+// Compare _old_methods and _new_methods arrays and store the result into
|
||||
+// _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
+// Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
Method* old_method;
|
||||
Method* new_method;
|
||||
@@ -1900,7 +1863,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
-
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
// increment the classRedefinedCount field in the_class and in any
|
||||
@@ -1940,9 +1902,7 @@ void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Logging of all methods (old, new, changed, ...)
|
||||
- */
|
||||
+// Logging of all methods (old, new, changed, ...)
|
||||
void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
int j;
|
||||
log_trace(redefine, class, dump)("_old_methods --");
|
||||
@@ -2002,9 +1962,7 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
-*/
|
||||
+// Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
class AffectedKlassClosure : public KlassClosure {
|
||||
private:
|
||||
GrowableArray<Klass*>* _affected_klasses;
|
||||
@@ -2052,10 +2010,8 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
}
|
||||
};
|
||||
|
||||
-/**
|
||||
- Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
- Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
-*/
|
||||
+// Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
+// Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
for (int i = 0; i < _class_count; i++) {
|
||||
InstanceKlass* klass_handle = get_ik(_class_defs[i].klass);
|
||||
@@ -2086,9 +2042,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Pairs of class dependencies (for topological sort)
|
||||
-*/
|
||||
+// Pairs of class dependencies (for topological sort)
|
||||
struct KlassPair {
|
||||
const Klass* _left;
|
||||
const Klass* _right;
|
||||
@@ -2101,14 +2055,11 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
return elem._right == value;
|
||||
}
|
||||
|
||||
-/**
|
||||
- For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
- First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
- Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
- For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
-
|
||||
- TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
-*/
|
||||
+// For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
+// First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
+// Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
+// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
+// TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
ResourceMark mark(THREAD);
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 7e2afd49650..d8a11b51fe9 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -35,17 +35,16 @@
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
-/**
|
||||
- * Enhanced class redefiner.
|
||||
- *
|
||||
- * This class implements VM_GC_Operation - the usual usage should be:
|
||||
- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
- * VMThread::execute(&op);
|
||||
- * Which in turn runs:
|
||||
- * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions
|
||||
- * - doit() - main redefition, adjust existing objects on the heap, clear caches
|
||||
- * - doit_epilogue() - cleanup
|
||||
-*/
|
||||
+//
|
||||
+// Enhanced class redefiner.
|
||||
+//
|
||||
+// This class implements VM_GC_Operation - the usual usage should be:
|
||||
+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
+// VMThread::execute(&op);
|
||||
+// Which in turn runs:
|
||||
+// - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions
|
||||
+// - doit() - main redefition, adjust existing objects on the heap, clear caches
|
||||
+// - doit_epilogue() - cleanup
|
||||
class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
private:
|
||||
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
||||
@@ -93,17 +92,15 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
// These routines are roughly in call order unless otherwise noted.
|
||||
|
||||
- /**
|
||||
- Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
-
|
||||
- - find sorted affected classes
|
||||
- - resolve new class
|
||||
- - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
- - calculate modified fields and mapping to old fields
|
||||
- - link new classes
|
||||
-
|
||||
- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
- */
|
||||
+ // Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
+ //
|
||||
+ // - find sorted affected classes
|
||||
+ // - resolve new class
|
||||
+ // - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
+ // - calculate modified fields and mapping to old fields
|
||||
+ // - link new classes
|
||||
+ //
|
||||
+ // The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
jvmtiError load_new_class_versions(TRAPS);
|
||||
|
||||
// Searches for all affected classes and performs a sorting such tha
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 2ad306a4cce06cfccf95a1193daf5b968ec1fa87 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 24 May 2020 12:07:09 +0200
|
||||
Subject: [PATCH 47/48] Review threads, cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 8d00203fd9a..1fbba406087 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -253,7 +253,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// Note: we might set NULL at this point, which should force AbstractMethodError at runtime
|
||||
Thread *thread = Thread::current();
|
||||
CallInfo info(new_method, newest, thread);
|
||||
- Handle objHandle(thread, obj); // TODO : review thread
|
||||
+ Handle objHandle(thread, obj);
|
||||
MethodHandles::init_method_MemberName(objHandle, info);
|
||||
} else {
|
||||
java_lang_invoke_MemberName::set_method(obj, NULL);
|
||||
@@ -280,7 +280,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version());
|
||||
fieldDescriptor fd_new;
|
||||
if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
- Handle objHandle(Thread::current(), obj); // TODO : review thread
|
||||
+ Handle objHandle(Thread::current(), obj);
|
||||
MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind));
|
||||
} else {
|
||||
// Matching field is not found in new version, not much we can do here.
|
||||
@@ -441,10 +441,9 @@ public:
|
||||
|
||||
|
||||
// Main transformation method - runs in VM thread.
|
||||
-// - UseSharedSpaces - TODO what does it mean?
|
||||
-// - for each sratch class call redefine_single_class
|
||||
+// - for each scratch class call redefine_single_class
|
||||
// - clear code cache (flush_dependent_code)
|
||||
-// - iterate the heap and update object defintions, check it old/new class fields
|
||||
+// - iterate the heap and update object definitions, check it old/new class fields
|
||||
// are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
// - iterate the heap and update method handles to new version
|
||||
// - Swap marks to have same hashcodes
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From a5586aff03fde654102e2c2e1fc19fdea406b31e Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 24 May 2020 12:07:42 +0200
|
||||
Subject: [PATCH 48/48] Replace deleted method with
|
||||
Universe::throw_no_such_method_error
|
||||
|
||||
---
|
||||
.../share/prims/resolvedMethodTable.cpp | 28 +++++++++----------
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index 7741328979f..06581643c3b 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -261,25 +261,25 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
|
||||
if (old_method->is_old()) {
|
||||
|
||||
+ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
+ Method* newer_method;
|
||||
+
|
||||
// Method* new_method;
|
||||
if (old_method->is_deleted()) {
|
||||
- // FIXME:(DCEVM) - check if exception can be thrown
|
||||
- // new_method = Universe::throw_no_such_method_error();
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
- Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
+ newer_method = Universe::throw_no_such_method_error();
|
||||
+ } else {
|
||||
+ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
|
||||
- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
- assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
- assert(old_method != newer_method, "sanity check");
|
||||
+ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
+ assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
+ assert(old_method != newer_method, "sanity check");
|
||||
|
||||
- if (_the_table->lookup(newer_method) != NULL) {
|
||||
- // old method was already adjusted if new method exists in _the_table
|
||||
- continue;
|
||||
+ if (_the_table->lookup(newer_method) != NULL) {
|
||||
+ // old method was already adjusted if new method exists in _the_table
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/windows/scripts
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -16,104 +17,91 @@
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
# Environment variables:
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_win_x64
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
WORK_DIR=$(pwd)
|
||||
JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64}
|
||||
|
||||
function create_jbr {
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef" | "jfx_jcef")
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__modules_path=$2
|
||||
__modules=$3
|
||||
|
||||
[ -d $__bundle_name ] && rm -rf $__bundle_name
|
||||
|
||||
echo Running jlink ...
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
if [[ "${bundle_type}" == *jcef* ]]
|
||||
then
|
||||
cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin
|
||||
fi
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release
|
||||
--module-path $__modules_path --no-man-pages --compress=2 \
|
||||
--add-modules $__modules --output $__bundle_name || do_exit $?
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
WORK_DIR=$(pwd)
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=windows-x86_64-server-release
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
echo "Excluding jcef modules"
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
echo "Excluding jfx modules"
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
;;
|
||||
"fd")
|
||||
do_reset_changes=1
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
|
||||
RELEASE_NAME=windows-x86_64-server-fastdebug
|
||||
;;
|
||||
esac
|
||||
|
||||
PATH="/usr/local/bin:/usr/bin:${PATH}"
|
||||
sh ./configure \
|
||||
--disable-warnings-as-errors \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-version-pre= \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-toolchain-version=$TOOLCHAIN_VERSION \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || do_exit $?
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
bash ./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-target-bits=64 \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-toolchain-version=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $?
|
||||
else
|
||||
bash ./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-target-bits=64 \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=${WORK_DIR}/modular-sdk \
|
||||
--with-toolchain-version=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
make LOG=info CONF=$RELEASE_NAME clean images || do_exit $?
|
||||
fi
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1
|
||||
else
|
||||
make LOG=info images CONF=windows-x86_64-server-release || exit 1
|
||||
fi
|
||||
|
||||
JSDK=build/windows-x86_64-server-release/images/jdk
|
||||
if [[ "$bundle_type" == "*jcef*" || -z "$bundle_type" ]]; then
|
||||
JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number}
|
||||
fi
|
||||
BASE_DIR=build/windows-x86_64-server-release/images
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1
|
||||
if [[ "$bundle_type" == "*jcef*" ]]; then
|
||||
cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $?
|
||||
update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $?
|
||||
cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged
|
||||
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
fi
|
||||
create_jbr ${bundle_type}
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
#JBR_BUNDLE=jbr_${bundle_type}_lw
|
||||
#create_jbr ${bundle_type}_lw
|
||||
# create sdk image bundle
|
||||
modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g)
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
do_exit 0
|
||||
@@ -4,9 +4,6 @@
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -21,30 +18,39 @@ JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
WORK_DIR=$(pwd)
|
||||
|
||||
[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?)
|
||||
|
||||
PATH="/usr/local/bin:/usr/bin:${PATH}"
|
||||
./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--disable-debug-symbols \
|
||||
--with-target-bits=32 \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-toolchain-version=2015 \
|
||||
--with-toolchain-version=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
make clean CONF=windows-x86-normal-server-release || exit 1
|
||||
make LOG=info images CONF=windows-x86-normal-server-release test-image || exit 1
|
||||
make clean CONF=windows-x86-server-release || exit 1
|
||||
make LOG=info images CONF=windows-x86-server-release test-image || exit 1
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-windows-x86-b${build_number}
|
||||
BASE_DIR=build/windows-x86-normal-server-release/images
|
||||
BASE_DIR=build/windows-x86-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1
|
||||
sed 's/JBR/JBRSDK/g' ${JSDK}/release > release
|
||||
mv release ${JBRSDK_BUNDLE}/release
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
@@ -54,4 +60,4 @@ ${JSDK}/bin/jlink \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release
|
||||
#grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies udate release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the bundles without any additional modules (jcef)
|
||||
# jcef - the bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -17,6 +18,8 @@
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
@@ -24,56 +27,51 @@ bundle_type=$4
|
||||
|
||||
function pack_jbr {
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
;;
|
||||
"jfx_jcef" | "")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
;;
|
||||
*)
|
||||
echo "***ERR*** bundle was not specified" && exit 1
|
||||
;;
|
||||
esac
|
||||
if [ -z "${bundle_type}" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
[ -d ${BASE_DIR}/jbr ] && rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION}
|
||||
|
||||
JBR=$JBR_BASE_NAME-windows-x64-b$build_number
|
||||
echo Creating $JBR.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
|
||||
/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1
|
||||
#rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || do_exit $?
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
RELEASE_NAME=windows-x86_64-server-release
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number}
|
||||
case "$bundle_type" in
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
;;
|
||||
"fd")
|
||||
RELEASE_NAME=macosx-x86_64-server-fastdebug
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number}
|
||||
;;
|
||||
esac
|
||||
|
||||
IMAGES_DIR=build/windows-x86_64-server-release/images
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1
|
||||
[ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz"
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || do_exit $?
|
||||
fi
|
||||
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
pack_jbr $bundle_type
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1
|
||||
/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
fi
|
||||
@@ -4,9 +4,6 @@
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
@@ -24,7 +21,7 @@ build_number=$3
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
IMAGES_DIR=build/windows-x86-normal-server-release/images
|
||||
IMAGES_DIR=build/windows-x86-server-release/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
@@ -242,6 +242,16 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
)
|
||||
|
||||
JDK_SYMBOLS_BUNDLE_FILES := \
|
||||
$(filter \
|
||||
$(JDK_SYMBOLS_EXCLUDE_PATTERN) \
|
||||
$(SYMBOLS_EXCLUDE_PATTERN) \
|
||||
, \
|
||||
$(filter-out \
|
||||
$(JDK_IMAGE_HOMEDIR)/demo/% %.stripped.pdb \
|
||||
, \
|
||||
$(ALL_JDK_SYMBOLS_FILES) \
|
||||
) \
|
||||
) \
|
||||
$(call FindFiles, $(SYMBOLS_IMAGE_DIR))
|
||||
|
||||
TEST_DEMOS_BUNDLE_FILES := $(filter $(JDK_DEMOS_IMAGE_HOMEDIR)/demo/%, \
|
||||
@@ -373,7 +383,7 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
$(eval $(call SetupBundleFile, BUILD_JDK_SYMBOLS_BUNDLE, \
|
||||
BUNDLE_NAME := $(JDK_SYMBOLS_BUNDLE_NAME), \
|
||||
FILES := $(JDK_SYMBOLS_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(SYMBOLS_IMAGE_DIR), \
|
||||
BASE_DIRS := $(JDK_SYMBOLS_IMAGE_DIR) $(wildcard $(SYMBOLS_IMAGE_DIR)), \
|
||||
SUBDIR := $(JDK_BUNDLE_SUBDIR), \
|
||||
UNZIP_DEBUGINFO := true, \
|
||||
))
|
||||
@@ -410,43 +420,17 @@ endif
|
||||
|
||||
################################################################################
|
||||
|
||||
ifneq ($(filter docs-jdk-bundles, $(MAKECMDGOALS)), )
|
||||
DOCS_JDK_BUNDLE_FILES := $(call FindFiles, $(DOCS_JDK_IMAGE_DIR))
|
||||
ifneq ($(filter docs-bundles, $(MAKECMDGOALS)), )
|
||||
DOCS_BUNDLE_FILES := $(call FindFiles, $(DOCS_IMAGE_DIR))
|
||||
|
||||
$(eval $(call SetupBundleFile, BUILD_DOCS_JDK_BUNDLE, \
|
||||
BUNDLE_NAME := $(DOCS_JDK_BUNDLE_NAME), \
|
||||
FILES := $(DOCS_JDK_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(DOCS_JDK_IMAGE_DIR), \
|
||||
$(eval $(call SetupBundleFile, BUILD_DOCS_BUNDLE, \
|
||||
BUNDLE_NAME := $(DOCS_BUNDLE_NAME), \
|
||||
FILES := $(DOCS_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(DOCS_IMAGE_DIR), \
|
||||
SUBDIR := docs, \
|
||||
))
|
||||
|
||||
DOCS_JDK_TARGETS += $(BUILD_DOCS_JDK_BUNDLE)
|
||||
endif
|
||||
|
||||
ifneq ($(filter docs-javase-bundles, $(MAKECMDGOALS)), )
|
||||
DOCS_JAVASE_BUNDLE_FILES := $(call FindFiles, $(DOCS_JAVASE_IMAGE_DIR))
|
||||
|
||||
$(eval $(call SetupBundleFile, BUILD_DOCS_JAVASE_BUNDLE, \
|
||||
BUNDLE_NAME := $(DOCS_JAVASE_BUNDLE_NAME), \
|
||||
FILES := $(DOCS_JAVASE_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(DOCS_JAVASE_IMAGE_DIR), \
|
||||
SUBDIR := docs-javase, \
|
||||
))
|
||||
|
||||
DOCS_JAVASE_TARGETS += $(BUILD_DOCS_JAVASE_BUNDLE)
|
||||
endif
|
||||
|
||||
ifneq ($(filter docs-reference-bundles, $(MAKECMDGOALS)), )
|
||||
DOCS_REFERENCE_BUNDLE_FILES := $(call FindFiles, $(DOCS_REFERENCE_IMAGE_DIR))
|
||||
|
||||
$(eval $(call SetupBundleFile, BUILD_DOCS_REFERENCE_BUNDLE, \
|
||||
BUNDLE_NAME := $(DOCS_REFERENCE_BUNDLE_NAME), \
|
||||
FILES := $(DOCS_REFERENCE_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(DOCS_REFERENCE_IMAGE_DIR), \
|
||||
SUBDIR := docs-reference, \
|
||||
))
|
||||
|
||||
DOCS_REFERENCE_TARGETS += $(BUILD_DOCS_REFERENCE_BUNDLE)
|
||||
DOCS_TARGETS += $(BUILD_DOCS_BUNDLE)
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
@@ -495,12 +479,9 @@ $(eval $(call IncludeCustomExtension, Bundles.gmk))
|
||||
product-bundles: $(PRODUCT_TARGETS)
|
||||
legacy-bundles: $(LEGACY_TARGETS)
|
||||
test-bundles: $(TEST_TARGETS)
|
||||
docs-jdk-bundles: $(DOCS_JDK_TARGETS)
|
||||
docs-javase-bundles: $(DOCS_JAVASE_TARGETS)
|
||||
docs-reference-bundles: $(DOCS_REFERENCE_TARGETS)
|
||||
docs-bundles: $(DOCS_TARGETS)
|
||||
static-libs-bundles: $(STATIC_LIBS_TARGETS)
|
||||
jcov-bundles: $(JCOV_TARGETS)
|
||||
|
||||
.PHONY: all default product-bundles test-bundles \
|
||||
docs-jdk-bundles docs-javase-bundles docs-reference-bundles \
|
||||
.PHONY: all default product-bundles test-bundles docs-bundles \
|
||||
static-libs-bundles jcov-bundles
|
||||
|
||||
@@ -52,6 +52,7 @@ TARGETS =
|
||||
# READMEs and other files.
|
||||
|
||||
DEMO_SHARE_SRC := $(TOPDIR)/src/demo/share
|
||||
GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc
|
||||
|
||||
DEMO_MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ define SetupInterimModule
|
||||
EXCLUDE_FILES := $(TOPDIR)/src/$1/share/classes/module-info.java \
|
||||
Standard.java, \
|
||||
EXTRA_FILES := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim/module-info.java, \
|
||||
COPY := .gif .png .xml .css .js .txt javax.tools.JavaCompilerTool, \
|
||||
COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_langtools_modules/$1.interim, \
|
||||
DISABLED_WARNINGS := module options, \
|
||||
JAVAC_FLAGS := \
|
||||
|
||||
@@ -76,7 +76,6 @@ java.datatransfer_COPY += flavormap.properties
|
||||
|
||||
################################################################################
|
||||
|
||||
java.desktop_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
java.desktop_DOCLINT += -Xdoclint:all/protected,-reference \
|
||||
'-Xdoclint/package:java.*,javax.*'
|
||||
java.desktop_COPY += .gif .png .wav .txt .xml .css .pf
|
||||
@@ -184,6 +183,10 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
java.desktop_EXCLUDES += com/sun/java/swing/plaf/gtk
|
||||
endif
|
||||
|
||||
ifdef BUILD_HEADLESS_ONLY
|
||||
java.desktop_EXCLUDES += sun/applet
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows macosx), false)
|
||||
java.desktop_EXCLUDE_FILES += sun/awt/AWTCharset.java
|
||||
endif
|
||||
@@ -295,10 +298,6 @@ java.xml.crypto_CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.accessibility_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.charsets_COPY += .dat
|
||||
|
||||
################################################################################
|
||||
@@ -344,23 +343,14 @@ jdk.dynalink_CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.javadoc_COPY += .xml .css .js .png .txt
|
||||
jdk.javadoc_COPY += .xml .css .js .png
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.jartool_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
jdk.jartool_JAVAC_FLAGS += -XDstringConcat=inline
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.httpserver_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.unsupported.desktop_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
# No SCTP implementation on Mac OS X or AIX. These classes should be excluded.
|
||||
SCTP_IMPL_CLASSES = \
|
||||
$(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \
|
||||
@@ -385,11 +375,11 @@ endif
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.jpackage_COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||
jdk.incubator.jpackage_COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \
|
||||
.icns .scpt .wxs .wxl .wxi .ico .bmp .tiff
|
||||
|
||||
jdk.jpackage_CLEAN += .properties
|
||||
jdk.incubator.jpackage_CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -487,7 +477,6 @@ jdk.internal.vm.compiler_EXCLUDES += \
|
||||
org.graalvm.compiler.options.test \
|
||||
org.graalvm.compiler.phases.common.test \
|
||||
org.graalvm.compiler.processor \
|
||||
org.graalvm.compiler.replacements.jdk10.test \
|
||||
org.graalvm.compiler.replacements.jdk12.test \
|
||||
org.graalvm.compiler.replacements.jdk9.test \
|
||||
org.graalvm.compiler.replacements.processor \
|
||||
@@ -542,10 +531,6 @@ jdk.jfr_DISABLED_WARNINGS += exports
|
||||
jdk.jfr_COPY := .xsd .xml .dtd
|
||||
jdk.jfr_JAVAC_FLAGS := -XDstringConcat=inline
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.incubator.vector_DOCLINT += -Xdoclint:all/protected
|
||||
|
||||
################################################################################
|
||||
# If this is an imported module that has prebuilt classes, only compile
|
||||
# module-info.java.
|
||||
|
||||
@@ -33,20 +33,8 @@ include JavaCompilation.gmk
|
||||
|
||||
TOOLS_CLASSES_DIR := $(BUILDTOOLS_OUTPUTDIR)/tools_jigsaw_classes
|
||||
|
||||
# When using an external BUILDJDK, make it possible to shortcut building of
|
||||
# these tools using the BUILD_JAVAC instead of having to build the complete
|
||||
# exploded image first.
|
||||
ifeq ($(EXTERNAL_BUILDJDK), true)
|
||||
COMPILER := buildjdk
|
||||
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK)
|
||||
else
|
||||
COMPILER := interim
|
||||
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED)
|
||||
endif
|
||||
|
||||
$(eval $(call SetupJavaCompilation, BUILD_JIGSAW_TOOLS, \
|
||||
TARGET_RELEASE := $(TARGET_RELEASE), \
|
||||
COMPILER := $(COMPILER), \
|
||||
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \
|
||||
SRC := $(TOPDIR)/make/jdk/src/classes, \
|
||||
INCLUDES := build/tools/deps \
|
||||
build/tools/docs \
|
||||
|
||||
@@ -36,24 +36,6 @@ TARGETS :=
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
$(eval $(call IncludeCustomExtension, hotspot/CompileTools.gmk))
|
||||
|
||||
################################################################################
|
||||
# Build tools needed for the JFR source code generation
|
||||
|
||||
HOTSPOT_TOOLS_SRCDIR := $(TOPDIR)/make/src/classes
|
||||
|
||||
HOTSPOT_TOOLS_OUTPUTDIR := $(BUILDTOOLS_OUTPUTDIR)/buildtools/hotspot_tools_classes
|
||||
|
||||
$(eval $(call SetupJavaCompilation, BUILD_TOOLS_HOTSPOT, \
|
||||
COMPILER := bootjdk, \
|
||||
SRC := $(HOTSPOT_TOOLS_SRCDIR), \
|
||||
BIN := $(HOTSPOT_TOOLS_OUTPUTDIR), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_TOOLS_HOTSPOT)
|
||||
|
||||
|
||||
################################################################################
|
||||
# Graal build tools
|
||||
ifeq ($(INCLUDE_GRAAL), true)
|
||||
VM_CI_SRC_DIR := $(TOPDIR)/src/jdk.internal.vm.ci/share/classes
|
||||
|
||||
|
||||
@@ -56,8 +56,7 @@ $(eval $(call SetupJavaCompilation, BUILD_TOOLS_JDK, \
|
||||
DISABLED_WARNINGS := options, \
|
||||
JAVAC_FLAGS := \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.base/sun.text=ALL-UNNAMED \
|
||||
--add-exports java.base/sun.security.util=ALL-UNNAMED, \
|
||||
--add-exports java.base/sun.text=ALL-UNNAMED, \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_TOOLS_JDK)
|
||||
|
||||
@@ -63,7 +63,7 @@ MODULES_SOURCE_PATH := $(call PathList, $(call GetModuleSrcPath) )
|
||||
JAVADOC_BASE_URL := https://docs.oracle.com/pls/topic/lookup?ctx=javase$(VERSION_NUMBER)&id=homepage
|
||||
BUG_SUBMIT_URL := https://bugreport.java.com/bugreport/
|
||||
COPYRIGHT_URL := legal/copyright.html
|
||||
LICENSE_URL := https://www.oracle.com/java/javase/terms/license/java$(VERSION_NUMBER)speclicense.html
|
||||
LICENSE_URL := https://www.oracle.com/technetwork/java/javase/terms/license/java$(VERSION_NUMBER)speclicense.html
|
||||
REDISTRIBUTION_URL := https://www.oracle.com/technetwork/java/redist-137594.html
|
||||
|
||||
# In order to get a specific ordering it's necessary to specify the total
|
||||
@@ -298,8 +298,6 @@ define SetupApiDocsGenerationBody
|
||||
# Create a string like "-Xdoclint:all,-syntax,-html,..."
|
||||
$1_OPTIONS += -Xdoclint:all,$$(call CommaList, $$(addprefix -, \
|
||||
$$(JAVADOC_DISABLED_DOCLINT)))
|
||||
# Ignore the doclint warnings in the W3C DOM package
|
||||
$1_OPTIONS += -Xdoclint/package:-org.w3c.*
|
||||
|
||||
$1_DOC_TITLE := $$($1_LONG_NAME)<br>Version $$(VERSION_SPECIFICATION) API \
|
||||
Specification
|
||||
@@ -458,7 +456,7 @@ $(eval $(call SetupApiDocsGeneration, JAVASE_API, \
|
||||
MODULES := $(JAVASE_MODULES), \
|
||||
SHORT_NAME := $(JAVASE_SHORT_NAME), \
|
||||
LONG_NAME := $(JAVASE_LONG_NAME), \
|
||||
TARGET_DIR := $(DOCS_JAVASE_IMAGE_DIR)/api, \
|
||||
TARGET_DIR := $(IMAGES_OUTPUTDIR)/javase-docs/api, \
|
||||
))
|
||||
|
||||
# Targets generated are returned in JAVASE_API_JAVADOC_TARGETS and
|
||||
@@ -476,7 +474,7 @@ $(eval $(call SetupApiDocsGeneration, REFERENCE_API, \
|
||||
MODULES := $(JAVASE_MODULES), \
|
||||
SHORT_NAME := $(JAVASE_SHORT_NAME), \
|
||||
LONG_NAME := $(JAVASE_LONG_NAME), \
|
||||
TARGET_DIR := $(DOCS_REFERENCE_IMAGE_DIR)/api, \
|
||||
TARGET_DIR := $(IMAGES_OUTPUTDIR)/reference-docs/api, \
|
||||
JAVADOC_CMD := $(JAVADOC), \
|
||||
OPTIONS := $(REFERENCE_OPTIONS), \
|
||||
TAGS := $(REFERENCE_TAGS), \
|
||||
|
||||
@@ -101,9 +101,9 @@ help:
|
||||
$(info $(_) # method is 'auto', 'ignore' or 'fail' (default))
|
||||
$(info $(_) TEST="test1 ..." # Use the given test descriptor(s) for testing, e.g.)
|
||||
$(info $(_) # make test TEST="jdk_lang gtest:all")
|
||||
$(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness, use 'help' to list)
|
||||
$(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness, use 'help' to list)
|
||||
$(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness, use 'help' to list)
|
||||
$(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness)
|
||||
$(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness)
|
||||
$(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness)
|
||||
$(info $(_) TEST_OPTS="OPT1=x;..." # Generic control of all test harnesses)
|
||||
$(info $(_) TEST_VM_OPTS="ARG ..." # Same as setting TEST_OPTS to VM_OPTIONS="ARG ...")
|
||||
$(info )
|
||||
|
||||
@@ -238,7 +238,6 @@ endif
|
||||
ALL_JDK_MODULES := $(JDK_MODULES)
|
||||
ALL_JRE_MODULES := $(sort $(JRE_MODULES), $(foreach m, $(JRE_MODULES), \
|
||||
$(call FindTransitiveDepsForModule, $m)))
|
||||
ALL_SYMBOLS_MODULES := $(JDK_MODULES)
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBS_TARGET_SUBDIR := bin
|
||||
@@ -294,7 +293,6 @@ SetupCopyDebuginfo = \
|
||||
# implementation above.
|
||||
$(call SetupCopyDebuginfo,JDK)
|
||||
$(call SetupCopyDebuginfo,JRE)
|
||||
$(call SetupCopyDebuginfo,SYMBOLS)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ ifeq ($(HAS_SPEC),)
|
||||
COMPARE_BUILD="$(COMPARE_BUILD)" pre-compare-build && \
|
||||
$(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -j 1 -f $(topdir)/make/Init.gmk \
|
||||
SPEC=$(spec) HAS_SPEC=true $(MAKE_INIT_WITH_SPEC_ARGUMENTS) \
|
||||
COMPARE_BUILD="$(COMPARE_BUILD):NODRYRUN=true" main && \
|
||||
COMPARE_BUILD="$(COMPARE_BUILD)" main && \
|
||||
$(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -f $(topdir)/make/Init.gmk \
|
||||
SPEC=$(spec) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) \
|
||||
COMPARE_BUILD="$(COMPARE_BUILD)" post-compare-build && \
|
||||
|
||||
@@ -350,9 +350,6 @@ else # $(HAS_SPEC)=true
|
||||
$$(if $$(filter FAIL=%, $$(part)), \
|
||||
$$(eval COMPARE_BUILD_FAIL=$$(strip $$(subst +, , $$(patsubst FAIL=%, %, $$(part))))) \
|
||||
) \
|
||||
$$(if $$(filter NODRYRUN=%, $$(part)), \
|
||||
$$(eval COMPARE_BUILD_NODRYRUN=$$(strip $$(subst +, , $$(patsubst NODRYRUN=%, %, $$(part))))) \
|
||||
) \
|
||||
)
|
||||
else
|
||||
# Separate handling for single field case, to allow for spaces in values.
|
||||
@@ -375,11 +372,9 @@ else # $(HAS_SPEC)=true
|
||||
else ifeq ($$(wildcard $$(COMPARE_BUILD_PATCH)), )
|
||||
$$(error Patch file $$(COMPARE_BUILD_PATCH) does not exist)
|
||||
endif
|
||||
ifneq ($$(COMPARE_BUILD_NODRYRUN), true)
|
||||
PATCH_DRY_RUN := $$(shell cd $$(topdir) && $$(PATCH) --dry-run -p1 < $$(COMPARE_BUILD_PATCH) > /dev/null 2>&1 || $$(ECHO) FAILED)
|
||||
ifeq ($$(PATCH_DRY_RUN), FAILED)
|
||||
$$(error Patch file $$(COMPARE_BUILD_PATCH) does not apply cleanly)
|
||||
endif
|
||||
PATCH_DRY_RUN := $$(shell cd $$(topdir) && $$(PATCH) --dry-run -p1 < $$(COMPARE_BUILD_PATCH) > /dev/null 2>&1 || $$(ECHO) FAILED)
|
||||
ifeq ($$(PATCH_DRY_RUN), FAILED)
|
||||
$$(error Patch file $$(COMPARE_BUILD_PATCH) does not apply cleanly)
|
||||
endif
|
||||
endif
|
||||
ifneq ($$(COMPARE_BUILD_FAIL), true)
|
||||
|
||||
@@ -38,8 +38,11 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
|
||||
MACOSX_PLIST_SRC := $(TOPDIR)/make/data/bundle
|
||||
|
||||
BUNDLE_ID := $(MACOSX_BUNDLE_ID_BASE).$(VERSION_SHORT)
|
||||
BUNDLE_NAME := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_SHORT)
|
||||
BUNDLE_INFO := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_STRING)
|
||||
BUNDLE_PLATFORM_VERSION := $(VERSION_FEATURE).$(VERSION_INTERIM)
|
||||
BUNDLE_VERSION := $(VERSION_NUMBER)
|
||||
ifeq ($(COMPANY_NAME), N/A)
|
||||
BUNDLE_VENDOR := UNDEFINED
|
||||
else
|
||||
@@ -72,26 +75,24 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
SOURCE_FILES := $(MACOSX_PLIST_SRC)/JDK-Info.plist, \
|
||||
OUTPUT_FILE := $(JDK_MACOSX_CONTENTS_DIR)/Info.plist, \
|
||||
REPLACEMENTS := \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).jdk ; \
|
||||
@@ID@@ => $(BUNDLE_ID).jdk ; \
|
||||
@@NAME@@ => $(BUNDLE_NAME) ; \
|
||||
@@INFO@@ => $(BUNDLE_INFO) ; \
|
||||
@@VERSION@@ => $(VERSION_NUMBER) ; \
|
||||
@@BUILD_VERSION@@ => $(MACOSX_BUNDLE_BUILD_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) ; \
|
||||
@@MACOSX_VERSION_MIN@@ => $(MACOSX_VERSION_MIN) , \
|
||||
@@PLATFORM_VERSION@@ => $(BUNDLE_PLATFORM_VERSION) ; \
|
||||
@@VERSION@@ => $(BUNDLE_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) , \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTextFileProcessing, BUILD_JRE_PLIST, \
|
||||
SOURCE_FILES := $(MACOSX_PLIST_SRC)/JRE-Info.plist, \
|
||||
OUTPUT_FILE := $(JRE_MACOSX_CONTENTS_DIR)/Info.plist, \
|
||||
REPLACEMENTS := \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).jre ; \
|
||||
@@ID@@ => $(BUNDLE_ID).jre ; \
|
||||
@@NAME@@ => $(BUNDLE_NAME) ; \
|
||||
@@INFO@@ => $(BUNDLE_INFO) ; \
|
||||
@@VERSION@@ => $(VERSION_NUMBER) ; \
|
||||
@@BUILD_VERSION@@ => $(BUNDLE_BUILD_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) ; \
|
||||
@@MACOSX_VERSION_MIN@@ => $(MACOSX_VERSION_MIN) , \
|
||||
@@PLATFORM_VERSION@@ => $(BUNDLE_PLATFORM_VERSION) ; \
|
||||
@@VERSION@@ => $(BUNDLE_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) , \
|
||||
))
|
||||
|
||||
$(SUPPORT_OUTPUTDIR)/images/_jdk_bundle_attribute_set: $(COPY_JDK_IMAGE)
|
||||
|
||||
@@ -90,6 +90,7 @@ $(eval $(call SetupTarget, buildtools-jdk, \
|
||||
|
||||
$(eval $(call SetupTarget, buildtools-modules, \
|
||||
MAKEFILE := CompileModuleTools, \
|
||||
DEPS := exploded-image-base, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, buildtools-hotspot, \
|
||||
@@ -111,6 +112,7 @@ $(eval $(call SetupTarget, generate-exported-symbols, \
|
||||
$(eval $(call DeclareRecipesForPhase, GENSRC, \
|
||||
TARGET_SUFFIX := gensrc-src, \
|
||||
FILE_PREFIX := Gensrc, \
|
||||
MAKE_SUBDIR := gensrc, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
))
|
||||
|
||||
@@ -148,6 +150,7 @@ ALL_TARGETS += $(GENSRC_TARGETS)
|
||||
$(eval $(call DeclareRecipesForPhase, GENDATA, \
|
||||
TARGET_SUFFIX := gendata, \
|
||||
FILE_PREFIX := Gendata, \
|
||||
MAKE_SUBDIR := gendata, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
))
|
||||
|
||||
@@ -158,6 +161,7 @@ ALL_TARGETS += $(GENDATA_TARGETS)
|
||||
$(eval $(call DeclareRecipesForPhase, COPY, \
|
||||
TARGET_SUFFIX := copy, \
|
||||
FILE_PREFIX := Copy, \
|
||||
MAKE_SUBDIR := copy, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
))
|
||||
|
||||
@@ -199,6 +203,7 @@ ALL_TARGETS += $(JAVA_TARGETS)
|
||||
$(eval $(call DeclareRecipesForPhase, LIBS, \
|
||||
TARGET_SUFFIX := libs, \
|
||||
FILE_PREFIX := Lib, \
|
||||
MAKE_SUBDIR := lib, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
))
|
||||
|
||||
@@ -211,6 +216,7 @@ ALL_TARGETS += $(LIBS_TARGETS)
|
||||
$(eval $(call DeclareRecipesForPhase, STATIC_LIBS, \
|
||||
TARGET_SUFFIX := static-libs, \
|
||||
FILE_PREFIX := Lib, \
|
||||
MAKE_SUBDIR := lib, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
EXTRA_ARGS := STATIC_LIBS=true, \
|
||||
))
|
||||
@@ -222,6 +228,7 @@ ALL_TARGETS += $(STATIC_LIBS_TARGETS)
|
||||
$(eval $(call DeclareRecipesForPhase, LAUNCHER, \
|
||||
TARGET_SUFFIX := launchers, \
|
||||
FILE_PREFIX := Launcher, \
|
||||
MAKE_SUBDIR := launcher, \
|
||||
CHECK_MODULES := $(ALL_MODULES), \
|
||||
))
|
||||
|
||||
@@ -338,7 +345,7 @@ $(eval $(call SetupTarget, test-image-demos-jdk, \
|
||||
|
||||
$(eval $(call SetupTarget, generate-summary, \
|
||||
MAKEFILE := GenerateModuleSummary, \
|
||||
DEPS := jmods buildtools-modules runnable-buildjdk, \
|
||||
DEPS := jmods buildtools-modules, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
@@ -468,7 +475,7 @@ $(eval $(call SetupTarget, docs-jdk-api-javadoc, \
|
||||
$(eval $(call SetupTarget, docs-jdk-api-modulegraph, \
|
||||
MAKEFILE := Docs, \
|
||||
TARGET := docs-jdk-api-modulegraph, \
|
||||
DEPS := buildtools-modules runnable-buildjdk, \
|
||||
DEPS := exploded-image buildtools-modules, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-javase-api-javadoc, \
|
||||
@@ -479,7 +486,7 @@ $(eval $(call SetupTarget, docs-javase-api-javadoc, \
|
||||
$(eval $(call SetupTarget, docs-javase-api-modulegraph, \
|
||||
MAKEFILE := Docs, \
|
||||
TARGET := docs-javase-api-modulegraph, \
|
||||
DEPS := buildtools-modules runnable-buildjdk, \
|
||||
DEPS := exploded-image buildtools-modules, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-reference-api-javadoc, \
|
||||
@@ -490,7 +497,7 @@ $(eval $(call SetupTarget, docs-reference-api-javadoc, \
|
||||
$(eval $(call SetupTarget, docs-reference-api-modulegraph, \
|
||||
MAKEFILE := Docs, \
|
||||
TARGET := docs-reference-api-modulegraph, \
|
||||
DEPS := buildtools-modules runnable-buildjdk, \
|
||||
DEPS := exploded-image buildtools-modules, \
|
||||
))
|
||||
|
||||
# The gensrc steps for jdk.jdi create html spec files.
|
||||
@@ -633,20 +640,6 @@ $(eval $(call SetupTarget, test-image-jdk-jtreg-native, \
|
||||
DEPS := build-test-jdk-jtreg-native, \
|
||||
))
|
||||
|
||||
# Native files needed by the testlib
|
||||
$(eval $(call SetupTarget, build-test-lib-native, \
|
||||
MAKEFILE := test/BuildTestLibNative, \
|
||||
TARGET := build-test-lib-native, \
|
||||
DEPS := buildtools-jdk java.base-libs, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, test-image-lib-native, \
|
||||
MAKEFILE := test/BuildTestLibNative, \
|
||||
TARGET := test-image-lib-native, \
|
||||
DEPS := build-test-lib-native, \
|
||||
))
|
||||
|
||||
# Native files needed when testing the testlib itself
|
||||
$(eval $(call SetupTarget, build-test-libtest-jtreg-native, \
|
||||
MAKEFILE := test/JtregNativeLibTest, \
|
||||
TARGET := build-test-libtest-jtreg-native, \
|
||||
@@ -748,24 +741,12 @@ $(eval $(call SetupTarget, test-bundles, \
|
||||
DEPS := test-image, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-jdk-bundles, \
|
||||
$(eval $(call SetupTarget, docs-bundles, \
|
||||
MAKEFILE := Bundles, \
|
||||
TARGET := docs-jdk-bundles, \
|
||||
TARGET := docs-bundles, \
|
||||
DEPS := docs-image, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-javase-bundles, \
|
||||
MAKEFILE := Bundles, \
|
||||
TARGET := docs-javase-bundles, \
|
||||
DEPS := docs-javase-image, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-reference-bundles, \
|
||||
MAKEFILE := Bundles, \
|
||||
TARGET := docs-reference-bundles, \
|
||||
DEPS := docs-reference-image, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, static-libs-bundles, \
|
||||
MAKEFILE := Bundles, \
|
||||
TARGET := static-libs-bundles, \
|
||||
@@ -823,7 +804,7 @@ else
|
||||
|
||||
# Declare dependencies between hotspot-<variant>* targets
|
||||
$(foreach v, $(JVM_VARIANTS), \
|
||||
$(eval hotspot-$v-gensrc: java.base-copy buildtools-hotspot) \
|
||||
$(eval hotspot-$v-gensrc: java.base-copy) \
|
||||
$(eval hotspot-$v-libs: hotspot-$v-gensrc java.base-copy) \
|
||||
)
|
||||
|
||||
@@ -956,13 +937,10 @@ else
|
||||
$(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): java.base-libs java.base-copy \
|
||||
java.base-gendata jdk.jlink-launchers java
|
||||
endif
|
||||
else ifeq ($(EXTERNAL_BUILDJDK), false)
|
||||
# The normal non cross compilation usecase needs to wait for the full
|
||||
else
|
||||
# The normal non cross compilation case uses needs to wait for the full
|
||||
# exploded-image to avoid a race with the optimize target.
|
||||
$(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): exploded-image
|
||||
# The buildtools-modules are used for the exploded-image-optimize target,
|
||||
# but can be built either using the exploded-image or an external BUILDJDK.
|
||||
buildtools-modules: exploded-image-base
|
||||
endif
|
||||
|
||||
# All modules include the main license files from java.base.
|
||||
@@ -1083,18 +1061,6 @@ ifneq ($(COMPILE_TYPE), cross)
|
||||
exploded-image: exploded-image-optimize
|
||||
endif
|
||||
|
||||
# The runnable-buildjdk target guarantees that the buildjdk is done
|
||||
# building and ready to be used. The exact set of dependencies it needs
|
||||
# depends on what kind of buildjdk is used for the current configuration.
|
||||
runnable-buildjdk:
|
||||
ifeq ($(CREATE_BUILDJDK), true)
|
||||
ifneq ($(CREATING_BUILDJDK), true)
|
||||
runnable-buildjdk: create-buildjdk
|
||||
endif
|
||||
else ifeq ($(EXTERNAL_BUILDJDK), false)
|
||||
runnable-buildjdk: exploded-image
|
||||
endif
|
||||
|
||||
create-buildjdk: create-buildjdk-interim-image
|
||||
|
||||
docs-jdk-api: docs-jdk-api-javadoc
|
||||
@@ -1148,21 +1114,11 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
legacy-images: mac-legacy-jre-bundle
|
||||
endif
|
||||
|
||||
# These targets build the various documentation images
|
||||
docs-jdk-image: docs-jdk
|
||||
docs-javase-image: docs-javase
|
||||
docs-reference-image: docs-reference
|
||||
# The docs-jdk-image is what most users expect to be built
|
||||
docs-image: docs-jdk-image
|
||||
all-docs-images: docs-jdk-image docs-javase-image docs-reference-image
|
||||
|
||||
docs-bundles: docs-jdk-bundles
|
||||
all-docs-bundles: docs-jdk-bundles docs-javase-bundles docs-reference-bundles
|
||||
# This target builds the documentation image
|
||||
docs-image: docs-jdk
|
||||
|
||||
# This target builds the test image
|
||||
test-image: prepare-test-image test-image-jdk-jtreg-native \
|
||||
test-image-demos-jdk test-image-libtest-jtreg-native \
|
||||
test-image-lib-native
|
||||
test-image: prepare-test-image test-image-jdk-jtreg-native test-image-demos-jdk test-image-libtest-jtreg-native
|
||||
|
||||
ifneq ($(JVM_TEST_IMAGE_TARGETS), )
|
||||
# If JVM_TEST_IMAGE_TARGETS is externally defined, use it instead of the
|
||||
@@ -1190,7 +1146,7 @@ endif
|
||||
################################################################################
|
||||
|
||||
# all-images builds all our deliverables as images.
|
||||
all-images: product-images test-image all-docs-images
|
||||
all-images: product-images test-image docs-image
|
||||
|
||||
# all-bundles packages all our deliverables as tar.gz bundles.
|
||||
all-bundles: product-bundles test-bundles docs-bundles static-libs-bundles
|
||||
@@ -1198,11 +1154,10 @@ all-bundles: product-bundles test-bundles docs-bundles static-libs-bundles
|
||||
ALL_TARGETS += buildtools hotspot hotspot-libs hotspot-gensrc gensrc gendata \
|
||||
copy java libs static-libs launchers jmods \
|
||||
jdk.jdwp.agent-gensrc $(ALL_MODULES) demos \
|
||||
exploded-image-base exploded-image runnable-buildjdk \
|
||||
exploded-image-base exploded-image \
|
||||
create-buildjdk docs-jdk-api docs-javase-api docs-reference-api docs-jdk \
|
||||
docs-javase docs-reference docs-javadoc mac-bundles product-images legacy-images \
|
||||
docs-image docs-javase-image docs-reference-image all-docs-images \
|
||||
docs-bundles all-docs-bundles test-image all-images \
|
||||
docs-image test-image all-images \
|
||||
all-bundles
|
||||
|
||||
################################################################################
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user