mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
Compare commits
218 Commits
kharitonov
...
jb17_0_1-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fbdbcf7e4 | ||
|
|
3ee3c6386f | ||
|
|
30bc77c656 | ||
|
|
b2c21a7ff2 | ||
|
|
64b1068684 | ||
|
|
bd0e89a795 | ||
|
|
d92fd7c586 | ||
|
|
6fe971f3cf | ||
|
|
a087359232 | ||
|
|
8d5a142400 | ||
|
|
a719227d82 | ||
|
|
49342bb14c | ||
|
|
c6a0293d91 | ||
|
|
7bfbe200c1 | ||
|
|
578455ba0d | ||
|
|
c2b33bdd5c | ||
|
|
eb3ad964ba | ||
|
|
1506bd3607 | ||
|
|
2cdf1fc210 | ||
|
|
a8ffd4340a | ||
|
|
69ddf96cb5 | ||
|
|
67490807cc | ||
|
|
c09c089d9e | ||
|
|
3c4c7bab4d | ||
|
|
9627c68f72 | ||
|
|
d45a3fc927 | ||
|
|
211cb8d9e1 | ||
|
|
3f44d422b9 | ||
|
|
a7d73616ff | ||
|
|
6620e47d66 | ||
|
|
65c520ae3f | ||
|
|
2f34356d54 | ||
|
|
0a42abd61d | ||
|
|
18c5c7e80d | ||
|
|
4d8d4955ed | ||
|
|
c3592516a6 | ||
|
|
133904610f | ||
|
|
3b6464043b | ||
|
|
e0db7508a3 | ||
|
|
0db22561ff | ||
|
|
162b85305b | ||
|
|
7995c96d0c | ||
|
|
be4f890a03 | ||
|
|
3c6aaba7af | ||
|
|
7a91294571 | ||
|
|
0fbac1015d | ||
|
|
f07119d5e7 | ||
|
|
97bba86061 | ||
|
|
40f995d3ab | ||
|
|
aac5e29667 | ||
|
|
09c70729a3 | ||
|
|
d71c368588 | ||
|
|
0001763163 | ||
|
|
ae3255b783 | ||
|
|
3ad1355ee9 | ||
|
|
ea7cc0a25e | ||
|
|
f2cbf602b7 | ||
|
|
5911e4de07 | ||
|
|
99f0739e22 | ||
|
|
b9f61f381e | ||
|
|
9a0f7cb797 | ||
|
|
23a785f295 | ||
|
|
20f192f575 | ||
|
|
433371f454 | ||
|
|
3e7505682c | ||
|
|
510c614bd5 | ||
|
|
b21bd30a99 | ||
|
|
d2a2552251 | ||
|
|
bcf87546fd | ||
|
|
80aaadb63b | ||
|
|
b0f8eb0520 | ||
|
|
1d5d93965d | ||
|
|
51cad78be2 | ||
|
|
7178335ef2 | ||
|
|
d27a99d017 | ||
|
|
c84a5d6b68 | ||
|
|
5767bb3e33 | ||
|
|
e25d9df9ac | ||
|
|
a2f68a23ad | ||
|
|
67924e1a3f | ||
|
|
aec04f7e60 | ||
|
|
5d215bf145 | ||
|
|
55f7e129d8 | ||
|
|
ee4cc9ef28 | ||
|
|
0661deff06 | ||
|
|
1d77c059fd | ||
|
|
80a9e97280 | ||
|
|
326e256f52 | ||
|
|
e3d28840e6 | ||
|
|
fc216497df | ||
|
|
9c8d340b57 | ||
|
|
7aaad0aaa0 | ||
|
|
76d3bbf854 | ||
|
|
44abc5029b | ||
|
|
0a668a996d | ||
|
|
5badac0956 | ||
|
|
d5ea87b9de | ||
|
|
cc7796b8b2 | ||
|
|
ec858078e8 | ||
|
|
eb6859c079 | ||
|
|
922afec029 | ||
|
|
9bc7904167 | ||
|
|
2cb7130347 | ||
|
|
1a5015f8b0 | ||
|
|
b3d2cae5a7 | ||
|
|
9319f9b992 | ||
|
|
bd46044123 | ||
|
|
ac99462ad9 | ||
|
|
6f0b0d229e | ||
|
|
4ec82b634a | ||
|
|
d0b4503b6d | ||
|
|
6a5db5e5a8 | ||
|
|
95bd84812b | ||
|
|
06fe4066e1 | ||
|
|
a0eca85c7a | ||
|
|
3749ae27d4 | ||
|
|
3fb5883b89 | ||
|
|
6ddd23d65d | ||
|
|
11b0314036 | ||
|
|
3054d900bd | ||
|
|
9aa5ba174b | ||
|
|
dd8712b550 | ||
|
|
b581a10ce9 | ||
|
|
ee36294f58 | ||
|
|
1a1e5576e2 | ||
|
|
cd246b3404 | ||
|
|
f212cc3976 | ||
|
|
58eb308b17 | ||
|
|
5bcd0a57de | ||
|
|
a4b86294a6 | ||
|
|
07f0fbb60d | ||
|
|
8055596ae4 | ||
|
|
9058bce915 | ||
|
|
cc6f04c1e3 | ||
|
|
de63e0d73b | ||
|
|
2438425d40 | ||
|
|
f73c242026 | ||
|
|
4db6003473 | ||
|
|
1fcd8bd4db | ||
|
|
f9bffbea0a | ||
|
|
fdffcb1af5 | ||
|
|
c678f8e1cf | ||
|
|
98390cc2b9 | ||
|
|
fec7acc8f8 | ||
|
|
f772a4fd99 | ||
|
|
93f8608fda | ||
|
|
3590c1122e | ||
|
|
c0a651373d | ||
|
|
3b3507aaf7 | ||
|
|
3d04ce016b | ||
|
|
2a2a70021e | ||
|
|
1c6602fad0 | ||
|
|
b0a15f303d | ||
|
|
1a726c1d05 | ||
|
|
db55911bd8 | ||
|
|
4a5f610c2d | ||
|
|
1b900aedb0 | ||
|
|
f367a94f21 | ||
|
|
735d0ad37f | ||
|
|
c28059f1b5 | ||
|
|
ef836d7ff0 | ||
|
|
1ec0c79f2a | ||
|
|
fccb1b3db1 | ||
|
|
554b424427 | ||
|
|
1618e45938 | ||
|
|
963dd6dc6c | ||
|
|
ae76c485e5 | ||
|
|
f115e22d9b | ||
|
|
9a1c3bf07c | ||
|
|
de6ce7d6fc | ||
|
|
ea9aaa43d0 | ||
|
|
8796b595cd | ||
|
|
38af132168 | ||
|
|
021b85bd30 | ||
|
|
bb76f78f55 | ||
|
|
5fb11bd80e | ||
|
|
be7e87a588 | ||
|
|
859924e4e9 | ||
|
|
f0e805c3b7 | ||
|
|
7c9fa398e5 | ||
|
|
2c683b659b | ||
|
|
4e89491e10 | ||
|
|
21edf2d11f | ||
|
|
29e19d8019 | ||
|
|
9e4606d717 | ||
|
|
81f119acb8 | ||
|
|
722af5ade6 | ||
|
|
0abcde88b3 | ||
|
|
c32d3a7919 | ||
|
|
d095607839 | ||
|
|
16069de470 | ||
|
|
7d3661cc70 | ||
|
|
551b50d00f | ||
|
|
2a911aa4a9 | ||
|
|
519ff38020 | ||
|
|
ef83ecff11 | ||
|
|
ee707b5935 | ||
|
|
fb85abda92 | ||
|
|
feb9927b59 | ||
|
|
358e415fef | ||
|
|
cd6e10ffb9 | ||
|
|
a6a7bf49ed | ||
|
|
663944a576 | ||
|
|
e60dd92580 | ||
|
|
c157508bcb | ||
|
|
94524f8ab6 | ||
|
|
6186194757 | ||
|
|
e7dbacd3f9 | ||
|
|
9695d28d7d | ||
|
|
ea8e4e07e2 | ||
|
|
2475dd1c1d | ||
|
|
01f87e40bb | ||
|
|
a3103059a8 | ||
|
|
83886f3d7a | ||
|
|
f2144980df | ||
|
|
f1a1642895 | ||
|
|
af44a23af9 | ||
|
|
139fcb747c |
13
jb/project/docker/Dockerfile
Normal file
13
jb/project/docker/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# jetbrains/runtime:jbr15env
|
||||
FROM centos:7
|
||||
RUN yum -y install centos-release-scl
|
||||
RUN yum -y install devtoolset-8
|
||||
RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool gcc gcc-c++ libstdc++-devel alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel git
|
||||
# Install Java 15
|
||||
RUN wget https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz \
|
||||
-O - | tar xz -C /
|
||||
RUN mv /zulu15.27.17-ca-jdk15.0.0-linux_x64 /jdk15.0.0
|
||||
ENV PATH /opt/rh/devtoolset-8/root/usr/bin:$PATH
|
||||
RUN mkdir .git
|
||||
RUN git config user.email "builduser@jetbrains.com"
|
||||
RUN git config user.name "builduser"
|
||||
135
jb/project/java-gradle/build.gradle
Normal file
135
jb/project/java-gradle/build.gradle
Normal file
@@ -0,0 +1,135 @@
|
||||
apply plugin: 'java'
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
def test_jvm = {
|
||||
if (project.hasProperty('jbsdkhome')) {
|
||||
file(jbsdkhome + (OperatingSystem.current().isWindows()?"/bin/java.exe" : "/bin/java")).absolutePath
|
||||
} else {
|
||||
if (OperatingSystem.current().isMacOsX()) {
|
||||
file('../../../build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-11.0.4.jdk/Contents/Home/bin/java').absolutePath
|
||||
} else if (OperatingSystem.current().isLinux()) {
|
||||
file('../../../build/linux-x86_64-normal-server-release/images/jdk/bin/java').absolutePath
|
||||
} else {
|
||||
file('../../../build/windows-x86_64-normal-server-release/images/jdk/bin/java.exe').absolutePath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile('junit:junit:4.12'){
|
||||
exclude group: 'org.hamcrest'
|
||||
}
|
||||
testCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||
testCompile 'net.java.dev.jna:jna:4.4.0'
|
||||
testCompile 'com.twelvemonkeys.imageio:imageio-tiff:3.3.2'
|
||||
testCompile 'org.apache.commons:commons-lang3:3.0'
|
||||
}
|
||||
|
||||
def jdk_modules = ["java.base", "java.logging", "java.prefs",
|
||||
"java.se.ee", "java.sql", "java.datatransfer",
|
||||
"java.management", "java.rmi", "java.security.jgss",
|
||||
"java.sql.rowset", "java.desktop", "java.management.rmi",
|
||||
"java.scripting", "java.security.sasl", "java.transaction",
|
||||
"java.instrument", "java.naming", "java.se",
|
||||
"java.smartcardio", "java.xml.crypto"]
|
||||
|
||||
def jdk_class_dirs = []
|
||||
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
new File("../../../src/" + it + "/share/classes")
|
||||
}
|
||||
|
||||
if (OperatingSystem.current().isMacOsX())
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/macosx/classes"
|
||||
}
|
||||
else if (OperatingSystem.current().isLinux()) {
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/solaris/classes"
|
||||
}
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/unix/classes"
|
||||
}
|
||||
} else
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/windows/classes"
|
||||
}
|
||||
|
||||
sourceSets.main.java.srcDirs = jdk_class_dirs
|
||||
|
||||
sourceSets {
|
||||
test {
|
||||
java {
|
||||
srcDir "../../../test/jdk/jbu"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test.dependsOn.clear()
|
||||
|
||||
test.dependsOn tasks.compileTestJava
|
||||
|
||||
test {
|
||||
systemProperty "jb.java2d.metal", "true"
|
||||
systemProperty "testdata", file('../../../test/jdk/jbu/testdata').absolutePath
|
||||
|
||||
// Generate golden images for DroidFontTest and MixedTextTest
|
||||
// systemProperty "gentestdata", ""
|
||||
|
||||
// Enable Java2D logging (https://confluence.jetbrains.com/display/JRE/Java2D+Rendering+Logging)
|
||||
// systemProperty "sun.java2d.trace", "log"
|
||||
// systemProperty "sun.java2d.trace", "log,pimpl"
|
||||
|
||||
outputs.upToDateWhen { false }
|
||||
executable = test_jvm()
|
||||
|
||||
// Enable async/dtrace profiler
|
||||
jvmArgs "-XX:+PreserveFramePointer"
|
||||
// Enable native J2D logging (only in debug build)
|
||||
// Can be turned on for J2D by adding "#define DEBUG 1" into jdk/src/share/native/sun/java2d/Trace.h
|
||||
|
||||
// environment 'J2D_TRACE_LEVEL', '4'
|
||||
}
|
||||
|
||||
def buildDir = project.buildscript.sourceFile.parentFile.parentFile.parentFile.parentFile
|
||||
|
||||
def make_cmd = "make"
|
||||
if (OperatingSystem.current().isWindows()) {
|
||||
def cyg_make_cmd = new File("c:/cygwin64/bin/make.exe")
|
||||
if (cyg_make_cmd.exists()) make_cmd = cyg_make_cmd.absolutePath
|
||||
}
|
||||
def test_run = false
|
||||
task make_images {
|
||||
doLast {
|
||||
if (!test_run) {
|
||||
def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "images")
|
||||
def proc = pb.redirectErrorStream(true).start()
|
||||
proc.inputStream.eachLine { println it }
|
||||
assert proc.waitFor() == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task make_clean {
|
||||
doLast {
|
||||
def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "clean")
|
||||
def proc = pb.redirectErrorStream(true).start()
|
||||
proc.inputStream.eachLine { println it }
|
||||
assert proc.waitFor() == 0
|
||||
}
|
||||
}
|
||||
|
||||
task run_test {
|
||||
doLast {
|
||||
test_run = true
|
||||
}
|
||||
}
|
||||
|
||||
tasks.cleanTest.dependsOn tasks.run_test
|
||||
classes.dependsOn.clear()
|
||||
classes.dependsOn tasks.make_images
|
||||
tasks.cleanClasses.dependsOn tasks.make_clean
|
||||
54
jb/project/tools/common/scripts/common.sh
Normal file
54
jb/project/tools/common/scripts/common.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
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
|
||||
do_reset_dcevm=0
|
||||
HEAD_REVISION=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
|
||||
if [ $do_reset_dcevm -eq 1 ]; then
|
||||
[ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION
|
||||
fi
|
||||
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
|
||||
echo $(ls $__mods) | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g
|
||||
}
|
||||
84
jb/project/tools/linux/scripts/mkimages_aarch64.sh
Executable file
84
jb/project/tools/linux/scripts/mkimages_aarch64.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/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
|
||||
#
|
||||
# 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
|
||||
|
||||
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-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 || 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-server-release/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 $?
|
||||
|
||||
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 $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/,$//g) \
|
||||
--output ${BASE_DIR}/${JBR_BUNDLE} || 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 -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
137
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
137
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# 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 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
|
||||
#
|
||||
# $ ./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)
|
||||
#
|
||||
# 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}
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__arch_name=$2
|
||||
__modules_path=$3
|
||||
__modules=$4
|
||||
|
||||
[ "$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 "$__modules_path" --no-man-pages --compress=2 \
|
||||
--add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name"
|
||||
|
||||
grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release
|
||||
if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then
|
||||
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release
|
||||
mv release "$IMAGES_DIR"/"$__arch_name"/release
|
||||
fi
|
||||
|
||||
# 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 ...
|
||||
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"
|
||||
}
|
||||
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=linux-x86_64-server-release
|
||||
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"dcevm")
|
||||
HEAD_REVISION=$(git rev-parse HEAD)
|
||||
git am jb/project/tools/patches/dcevm/*.patch || do_exit $?
|
||||
do_reset_dcevm=1
|
||||
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
|
||||
|
||||
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 clean CONF=$RELEASE_NAME || exit $?
|
||||
make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
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
|
||||
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$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
|
||||
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
# 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 $?
|
||||
|
||||
# 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" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
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
|
||||
|
||||
do_exit 0
|
||||
81
jb/project/tools/linux/scripts/mkimages_x86.sh
Executable file
81
jb/project/tools/linux/scripts/mkimages_x86.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/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
|
||||
#
|
||||
# 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
|
||||
|
||||
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-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 || 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-server-release/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 $?
|
||||
|
||||
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 $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x86-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g | sed s/,$//g) --output ${BASE_DIR}/${JBR_BUNDLE} || 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 -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
16
jb/project/tools/mac/scripts/entitlements.xml
Normal file
16
jb/project/tools/mac/scripts/entitlements.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
139
jb/project/tools/mac/scripts/mkimages.sh
Executable file
139
jb/project/tools/mac/scripts/mkimages.sh
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# 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 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
|
||||
#
|
||||
# $ ./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)
|
||||
#
|
||||
# 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)}
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__arch_name=$2
|
||||
__modules_path=$3
|
||||
__modules=$4
|
||||
|
||||
tmp=.bundle.$$.tmp
|
||||
mkdir "$tmp" || do_exit $?
|
||||
|
||||
[ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-"
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-osx-x64-${fastdebug_infix}b${build_number}
|
||||
|
||||
JRE_CONTENTS=$tmp/$__arch_name/Contents
|
||||
mkdir -p "$JRE_CONTENTS" || do_exit $?
|
||||
|
||||
echo Running jlink...
|
||||
"$JSDK"/bin/jlink \
|
||||
--module-path "$__modules_path" --no-man-pages --compress=2 \
|
||||
--add-modules "$__modules" --output "$JRE_CONTENTS/Home" || do_exit $?
|
||||
|
||||
grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$JRE_CONTENTS/Home/release"
|
||||
if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then
|
||||
sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release
|
||||
mv release $JRE_CONTENTS/Home/release
|
||||
fi
|
||||
|
||||
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" "$__arch_name" || do_exit $?
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=macosx-x86_64-server-release
|
||||
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"dcevm")
|
||||
HEAD_REVISION=$(git rev-parse HEAD)
|
||||
git am jb/project/tools/patches/dcevm/*.patch || do_exit $?
|
||||
do_reset_dcevm=1
|
||||
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
|
||||
|
||||
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 clean CONF=$RELEASE_NAME || do_exit $?
|
||||
make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
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
|
||||
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$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
|
||||
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
# 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 $?
|
||||
|
||||
# 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" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
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
|
||||
|
||||
do_exit 0
|
||||
120
jb/project/tools/mac/scripts/notarize.sh
Executable file
120
jb/project/tools/mac/scripts/notarize.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
APPL_USER=$2
|
||||
APPL_PASSWORD=$3
|
||||
APP_NAME=$4
|
||||
BUNDLE_ID=$5
|
||||
FAKE_ROOT="${6:-fake-root}"
|
||||
|
||||
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$APPL_USER" ]] || [[ -z "$APPL_PASSWORD" ]]; then
|
||||
echo "Usage: $0 AppDirectory Username Password"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$APP_DIRECTORY" ]]; then
|
||||
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
function publish-log() {
|
||||
id=$1
|
||||
file=$2
|
||||
curl -T "$file" "$ARTIFACTORY_URL/$id" || true
|
||||
}
|
||||
|
||||
function altool-upload() {
|
||||
# Since altool uses same file for upload token we have to trick it into using different folders for token file location
|
||||
# Also it copies zip into TMPDIR so we override it too, to simplify cleanup
|
||||
OLD_HOME="$HOME"
|
||||
export HOME="$FAKE_ROOT/home"
|
||||
export TMPDIR="$FAKE_ROOT/tmp"
|
||||
mkdir -p "$HOME"
|
||||
mkdir -p "$TMPDIR"
|
||||
export _JAVA_OPTIONS="-Duser.home=$HOME -Djava.io.tmpdir=$TMPDIR"
|
||||
# Reduce amount of downloads, cache transporter libraries
|
||||
shared_itmstransporter="$OLD_HOME/shared-itmstransporter"
|
||||
if [[ -f "$shared_itmstransporter" ]]; then
|
||||
cp -r "$shared_itmstransporter" "$HOME/.itmstransporter"
|
||||
fi
|
||||
# For some reason altool prints everything to stderr, not stdout
|
||||
set +e
|
||||
xcrun altool --notarize-app \
|
||||
--username "$APPL_USER" --password "$APPL_PASSWORD" \
|
||||
--primary-bundle-id "$BUNDLE_ID" \
|
||||
--asc-provider JetBrainssro --file "$1" 2>&1 | tee "altool.init.out"
|
||||
unset TMPDIR
|
||||
export HOME="$OLD_HOME"
|
||||
set -e
|
||||
}
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
file="$APP_NAME.zip"
|
||||
|
||||
log "Zipping $file..."
|
||||
rm -rf "$file"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY/Contents" "$file"
|
||||
|
||||
log "Notarizing $file..."
|
||||
rm -rf "altool.init.out" "altool.check.out"
|
||||
altool-upload "$file"
|
||||
|
||||
rm -rf "$file"
|
||||
|
||||
notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')"
|
||||
|
||||
if [ -z "$notarization_info" ]; then
|
||||
log "Faile to read RequestUUID from altool.init.out"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
PATH="$PATH:/usr/local/bin/"
|
||||
|
||||
log "Notarization request sent, awaiting response"
|
||||
spent=0
|
||||
|
||||
while true; do
|
||||
# For some reason altool prints everything to stderr, not stdout
|
||||
xcrun altool --username "$APPL_USER" --notarization-info "$notarization_info" --password "$APPL_PASSWORD" >"altool.check.out" 2>&1 || true
|
||||
status="$(grep -oe 'Status: .*' "altool.check.out" | cut -c 9- || true)"
|
||||
log "Current status: $status"
|
||||
if [ "$status" = "invalid" ]; then
|
||||
log "Notarization failed"
|
||||
ec=1
|
||||
elif [ "$status" = "success" ]; then
|
||||
log "Notarization succeeded"
|
||||
ec=0
|
||||
else
|
||||
if [ "$status" != "in progress" ]; then
|
||||
log "Unknown notarization status, waiting more, altool output:"
|
||||
cat "altool.check.out"
|
||||
fi
|
||||
if [[ $spent -gt 60 ]]; then
|
||||
log "Waiting time out (apx 60 minutes)"
|
||||
ec=2
|
||||
break
|
||||
fi
|
||||
sleep 60
|
||||
((spent += 1))
|
||||
continue
|
||||
fi
|
||||
developer_log="developer_log.json"
|
||||
log "Fetching $developer_log"
|
||||
# TODO: Replace cut with trim or something better
|
||||
url="$(grep -oe 'LogFileURL: .*' "altool.check.out" | cut -c 13-)"
|
||||
wget "$url" -O "$developer_log" && cat "$developer_log" || true
|
||||
if [ $ec != 0 ]; then
|
||||
log "Publishing $developer_log"
|
||||
publish-log "$notarization_info" "$developer_log"
|
||||
fi
|
||||
break
|
||||
done
|
||||
cat "altool.check.out"
|
||||
|
||||
rm -rf "altool.init.out" "altool.check.out"
|
||||
exit $ec
|
||||
94
jb/project/tools/mac/scripts/sign.sh
Executable file
94
jb/project/tools/mac/scripts/sign.sh
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
JB_CERT=$2
|
||||
|
||||
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then
|
||||
echo "Usage: $0 AppDirectory CertificateID"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$APP_DIRECTORY" ]]; then
|
||||
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
# Cleanup files left from previous sign attempt (if any)
|
||||
find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \;
|
||||
|
||||
log "Signing libraries and executables..."
|
||||
# -perm +111 searches for executables
|
||||
for f in \
|
||||
"Contents/Home/bin" \
|
||||
"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 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
log "Signing libraries in jars in $PWD"
|
||||
|
||||
# todo: add set -euo pipefail; into the inner sh -c
|
||||
# `-e` prevents `grep -q && printf` loginc
|
||||
# with `-o pipefail` there's no input for 'while' loop
|
||||
find "$APP_DIRECTORY" -name '*.jar' \
|
||||
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
log "Processing libraries in $file"
|
||||
|
||||
rm -rf jarfolder jar.jar
|
||||
mkdir jarfolder
|
||||
filename="${file##*/}"
|
||||
log "Filename: $filename"
|
||||
cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename")
|
||||
|
||||
find jarfolder \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
|
||||
(cd jarfolder; zip -q -r -o ../jar.jar .)
|
||||
mv jar.jar "$file"
|
||||
done
|
||||
|
||||
rm -rf jarfolder jar.jar
|
||||
|
||||
log "Signing other files..."
|
||||
for f in \
|
||||
"Contents/MacOS"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
#log "Signing executable..."
|
||||
#codesign --timestamp \
|
||||
# -v -s "$JB_CERT" --options=runtime \
|
||||
# --force \
|
||||
# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea"
|
||||
|
||||
log "Signing whole app..."
|
||||
codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--force \
|
||||
--entitlements entitlements.xml "$APP_DIRECTORY"
|
||||
|
||||
log "Verifying java is not broken"
|
||||
find "$APP_DIRECTORY" \
|
||||
-type f -name 'java' -perm +111 -exec {} -version \;
|
||||
138
jb/project/tools/mac/scripts/signapp.sh
Executable file
138
jb/project/tools/mac/scripts/signapp.sh
Executable file
@@ -0,0 +1,138 @@
|
||||
#!/bin/bash
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
export COPY_EXTENDED_ATTRIBUTES_DISABLE=true
|
||||
export COPYFILE_DISABLE=true
|
||||
|
||||
INPUT_FILE=$1
|
||||
EXPLODED=$2.exploded
|
||||
BACKUP_JMODS=$2.backup
|
||||
USERNAME=$3
|
||||
PASSWORD=$4
|
||||
CODESIGN_STRING=$5
|
||||
NOTARIZE=$6
|
||||
BUNDLE_ID=$7
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
log "Deleting $EXPLODED ..."
|
||||
if test -d "$EXPLODED"; then
|
||||
find "$EXPLODED" -mindepth 1 -maxdepth 1 -exec chmod -R u+wx '{}' \;
|
||||
fi
|
||||
rm -rf "$EXPLODED"
|
||||
mkdir "$EXPLODED"
|
||||
rm -rf "$BACKUP_JMODS"
|
||||
mkdir "$BACKUP_JMODS"
|
||||
|
||||
log "Unzipping $INPUT_FILE to $EXPLODED ..."
|
||||
tar -xzvf "$INPUT_FILE" --directory $EXPLODED
|
||||
rm "$INPUT_FILE"
|
||||
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 -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 extracted and removed"
|
||||
|
||||
APPLICATION_PATH="$EXPLODED/$BUILD_NAME"
|
||||
|
||||
find "$APPLICATION_PATH/Contents/Home/bin" \
|
||||
-maxdepth 1 -type f -name '*.jnilib' -print0 |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
if [ -f "$file" ]; then
|
||||
log "Linking $file"
|
||||
b="$(basename "$file" .jnilib)"
|
||||
ln -sf "$b.jnilib" "$(dirname "$file")/$b.dylib"
|
||||
fi
|
||||
done
|
||||
|
||||
find "$APPLICATION_PATH/Contents/" \
|
||||
-maxdepth 1 -type f -name '*.txt' -print0 |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
if [ -f "$file" ]; then
|
||||
log "Moving $file"
|
||||
mv "$file" "$APPLICATION_PATH/Contents/Resources"
|
||||
fi
|
||||
done
|
||||
|
||||
non_plist=$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist' | wc -l)
|
||||
if [[ $non_plist -gt 0 ]]; then
|
||||
log "Only Info.plist file is allowed in Contents directory but found $non_plist file(s):"
|
||||
log "$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Unlocking keychain..."
|
||||
# Make sure *.p12 is imported into local KeyChain
|
||||
security unlock-keychain -p "$PASSWORD" "/Users/$USERNAME/Library/Keychains/login.keychain"
|
||||
|
||||
attempt=1
|
||||
limit=3
|
||||
set +e
|
||||
while [[ $attempt -le $limit ]]; do
|
||||
log "Signing (attempt $attempt) $APPLICATION_PATH ..."
|
||||
./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING"
|
||||
ec=$?
|
||||
if [[ $ec -ne 0 ]]; then
|
||||
((attempt += 1))
|
||||
if [ $attempt -eq $limit ]; then
|
||||
set -e
|
||||
fi
|
||||
log "Signing failed, wait for 30 sec and try to sign again"
|
||||
sleep 30
|
||||
else
|
||||
log "Signing done"
|
||||
codesign -v "$APPLICATION_PATH" -vvvvv
|
||||
log "Check sign done"
|
||||
((attempt += limit))
|
||||
fi
|
||||
done
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$NOTARIZE" = "yes" ]; then
|
||||
log "Notarizing..."
|
||||
# shellcheck disable=SC1090
|
||||
source "$HOME/.notarize_token"
|
||||
APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }')
|
||||
# Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root
|
||||
# Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR
|
||||
FAKE_ROOT="$(pwd)/fake-root"
|
||||
mkdir -p "$FAKE_ROOT"
|
||||
echo "Notarization will use fake root: $FAKE_ROOT"
|
||||
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT"
|
||||
rm -rf "$FAKE_ROOT"
|
||||
|
||||
set +e
|
||||
log "Stapling..."
|
||||
xcrun stapler staple "$APPLICATION_PATH"
|
||||
else
|
||||
log "Notarization disabled"
|
||||
log "Stapling disabled"
|
||||
fi
|
||||
|
||||
log "Zipping $BUILD_NAME to $INPUT_FILE ..."
|
||||
(
|
||||
#cd "$EXPLODED"
|
||||
#ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE"
|
||||
if test -d $BACKUP_JMODS/jmods; then
|
||||
mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
fi
|
||||
|
||||
COPYFILE_DISABLE=1 tar -pczf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME
|
||||
log "Finished zipping"
|
||||
)
|
||||
rm -rf "$EXPLODED"
|
||||
log "Done"
|
||||
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;
|
||||
8853
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
8853
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
File diff suppressed because it is too large
Load Diff
1569
jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch
Normal file
1569
jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
From 960dafbeeba190911955c208b611fecc15d66738 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Wed, 11 Mar 2020 14:19:34 +0100
|
||||
Subject: [PATCH 03/34] 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 994fc8a3bc8..3be3a09ef8f 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -953,7 +953,10 @@ bool InstanceKlass::link_class_impl(TRAPS) {
|
||||
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
- {
|
||||
+ // (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 (!AllowEnhancedClassRedefinition || !newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
1086
jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch
Normal file
1086
jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,240 @@
|
||||
From 39df5f163d4a0f1fd6b92313a5570808f19d5e20 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 4 Oct 2020 21:12:12 +0200
|
||||
Subject: [PATCH 05/34] Support for Lambda class redefinition
|
||||
|
||||
---
|
||||
.../share/classfile/classLoaderData.cpp | 9 +++
|
||||
.../share/classfile/classLoaderData.hpp | 2 +-
|
||||
.../share/classfile/systemDictionary.cpp | 12 +++-
|
||||
.../share/classfile/systemDictionary.hpp | 1 +
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 65 +++++++++++++++++--
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 1 +
|
||||
.../share/prims/resolvedMethodTable.cpp | 2 +
|
||||
src/hotspot/share/prims/unsafe.cpp | 1 +
|
||||
8 files changed, 83 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index 0cd90bb8c27..4d64c6b454a 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -593,6 +593,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 ba2393f8dd0..e2ae0a77351 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
@@ -181,7 +181,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
bool has_accumulated_modified_oops() { return _accumulated_modified_oops; }
|
||||
oop holder_no_keepalive() const;
|
||||
oop holder_phantom() const;
|
||||
-
|
||||
+ void exchange_holders(ClassLoaderData* cld);
|
||||
private:
|
||||
void unload();
|
||||
bool keep_alive() const { return _keep_alive > 0; }
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index bd0cae7cb9b..8f2b46add4d 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -1062,10 +1062,14 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
ClassFileStream* st,
|
||||
const ClassLoadInfo& cl_info,
|
||||
+ InstanceKlass* old_klass,
|
||||
TRAPS) {
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
ClassLoaderData* loader_data;
|
||||
+
|
||||
+ bool is_redefining = (old_klass != NULL);
|
||||
+
|
||||
bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL;
|
||||
|
||||
// - for unsafe anonymous class: create a new CLD whith a class holder that uses
|
||||
@@ -1094,8 +1098,12 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
class_name,
|
||||
loader_data,
|
||||
cl_info,
|
||||
- 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 ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) {
|
||||
// Hidden classes that are not strong and unsafe anonymous classes must update
|
||||
@@ -1998,7 +2006,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 4547449dbec..931e655d631 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
@@ -329,6 +329,7 @@ public:
|
||||
Handle class_loader,
|
||||
ClassFileStream* st,
|
||||
const ClassLoadInfo& cl_info,
|
||||
+ InstanceKlass* old_klass,
|
||||
TRAPS);
|
||||
|
||||
// Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 92ce6c27b8a..8b765623dcd 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -494,6 +494,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;
|
||||
@@ -756,12 +758,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();
|
||||
|
||||
@@ -1442,6 +1466,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];
|
||||
@@ -1979,7 +2027,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 60b62c3170a..d8a11b51fe9 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -116,6 +116,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 122bb8c186b..81b3aa96564 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -414,6 +414,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 72d81ec9d6c..027afa3fabd 100644
|
||||
--- a/src/hotspot/share/prims/unsafe.cpp
|
||||
+++ b/src/hotspot/share/prims/unsafe.cpp
|
||||
@@ -865,6 +865,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
|
||||
host_loader,
|
||||
&st,
|
||||
cl_info,
|
||||
+ NULL,
|
||||
CHECK_NULL);
|
||||
if (anonk == NULL) {
|
||||
return NULL;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
From 5af1daedc86b5fec0f222cbdda3afbdf518985ea Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sat, 23 May 2020 10:02:15 +0200
|
||||
Subject: [PATCH 06/34] Fix "no original bytecode found" error if method with
|
||||
bkp is missing
|
||||
|
||||
Sometimes IDE can deploy class with erroneous method, such method has
|
||||
n 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 ed3cc3eb6a2..504e59caf51 100644
|
||||
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
@@ -814,7 +814,7 @@ JRT_END
|
||||
// Invokes
|
||||
|
||||
JRT_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);
|
||||
JRT_END
|
||||
|
||||
JRT_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 516f2bb8f2f..1c88511a5fc 100644
|
||||
--- a/src/hotspot/share/oops/method.cpp
|
||||
+++ b/src/hotspot/share/oops/method.cpp
|
||||
@@ -1853,14 +1853,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);
|
||||
}
|
||||
@@ -2006,7 +2006,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;
|
||||
}
|
||||
|
||||
@@ -2015,7 +2015,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 83ed2d9c3c1..4d4cc6dc012 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 8b765623dcd..a859b8e1162 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1362,14 +1362,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.23.0
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From 19d2274a5dff6e6b31474252b45e5e7484f0180b Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 24 May 2020 12:07:42 +0200
|
||||
Subject: [PATCH 07/34] 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 81b3aa96564..caf03ffe56d 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -404,25 +404,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.23.0
|
||||
|
||||
1310
jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch
Normal file
1310
jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
From ca47ab5a0a6ce8e2644736f323a335a957311af9 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sat, 13 Jun 2020 18:50:59 +0200
|
||||
Subject: [PATCH 09/34] Change log level in advanced redefinition
|
||||
|
||||
- Change log level for "Comparing different class ver.." to debug
|
||||
- Fix adjust_method_entries_dcevm logging levels and severity
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
src/hotspot/share/prims/resolvedMethodTable.cpp | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 6c9eb40ecf5..b09ba554e07 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -916,7 +916,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
// 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());
|
||||
+ log_debug(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string());
|
||||
|
||||
assert(new_class->old_version() != NULL, "must have old version");
|
||||
InstanceKlass* the_class = InstanceKlass::cast(new_class->old_version());
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index caf03ffe56d..eb9fcda44f3 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -413,7 +413,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
} 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_debug(redefine, class, update)("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");
|
||||
@@ -433,7 +433,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
|
||||
ResourceMark rm;
|
||||
if (!(*trace_name_printed)) {
|
||||
- log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
+ log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
log_debug(redefine, class, update, constantpool)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From 7e236beee0375656d1955fc1168143c1639fb7f1 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Tue, 6 Oct 2020 22:15:31 +0200
|
||||
Subject: [PATCH 10/34] AllowEnhancedClassRedefinition is false (disabled) by
|
||||
default
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/globals.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
|
||||
index 5b367704800..2710c6ea0e5 100644
|
||||
--- a/src/hotspot/share/runtime/globals.hpp
|
||||
+++ b/src/hotspot/share/runtime/globals.hpp
|
||||
@@ -2466,7 +2466,7 @@ const size_t minimumSymbolTableSize = 1024;
|
||||
diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \
|
||||
"Make nmethod barriers deoptimise a lot.") \
|
||||
\
|
||||
- product(bool, AllowEnhancedClassRedefinition, true, \
|
||||
+ product(bool, AllowEnhancedClassRedefinition, false, \
|
||||
"Allow enhanced class redefinition beyond swapping method " \
|
||||
"bodies") \
|
||||
\
|
||||
--
|
||||
2.23.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
From d56e73885111b386771f564ec6beb305338993df Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Mon, 19 Oct 2020 20:00:04 +0200
|
||||
Subject: [PATCH 12/34] Set HOTSPOT_VM_DISTRO=Dynamic Code Evolution
|
||||
|
||||
---
|
||||
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 aabdc5bed20..df8025a2e84 100644
|
||||
--- a/make/autoconf/version-numbers
|
||||
+++ b/make/autoconf/version-numbers
|
||||
@@ -45,7 +45,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"
|
||||
VENDOR_URL=https://openjdk.java.net/
|
||||
VENDOR_URL_BUG=https://bugreport.java.com/bugreport/
|
||||
VENDOR_URL_VM_BUG=https://bugreport.java.com/bugreport/crash.jsp
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
From 7ebad43ed45805b0a3736c510f708ff17697ba7e Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 11 Oct 2020 10:43:28 +0200
|
||||
Subject: [PATCH 13/34] Fix G1 nmethod registration
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 19 ++++++++++++++++---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 3 ++-
|
||||
2 files changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index b09ba554e07..718426f2819 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -216,7 +216,14 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
}
|
||||
}
|
||||
|
||||
-void VM_EnhancedRedefineClasses::mark_as_scavengable_g1(nmethod* nm) {
|
||||
+void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) {
|
||||
+ // It should work not only for G1 but also for another GCs, but this way is safer now
|
||||
+ if (!nm->is_zombie() && !nm->is_unloaded()) {
|
||||
+ Universe::heap()->unregister_nmethod(nm);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) {
|
||||
// It should work not only for G1 but also for another GCs, but this way is safer now
|
||||
if (!nm->is_zombie() && !nm->is_unloaded()) {
|
||||
Universe::heap()->register_nmethod(nm);
|
||||
@@ -521,8 +528,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// For now, mark all nmethod's as scavengable that are not scavengable already
|
||||
if (ScavengeRootsInCode) {
|
||||
if (UseG1GC) {
|
||||
- // this should work also for other GCs
|
||||
- CodeCache::nmethods_do(mark_as_scavengable_g1);
|
||||
+ // G1 holds references to nmethods in regions based on oops values. Since oops in nmethod can be changed in ChangePointers* closures
|
||||
+ // we unregister nmethods from G1 heap, then closures are processed (oops are changed) and finally we register nmethod to G1 again
|
||||
+ CodeCache::nmethods_do(unregister_nmethod_g1);
|
||||
} else {
|
||||
CodeCache::nmethods_do(mark_as_scavengable);
|
||||
}
|
||||
@@ -545,6 +553,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
|
||||
Universe::root_oops_do(&oopClosureNoBarrier);
|
||||
|
||||
+ if (UseG1GC) {
|
||||
+ // this should work also for other GCs
|
||||
+ CodeCache::nmethods_do(register_nmethod_g1);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
log_trace(redefine, class, obsolete, metadata)("After updating instances");
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 9755944d70b..4c0412d343d 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -116,7 +116,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
void rollback();
|
||||
static void mark_as_scavengable(nmethod* nm);
|
||||
- static void mark_as_scavengable_g1(nmethod* nm);
|
||||
+ static void unregister_nmethod_g1(nmethod* nm);
|
||||
+ static void register_nmethod_g1(nmethod* nm);
|
||||
static void unpatch_bytecode(Method* method);
|
||||
static void fix_invoke_method(Method* method);
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From 5c7e5f245f79d7e8575461dab0c356ed74c8e9a3 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Thu, 22 Oct 2020 20:15:20 +0200
|
||||
Subject: [PATCH 14/34] Initialize method's _new_version/_old_version to NULL
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/method.cpp | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
|
||||
index 1c88511a5fc..ce940cf10a9 100644
|
||||
--- a/src/hotspot/share/oops/method.cpp
|
||||
+++ b/src/hotspot/share/oops/method.cpp
|
||||
@@ -91,7 +91,8 @@ Method* Method::allocate(ClassLoaderData* loader_data,
|
||||
return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags);
|
||||
}
|
||||
|
||||
-Method::Method(ConstMethod* xconst, AccessFlags access_flags) {
|
||||
+Method::Method(ConstMethod* xconst, AccessFlags access_flags) : _new_version(NULL),
|
||||
+ _old_version(NULL) {
|
||||
NoSafepointVerifier no_safepoint;
|
||||
set_constMethod(xconst);
|
||||
set_access_flags(access_flags);
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
From 6ffac6e5064ec6633fdbeb8520333dca00bc6a62 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Fri, 23 Oct 2020 10:20:26 +0200
|
||||
Subject: [PATCH 15/34] Clear dcevm code separation
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/systemDictionary.cpp | 4 ++--
|
||||
src/hotspot/share/gc/serial/genMarkSweep.cpp | 8 +++++---
|
||||
src/hotspot/share/interpreter/linkResolver.cpp | 16 +++++++++++-----
|
||||
.../instrumentation/jfrEventClassTransformer.cpp | 2 +-
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 10 ++++++----
|
||||
src/hotspot/share/oops/method.cpp | 2 +-
|
||||
.../share/prims/jvmtiGetLoadedClasses.cpp | 2 +-
|
||||
src/hotspot/share/runtime/reflection.cpp | 2 +-
|
||||
8 files changed, 28 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index 8f2b46add4d..9ac6ec96cb5 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -1241,7 +1241,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
MutexLocker mu(THREAD, SystemDictionary_lock);
|
||||
|
||||
Klass* check = find_class(h_name, k->class_loader_data());
|
||||
- assert((check == k && !k->is_redefining()) || (k->is_redefining() && check == k->old_version()), "should be present in the dictionary");
|
||||
+ assert(check == k && !k->is_redefining() || k->is_redefining() && check == k->old_version(), "should be present in the dictionary");
|
||||
} );
|
||||
|
||||
return k;
|
||||
@@ -2290,7 +2290,7 @@ void SystemDictionary::check_constraints(unsigned int d_hash,
|
||||
// also hold array classes.
|
||||
|
||||
assert(check->is_instance_klass(), "noninstance in systemdictionary");
|
||||
- if ((defining == true) || ((k != check) && k->old_version() != check)) {
|
||||
+ if ((defining == true) || (k != check && (!AllowEnhancedClassRedefinition || k->old_version() != check))) {
|
||||
throwException = true;
|
||||
ss.print("loader %s", loader_data->loader_name_and_id());
|
||||
ss.print(" attempted duplicate %s definition for %s. (%s)",
|
||||
diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp
|
||||
index 1d13c647452..548df01e557 100644
|
||||
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp
|
||||
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp
|
||||
@@ -334,7 +334,9 @@ void GenMarkSweep::mark_sweep_phase4() {
|
||||
|
||||
GenCompactClosure blk;
|
||||
gch->generation_iterate(&blk, true);
|
||||
- DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true);
|
||||
- DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops);
|
||||
- MarkSweep::_rescued_oops = NULL;
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true);
|
||||
+ DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops);
|
||||
+ MarkSweep::_rescued_oops = NULL;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index b6e9e0a308d..b2f24ddbeda 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -282,9 +282,14 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass,
|
||||
if (!base_klass->is_instance_klass()) {
|
||||
return; // no relevant check to do
|
||||
}
|
||||
-
|
||||
- Reflection::VerifyClassAccessResults vca_result =
|
||||
- Reflection::verify_class_access(ref_klass->newest_version(), InstanceKlass::cast(base_klass->newest_version()), true);
|
||||
+ Klass* refKlassNewest = ref_klass;
|
||||
+ Klass* baseKlassNewest = base_klass;
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ refKlassNewest = ref_klass->newest_version();
|
||||
+ baseKlassNewest = base_klass->newest_version();
|
||||
+ }
|
||||
+ Reflection::VerifyClassAccessResults vca_result =
|
||||
+ Reflection::verify_class_access(refKlassNewest, InstanceKlass::cast(baseKlassNewest), true);
|
||||
if (vca_result != Reflection::ACCESS_OK) {
|
||||
ResourceMark rm(THREAD);
|
||||
char* msg = Reflection::verify_class_access_msg(ref_klass,
|
||||
@@ -566,7 +571,8 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
|
||||
// We'll check for the method name first, as that's most likely
|
||||
// to be false (so we'll short-circuit out of these tests).
|
||||
if (sel_method->name() == vmSymbols::clone_name() &&
|
||||
- sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version() &&
|
||||
+ ( !AllowEnhancedClassRedefinition && sel_klass == SystemDictionary::Object_klass() ||
|
||||
+ AllowEnhancedClassRedefinition && sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version()) &&
|
||||
resolved_klass->is_array_klass()) {
|
||||
// We need to change "protected" to "public".
|
||||
assert(flags.is_protected(), "clone not protected?");
|
||||
@@ -1011,7 +1017,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||
// or by the <init> method (in case of an instance field).
|
||||
if (is_put && fd.access_flags().is_final()) {
|
||||
|
||||
- if (sel_klass != current_klass && sel_klass != current_klass->active_version()) {
|
||||
+ if (sel_klass != current_klass && (!AllowEnhancedClassRedefinition || sel_klass != current_klass->active_version())) {
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
|
||||
diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
|
||||
index 96fc139bea3..f7284197c5a 100644
|
||||
--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
|
||||
+++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
|
||||
@@ -1471,7 +1471,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre
|
||||
cld,
|
||||
&cl_info,
|
||||
ClassFileParser::INTERNAL, // internal visibility
|
||||
- false,
|
||||
+ false,
|
||||
THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
log_pending_exception(PENDING_EXCEPTION);
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 3be3a09ef8f..f8e60941046 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -199,7 +199,9 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
|
||||
// able to perform that loading but we can't exclude the compiler threads from
|
||||
// executing this logic. But it should actually be impossible to trigger loading here.
|
||||
Klass* k2 = _constants->klass_at(cp_index, THREAD);
|
||||
- k2 = k2->newest_version();
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ k2 = k2->newest_version();
|
||||
+ }
|
||||
assert(!HAS_PENDING_EXCEPTION || PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass()),
|
||||
"Exceptions should not be possible here");
|
||||
if (k2 == k) {
|
||||
@@ -1003,7 +1005,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
|
||||
#endif
|
||||
set_init_state(linked);
|
||||
// (DCEVM) Must check for old version in order to prevent infinite loops.
|
||||
- if (JvmtiExport::should_post_class_prepare() && old_version() == NULL /* JVMTI deadlock otherwise */) {
|
||||
+ if (JvmtiExport::should_post_class_prepare() && (!AllowEnhancedClassRedefinition || old_version() == NULL) /* JVMTI deadlock otherwise */) {
|
||||
Thread *thread = THREAD;
|
||||
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
|
||||
JvmtiExport::post_class_prepare((JavaThread *) thread, this);
|
||||
@@ -1084,7 +1086,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
||||
// we might end up throwing IE from link/symbol resolution sites
|
||||
// that aren't expected to throw. This would wreak havoc. See 6320309.
|
||||
while ((is_being_initialized() && !is_reentrant_initialization(jt))
|
||||
- || (old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) {
|
||||
+ || (AllowEnhancedClassRedefinition && old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) {
|
||||
wait = true;
|
||||
jt->set_class_to_be_initialized(this);
|
||||
ol.wait_uninterruptibly(jt);
|
||||
@@ -3782,7 +3784,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");
|
||||
+ guarantee(sib->super() == super || AllowEnhancedClassRedefinition && super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass");
|
||||
}
|
||||
|
||||
// Verify local interfaces
|
||||
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
|
||||
index ce940cf10a9..2d8e5b0256b 100644
|
||||
--- a/src/hotspot/share/oops/method.cpp
|
||||
+++ b/src/hotspot/share/oops/method.cpp
|
||||
@@ -2208,7 +2208,7 @@ void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) {
|
||||
// Add a method id to the jmethod_ids
|
||||
jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) {
|
||||
// FIXME: (DCEVM) ???
|
||||
- if (m != m->newest_version()) {
|
||||
+ if (AllowEnhancedClassRedefinition && m != m->newest_version()) {
|
||||
m = m->newest_version();
|
||||
}
|
||||
ClassLoaderData* cld = loader_data;
|
||||
diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
index 1c7677f270f..6c12ee64a6e 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
// the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was
|
||||
// changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we
|
||||
// must use new versions only.
|
||||
- if (k->new_version()==NULL) {
|
||||
+ if (AllowEnhancedClassRedefinition && k->new_version()==NULL) {
|
||||
_classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
|
||||
if (_dictionary_walk) {
|
||||
// Collect array classes this way when walking the dictionary (because array classes are
|
||||
diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp
|
||||
index 0e7722dba7d..d67457f02ac 100644
|
||||
--- a/src/hotspot/share/runtime/reflection.cpp
|
||||
+++ b/src/hotspot/share/runtime/reflection.cpp
|
||||
@@ -628,7 +628,7 @@ bool Reflection::verify_member_access(const Klass* current_class,
|
||||
TRAPS) {
|
||||
|
||||
// (DCEVM) Decide accessibility based on active version
|
||||
- if (current_class != NULL) {
|
||||
+ if (AllowEnhancedClassRedefinition && current_class != NULL) {
|
||||
current_class = current_class->active_version();
|
||||
}
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From dc675de6ac42819b8536827ea450fcad13a97448 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Wed, 11 Nov 2020 18:45:15 +0100
|
||||
Subject: [PATCH 16/34] Fix LoadedClassesClosure - fixes problems with remote
|
||||
debugging
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
index 6c12ee64a6e..2a469555dbd 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
// the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was
|
||||
// changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we
|
||||
// must use new versions only.
|
||||
- if (AllowEnhancedClassRedefinition && k->new_version()==NULL) {
|
||||
+ if (!AllowEnhancedClassRedefinition || k->new_version()==NULL) {
|
||||
_classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
|
||||
if (_dictionary_walk) {
|
||||
// Collect array classes this way when walking the dictionary (because array classes are
|
||||
--
|
||||
2.23.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,183 @@
|
||||
From 1d682efa88c716e1849163d5abff3a3367581d16 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Mon, 16 Nov 2020 21:11:19 +0100
|
||||
Subject: [PATCH 18/34] pre dcevm15 - fix GC spaces originally in removed CMS
|
||||
patch
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.cpp | 16 ++++++++--------
|
||||
src/hotspot/share/gc/shared/space.hpp | 6 +++---
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 14 ++++++++------
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 6 ++----
|
||||
4 files changed, 21 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 875a6dc854f..9772c32c42e 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -375,11 +375,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 (cast_from_oop<HeapWord*>(q) != compact_top || (size_t)q->size() != size) {
|
||||
+ if (force_forward || cast_from_oop<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 {
|
||||
@@ -501,7 +501,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");
|
||||
@@ -824,14 +824,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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -845,7 +845,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.
|
||||
@@ -861,11 +861,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 c9bfc365f0f..f7648995454 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.hpp
|
||||
@@ -405,7 +405,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
|
||||
@@ -436,11 +436,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 5a93e93471b..fa645423685 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.
|
||||
@@ -362,8 +365,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 718426f2819..1da6661dd3e 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -431,13 +431,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);
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,942 @@
|
||||
From 297f564f6af79fb824f5b4e9119f1d3d0c827fb0 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Mon, 16 Nov 2020 20:20:12 +0100
|
||||
Subject: [PATCH 19/34] dcevm15 - fix java15 patch compilation issues
|
||||
|
||||
---
|
||||
.../share/classfile/classFileParser.hpp | 8 +-
|
||||
.../share/classfile/classLoaderData.cpp | 2 +-
|
||||
src/hotspot/share/classfile/dictionary.hpp | 10 +-
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 2 +
|
||||
.../share/gc/g1/g1FullGCCompactTask.cpp | 4 +-
|
||||
.../share/gc/g1/g1FullGCCompactionPoint.cpp | 8 +-
|
||||
.../share/gc/g1/g1FullGCPrepareTask.cpp | 4 +-
|
||||
src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 14 +-
|
||||
src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 2 +-
|
||||
src/hotspot/share/gc/shared/gcConfig.cpp | 2 +-
|
||||
src/hotspot/share/gc/shared/space.cpp | 4 +-
|
||||
.../share/interpreter/linkResolver.cpp | 2 +-
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 17 ++-
|
||||
src/hotspot/share/oops/instanceKlass.hpp | 1 +
|
||||
src/hotspot/share/oops/klass.cpp | 8 +-
|
||||
src/hotspot/share/prims/jvm.cpp | 2 +
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 129 +++++++++---------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 14 +-
|
||||
src/hotspot/share/prims/jvmtiEnv.cpp | 11 +-
|
||||
.../share/prims/jvmtiRedefineClasses.cpp | 1 +
|
||||
src/hotspot/share/prims/methodHandles.hpp | 3 +
|
||||
src/hotspot/share/runtime/arguments.cpp | 22 +--
|
||||
src/hotspot/share/runtime/mutexLocker.cpp | 2 +-
|
||||
23 files changed, 159 insertions(+), 113 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
index e5761e61767..0d266b9047e 100644
|
||||
--- a/src/hotspot/share/classfile/classFileParser.hpp
|
||||
+++ b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
@@ -150,9 +150,6 @@ class ClassFileParser {
|
||||
const intArray* _method_ordering;
|
||||
GrowableArray<Method*>* _all_mirandas;
|
||||
|
||||
- // Enhanced class redefinition
|
||||
- const bool _pick_newest;
|
||||
-
|
||||
enum { fixed_buffer_size = 128 };
|
||||
u_char _linenumbertable_buffer[fixed_buffer_size];
|
||||
|
||||
@@ -206,6 +203,9 @@ class ClassFileParser {
|
||||
bool _has_vanilla_constructor;
|
||||
int _max_bootstrap_specifier_index; // detects BSS values
|
||||
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
+ const bool _pick_newest;
|
||||
+
|
||||
void parse_stream(const ClassFileStream* const stream, TRAPS);
|
||||
|
||||
void mangle_hidden_class_name(InstanceKlass* const ik);
|
||||
@@ -582,7 +582,7 @@ class ClassFileParser {
|
||||
ClassLoaderData* loader_data() const { return _loader_data; }
|
||||
const Symbol* class_name() const { return _class_name; }
|
||||
const InstanceKlass* super_klass() const { return _super_klass; }
|
||||
- Array<Klass*>* local_interfaces() const { return _local_interfaces; }
|
||||
+ Array<InstanceKlass*>* local_interfaces() const { return _local_interfaces; }
|
||||
|
||||
ReferenceType reference_type() const { return _rt; }
|
||||
AccessFlags access_flags() const { return _access_flags; }
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index 4d64c6b454a..aadcd50ef4a 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -597,7 +597,7 @@ 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;
|
||||
+ WeakHandle<vm_weak_data> exchange = _holder;
|
||||
_holder = cld->_holder;
|
||||
cld->_holder = exchange;
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp
|
||||
index 114a983e783..a50f4ff84d2 100644
|
||||
--- a/src/hotspot/share/classfile/dictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/dictionary.hpp
|
||||
@@ -84,6 +84,11 @@ public:
|
||||
void print_on(outputStream* st) const;
|
||||
void verify();
|
||||
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
+ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass);
|
||||
+
|
||||
+ void rollback_redefinition();
|
||||
+
|
||||
private:
|
||||
DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass);
|
||||
|
||||
@@ -106,11 +111,6 @@ public:
|
||||
|
||||
void free_entry(DictionaryEntry* entry);
|
||||
|
||||
- // Enhanced class redefinition
|
||||
- bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass);
|
||||
-
|
||||
- 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/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index a68c5139151..9abf2e1d105 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -255,7 +255,9 @@ class java_lang_Class : AllStatic {
|
||||
static void set_init_lock(oop java_class, oop init_lock);
|
||||
static void set_protection_domain(oop java_class, oop protection_domain);
|
||||
static void set_class_loader(oop java_class, oop class_loader);
|
||||
+ public: // DCEVM
|
||||
static void set_component_mirror(oop java_class, oop comp_mirror);
|
||||
+ private:
|
||||
static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain,
|
||||
Handle classData, TRAPS);
|
||||
static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS);
|
||||
diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
||||
index f70f4606dc8..a22ed48560d 100644
|
||||
--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
||||
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
||||
@@ -157,14 +157,14 @@ void G1FullGCCompactTask::serial_compaction_dcevm() {
|
||||
|
||||
size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) {
|
||||
size_t size = obj->size();
|
||||
- HeapWord* destination = (HeapWord*)obj->forwardee();
|
||||
+ HeapWord* destination = cast_from_oop<HeapWord*>(obj->forwardee());
|
||||
if (destination == NULL) {
|
||||
// Object not moving
|
||||
return size;
|
||||
}
|
||||
|
||||
// copy object and reinit its mark
|
||||
- HeapWord* obj_addr = (HeapWord*) obj;
|
||||
+ HeapWord* obj_addr = cast_from_oop<HeapWord*>(obj);
|
||||
|
||||
if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) {
|
||||
++(*_rescue_oops_it);
|
||||
diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
||||
index 1e49571c999..755935a2c91 100644
|
||||
--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
||||
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
||||
@@ -174,7 +174,7 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_
|
||||
assert(_current_region != NULL, "Must have been initialized");
|
||||
|
||||
// Store a forwarding pointer if the object should be moved.
|
||||
- if ((HeapWord*)object != _compaction_top || force_forward) {
|
||||
+ if (cast_from_oop<HeapWord*>(object) != _compaction_top || force_forward) {
|
||||
object->forward_to(oop(_compaction_top));
|
||||
} else {
|
||||
if (object->forwardee() != NULL) {
|
||||
@@ -188,11 +188,11 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_
|
||||
} else {
|
||||
// Make sure object has the correct mark-word set or that it will be
|
||||
// fixed when restoring the preserved marks.
|
||||
- assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark
|
||||
- object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet
|
||||
+ assert(object->mark_raw() == markWord::prototype_for_klass(object->klass()) || // Correct mark
|
||||
+ object->mark_must_be_preserved() || // Will be restored by PreservedMarksSet
|
||||
(UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking
|
||||
"should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT,
|
||||
- p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object)));
|
||||
+ p2i(object), object->mark_raw().value(), markWord::prototype_for_klass(object->klass()).value());
|
||||
}
|
||||
assert(object->forwardee() == NULL, "should be forwarded to NULL");
|
||||
}
|
||||
diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
index a45681b60cf..2f06b9617e4 100644
|
||||
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
@@ -269,7 +269,7 @@ size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object)
|
||||
HeapWord* compact_top = _cp->forward_compact_top(forward_size);
|
||||
|
||||
if (compact_top == NULL || must_rescue(object, oop(compact_top))) {
|
||||
- _cp->rescued_oops()->append((HeapWord*)object);
|
||||
+ _cp->rescued_oops()->append(cast_from_oop<HeapWord*>(object));
|
||||
} else {
|
||||
_cp->forward_dcevm(object, forward_size, (size != forward_size));
|
||||
}
|
||||
@@ -295,7 +295,7 @@ bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_
|
||||
int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version());
|
||||
int original_size = old_obj->size();
|
||||
|
||||
- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size);
|
||||
+ bool overlap = (cast_from_oop<HeapWord*>(old_obj) + original_size < cast_from_oop<HeapWord*>(new_obj) + new_size);
|
||||
|
||||
return overlap;
|
||||
}
|
||||
diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
||||
index 803e645f843..3dee097f1d3 100644
|
||||
--- a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
||||
@@ -58,10 +58,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_
|
||||
DcevmSharedGC::update_fields(rescued_obj, new_obj);
|
||||
} else {
|
||||
rescued_obj->set_klass(new_klass);
|
||||
- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size);
|
||||
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(new_obj), size);
|
||||
}
|
||||
} else {
|
||||
- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size);
|
||||
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(new_obj), size);
|
||||
}
|
||||
|
||||
new_obj->init_mark_raw();
|
||||
@@ -111,11 +111,11 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
||||
|
||||
// Save object somewhere, there is an overlap in fields
|
||||
if (new_klass_oop->is_copying_backwards()) {
|
||||
- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) ||
|
||||
- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) {
|
||||
+ if ((cast_from_oop<HeapWord*>(q) >= cast_from_oop<HeapWord*>(new_location) && cast_from_oop<HeapWord*>(q) < cast_from_oop<HeapWord*>(new_location) + new_size) ||
|
||||
+ (cast_from_oop<HeapWord*>(new_location) >= cast_from_oop<HeapWord*>(q) && cast_from_oop<HeapWord*>(new_location) < cast_from_oop<HeapWord*>(q) + size)) {
|
||||
tmp = NEW_RESOURCE_ARRAY(HeapWord, size);
|
||||
q = (oop) tmp;
|
||||
- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size);
|
||||
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(tmp_obj), cast_from_oop<HeapWord*>(q), size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,13 +131,13 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
||||
|
||||
void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) {
|
||||
assert(cur != NULL, "just checking");
|
||||
- char* to = (char*)(HeapWord*)new_location;
|
||||
+ char* to = (char*)cast_from_oop<HeapWord*>(new_location);
|
||||
while (*cur != 0) {
|
||||
int size = *cur;
|
||||
if (size > 0) {
|
||||
cur++;
|
||||
int offset = *cur;
|
||||
- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset);
|
||||
+ HeapWord* from = (HeapWord*)(((char *)cast_from_oop<HeapWord*>(tmp_obj)) + offset);
|
||||
if (size == HeapWordSize) {
|
||||
*((HeapWord*)to) = *from;
|
||||
} else if (size == HeapWordSize * 2) {
|
||||
diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
||||
index e2ef0171fb2..a4e27e00280 100644
|
||||
--- a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "gc/shared/genOopClosures.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
-#include "oops/markOop.hpp"
|
||||
+#include "oops/markWord.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "runtime/timer.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
index f01d64d1434..5c1a09390f1 100644
|
||||
--- a/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
@@ -100,7 +100,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() {
|
||||
void GCConfig::select_gc_ergonomically() {
|
||||
if (AllowEnhancedClassRedefinition && !UseG1GC) {
|
||||
// Enhanced class redefinition only supports serial GC at the moment
|
||||
- FLAG_SET_ERGO(bool, UseSerialGC, true);
|
||||
+ FLAG_SET_ERGO(UseSerialGC, true);
|
||||
} else if (os::is_server_class_machine()) {
|
||||
#if INCLUDE_G1GC
|
||||
FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true);
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 9772c32c42e..e8e3d7884c2 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -440,7 +440,7 @@ int CompactibleSpace::space_index(oop obj) {
|
||||
index++;
|
||||
}
|
||||
|
||||
- tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj);
|
||||
+ tty->print_cr("could not compute space_index for %08xh", cast_from_oop<HeapWord*>(obj));
|
||||
index = 0;
|
||||
|
||||
Generation* gen = heap->old_gen();
|
||||
@@ -485,7 +485,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_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);
|
||||
+ bool overlap = (cast_from_oop<HeapWord*>(old_obj) + original_size < cast_from_oop<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.
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index b2f24ddbeda..9daeeb70b34 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -1031,7 +1031,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||
assert(m != 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()->name() == vmSymbols::ha_class_initializer_name()));
|
||||
+ !(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());
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index f8e60941046..5e40d78a87e 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -1316,7 +1316,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();
|
||||
+ Klass* volatile* addr = adr_implementor();
|
||||
assert(addr != NULL, "null addr");
|
||||
if (addr != NULL) {
|
||||
*addr = NULL;
|
||||
@@ -1659,6 +1659,21 @@ void InstanceKlass::methods_do(void f(Method* method)) {
|
||||
}
|
||||
}
|
||||
|
||||
+void InstanceKlass::methods_do(void f(Method* method, TRAPS), TRAPS) {
|
||||
+ // Methods aren't stable until they are loaded. This can be read outside
|
||||
+ // a lock through the ClassLoaderData for profiling
|
||||
+ if (!is_loaded()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int len = methods()->length();
|
||||
+ for (int index = 0; index < len; index++) {
|
||||
+ Method* m = methods()->at(index);
|
||||
+ assert(m->is_method(), "must be method");
|
||||
+ f(m, CHECK);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// (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) {
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
index 6ead9426728..b56d42cb177 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.hpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
@@ -1069,6 +1069,7 @@ public:
|
||||
void clear_update_information();
|
||||
|
||||
void methods_do(void f(Method* method));
|
||||
+ void methods_do(void f(Method* method, TRAPS), TRAPS);
|
||||
void array_klasses_do(void f(Klass* k));
|
||||
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
|
||||
|
||||
diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp
|
||||
index 352d8f84631..88f5ec9ba4a 100644
|
||||
--- a/src/hotspot/share/oops/klass.cpp
|
||||
+++ b/src/hotspot/share/oops/klass.cpp
|
||||
@@ -200,13 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word
|
||||
Klass::Klass(KlassID id) : _id(id),
|
||||
_java_mirror(NULL),
|
||||
_prototype_header(markWord::prototype()),
|
||||
- _shared_class_path_index(-1),
|
||||
- _new_version(NULL),
|
||||
_old_version(NULL),
|
||||
+ _new_version(NULL),
|
||||
+ _redefinition_flags(Klass::NoRedefinition),
|
||||
_is_redefining(false),
|
||||
+ _update_information(NULL),
|
||||
_is_copying_backwards(false),
|
||||
- _redefinition_flags(Klass::NoRedefinition),
|
||||
- _update_information(NULL) {
|
||||
+ _shared_class_path_index(-1) {
|
||||
CDS_ONLY(_shared_class_flags = 0;)
|
||||
CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;)
|
||||
_primary_supers[0] = this;
|
||||
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
|
||||
index 333b65ccfc1..13bcac352fb 100644
|
||||
--- a/src/hotspot/share/prims/jvm.cpp
|
||||
+++ b/src/hotspot/share/prims/jvm.cpp
|
||||
@@ -1054,6 +1054,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na
|
||||
class_loader,
|
||||
protection_domain,
|
||||
&st,
|
||||
+ NULL,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve) && defined_k != NULL) {
|
||||
@@ -1074,6 +1075,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na
|
||||
class_loader,
|
||||
&st,
|
||||
cl_info,
|
||||
+ NULL,
|
||||
CHECK_NULL);
|
||||
if (defined_k == NULL) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a hidden class");
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 1da6661dd3e..619e3988e3a 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -24,11 +24,14 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "aot/aotLoader.hpp"
|
||||
+#include "classfile/classFileParser.hpp"
|
||||
#include "classfile/classFileStream.hpp"
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/verifier.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
+#include "classfile/classLoaderDataGraph.hpp"
|
||||
+#include "interpreter/linkResolver.hpp"
|
||||
#include "interpreter/oopMapCache.hpp"
|
||||
#include "interpreter/rewriter.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@@ -37,17 +40,22 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
+#include "oops/fieldStreams.inline.hpp"
|
||||
#include "oops/klassVtable.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/constantPool.inline.hpp"
|
||||
+#include "oops/metadata.hpp"
|
||||
+#include "oops/methodData.hpp"
|
||||
#include "prims/jvmtiImpl.hpp"
|
||||
#include "prims/jvmtiClassFileReconstituter.hpp"
|
||||
#include "prims/jvmtiEnhancedRedefineClasses.hpp"
|
||||
#include "prims/methodComparator.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
+#include "prims/methodHandles.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/relocator.hpp"
|
||||
+#include "runtime/fieldDescriptor.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
@@ -55,6 +63,8 @@
|
||||
#include "oops/constantPool.inline.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/shared/dcevmSharedGC.hpp"
|
||||
+#include "gc/shared/scavengableNMethods.hpp"
|
||||
+#include "ci/ciObjectFactory.hpp"
|
||||
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_old_methods = NULL;
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_new_methods = NULL;
|
||||
@@ -66,6 +76,7 @@ int VM_EnhancedRedefineClasses::_matching_methods_length = 0;
|
||||
int VM_EnhancedRedefineClasses::_deleted_methods_length = 0;
|
||||
int VM_EnhancedRedefineClasses::_added_methods_length = 0;
|
||||
Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL;
|
||||
+u8 VM_EnhancedRedefineClasses::_id_counter = 0;
|
||||
|
||||
//
|
||||
// Create new instance of enhanced class redefiner.
|
||||
@@ -88,6 +99,7 @@ VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const j
|
||||
_class_load_kind = class_load_kind;
|
||||
_res = JVMTI_ERROR_NONE;
|
||||
_any_class_has_resolved_methods = false;
|
||||
+ _id = next_id();
|
||||
}
|
||||
|
||||
static inline InstanceKlass* get_ik(jclass def) {
|
||||
@@ -211,9 +223,7 @@ class FieldCopier : public FieldClosure {
|
||||
|
||||
// TODO: review...
|
||||
void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
- if (!nm->on_scavenge_root_list()) {
|
||||
- CodeCache::add_scavenge_root_nmethod(nm);
|
||||
- }
|
||||
+ ScavengableNMethods::register_nmethod(nm);
|
||||
}
|
||||
|
||||
void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) {
|
||||
@@ -414,7 +424,7 @@ public:
|
||||
_tmp_obj_size = size;
|
||||
_tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize);
|
||||
}
|
||||
- Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size);
|
||||
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(o), cast_from_oop<HeapWord*>(_tmp_obj), size);
|
||||
}
|
||||
|
||||
virtual void do_object(oop obj) {
|
||||
@@ -505,9 +515,6 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
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;
|
||||
@@ -564,8 +571,8 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
InstanceKlass* old = InstanceKlass::cast(cur->old_version());
|
||||
|
||||
// Swap marks to have same hashcodes
|
||||
- markOop cur_mark = cur->prototype_header();
|
||||
- markOop old_mark = old->prototype_header();
|
||||
+ markWord cur_mark = cur->prototype_header();
|
||||
+ markWord old_mark = old->prototype_header();
|
||||
cur->set_prototype_header(old_mark);
|
||||
old->set_prototype_header(cur_mark);
|
||||
|
||||
@@ -579,14 +586,14 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// Revert pool holder for old version of klass (it was updated by one of ours closure!)
|
||||
old->constants()->set_pool_holder(old);
|
||||
|
||||
- Klass* array_klasses = old->array_klasses();
|
||||
+ ObjArrayKlass* array_klasses = old->array_klasses();
|
||||
if (array_klasses != NULL) {
|
||||
assert(cur->array_klasses() == NULL, "just checking");
|
||||
|
||||
// Transfer the array classes, otherwise we might get cast exceptions when casting array types.
|
||||
// Also, set array klasses element klass.
|
||||
cur->set_array_klasses(array_klasses);
|
||||
- ObjArrayKlass::cast(array_klasses)->set_element_klass(cur);
|
||||
+ array_klasses->set_element_klass(cur);
|
||||
java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses);
|
||||
java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror());
|
||||
}
|
||||
@@ -641,11 +648,15 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
//ClassLoaderDataGraph::classes_do(&clean_weak_method_links);
|
||||
|
||||
// Disable any dependent concurrent compilations
|
||||
- SystemDictionary::notice_modification();
|
||||
+ // SystemDictionary::notice_modification();
|
||||
+
|
||||
+ JvmtiExport::increment_redefinition_count();
|
||||
|
||||
// Set flag indicating that some invariants are no longer true.
|
||||
// See jvmtiExport.hpp for detailed explanation.
|
||||
- JvmtiExport::set_has_redefined_a_class();
|
||||
+
|
||||
+ // dcevm15: handled by _redefinition_count
|
||||
+ // JvmtiExport::set_has_redefined_a_class();
|
||||
|
||||
#ifdef PRODUCT
|
||||
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
@@ -718,7 +729,7 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
}
|
||||
|
||||
// Cannot redefine or retransform an anonymous class.
|
||||
- if (InstanceKlass::cast(k)->is_anonymous()) {
|
||||
+ if (InstanceKlass::cast(k)->is_unsafe_anonymous()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -804,22 +815,30 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
|
||||
InstanceKlass* k;
|
||||
|
||||
- if (InstanceKlass::cast(the_class)->is_anonymous()) {
|
||||
- const InstanceKlass* host_class = the_class->host_klass();
|
||||
+ if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) {
|
||||
+ const InstanceKlass* host_class = the_class->unsafe_anonymous_host();
|
||||
|
||||
// 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();
|
||||
+ while (host_class != NULL && host_class->is_unsafe_anonymous()) {
|
||||
+ host_class = host_class->unsafe_anonymous_host();
|
||||
}
|
||||
|
||||
+ ClassLoadInfo cl_info(protection_domain,
|
||||
+ host_class,
|
||||
+ NULL, // dynamic_nest_host
|
||||
+ NULL, // cp_patches
|
||||
+ Handle(), // classData
|
||||
+ false, // is_hidden
|
||||
+ false, // is_strong_hidden
|
||||
+ true); // FIXME: check if correct. can_access_vm_annotations
|
||||
+
|
||||
k = SystemDictionary::parse_stream(the_class_sym,
|
||||
the_class_loader,
|
||||
- protection_domain,
|
||||
&st,
|
||||
- host_class,
|
||||
+ cl_info,
|
||||
the_class,
|
||||
- NULL,
|
||||
THREAD);
|
||||
+
|
||||
k->class_loader_data()->exchange_holders(the_class->class_loader_data());
|
||||
the_class->class_loader_data()->inc_keep_alive();
|
||||
} else {
|
||||
@@ -966,7 +985,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
// Check interfaces
|
||||
|
||||
// Interfaces removed?
|
||||
- Array<Klass*>* old_interfaces = the_class->transitive_interfaces();
|
||||
+ Array<InstanceKlass*>* old_interfaces = the_class->transitive_interfaces();
|
||||
for (i = 0; i < old_interfaces->length(); i++) {
|
||||
InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i));
|
||||
if (!new_class->implements_interface_any_version(old_interface)) {
|
||||
@@ -976,7 +995,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
}
|
||||
|
||||
// Interfaces added?
|
||||
- Array<Klass*>* new_interfaces = new_class->transitive_interfaces();
|
||||
+ Array<InstanceKlass*>* new_interfaces = new_class->transitive_interfaces();
|
||||
for (i = 0; i<new_interfaces->length(); i++) {
|
||||
if (!the_class->implements_interface_any_version(new_interfaces->at(i))) {
|
||||
result = result | Klass::ModifyClass;
|
||||
@@ -1389,8 +1408,8 @@ void VM_EnhancedRedefineClasses::rollback() {
|
||||
// Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp
|
||||
// The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not
|
||||
// do that, they assume that cache entry is resolved already.
|
||||
-void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
||||
- RawBytecodeStream bcs(method);
|
||||
+void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method, TRAPS) {
|
||||
+ RawBytecodeStream bcs(methodHandle(THREAD, method));
|
||||
Bytecodes::Code code;
|
||||
Bytecodes::Code java_code;
|
||||
while (!bcs.is_last_bytecode()) {
|
||||
@@ -1454,11 +1473,11 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
HandleMark hm(_thread);
|
||||
InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
|
||||
- constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
+ constantPoolHandle other_cp = constantPoolHandle(_thread, 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) {
|
||||
- ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version()));
|
||||
+ if (ik->is_unsafe_anonymous() && ik->unsafe_anonymous_host()->new_version() != NULL) {
|
||||
+ ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version()));
|
||||
}
|
||||
|
||||
// Update implementor if there is only one, in this case implementor() can reference old class
|
||||
@@ -1492,7 +1511,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
|
||||
// If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries
|
||||
if (RewriteBytecodes) {
|
||||
- ik->methods_do(unpatch_bytecode);
|
||||
+ ik->methods_do(unpatch_bytecode, _thread);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+u8 VM_EnhancedRedefineClasses::next_id() {
|
||||
+ while (true) {
|
||||
+ u8 id = _id_counter;
|
||||
+ u8 next_id = id + 1;
|
||||
+ u8 result = Atomic::cmpxchg(&_id_counter, id, next_id);
|
||||
+ if (result == id) {
|
||||
+ return next_id;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1512,31 +1542,8 @@ 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() {
|
||||
+void VM_EnhancedRedefineClasses::update_jmethod_ids(TRAPS) {
|
||||
for (int j = 0; j < _matching_methods_length; ++j) {
|
||||
Method* old_method = _matching_old_methods[j];
|
||||
jmethodID jmid = old_method->find_jmethod_id_or_null();
|
||||
@@ -1547,10 +1554,10 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
||||
|
||||
if (jmid != NULL) {
|
||||
// There is a jmethodID, change it to point to the new method
|
||||
- methodHandle new_method_h(_matching_new_methods[j]);
|
||||
+ methodHandle new_method_h(THREAD, _matching_new_methods[j]);
|
||||
|
||||
if (old_method->new_version() == NULL) {
|
||||
- methodHandle old_method_h(_matching_old_methods[j]);
|
||||
+ methodHandle old_method_h(THREAD, _matching_old_methods[j]);
|
||||
jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h());
|
||||
bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id);
|
||||
} else {
|
||||
@@ -1887,7 +1894,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
|
||||
// track number of methods that are EMCP for add_previous_version() call below
|
||||
check_methods_and_mark_as_obsolete();
|
||||
- update_jmethod_ids();
|
||||
+ update_jmethod_ids(THREAD);
|
||||
|
||||
_any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods;
|
||||
|
||||
@@ -2119,12 +2126,12 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
|
||||
Handle protection_domain(THREAD, klass->protection_domain());
|
||||
|
||||
+ ClassLoadInfo cl_info(protection_domain);
|
||||
+
|
||||
ClassFileParser parser(&st,
|
||||
klass->name(),
|
||||
klass->class_loader_data(),
|
||||
- protection_domain,
|
||||
- NULL, // host_klass
|
||||
- NULL, // cp_patches
|
||||
+ &cl_info,
|
||||
ClassFileParser::INTERNAL, // publicity level
|
||||
true,
|
||||
THREAD);
|
||||
@@ -2134,7 +2141,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
links.append(KlassPair(super_klass, klass));
|
||||
}
|
||||
|
||||
- Array<Klass*>* local_interfaces = parser.local_interfaces();
|
||||
+ Array<InstanceKlass*>* local_interfaces = parser.local_interfaces();
|
||||
for (int j = 0; j < local_interfaces->length(); j++) {
|
||||
Klass* iface = local_interfaces->at(j);
|
||||
if (iface != NULL && _affected_klasses->contains(iface)) {
|
||||
@@ -2157,7 +2164,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
links.append(KlassPair(super_klass, klass));
|
||||
}
|
||||
|
||||
- Array<Klass*>* local_interfaces = klass->local_interfaces();
|
||||
+ Array<InstanceKlass*>* local_interfaces = klass->local_interfaces();
|
||||
for (int j = 0; j < local_interfaces->length(); j++) {
|
||||
Klass* interfaceKlass = local_interfaces->at(j);
|
||||
if (_affected_klasses->contains(interfaceKlass)) {
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 4c0412d343d..0066088b3b0 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
-#include "gc/shared/vmGCOperations.hpp"
|
||||
+#include "gc/shared/gcVMOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
//
|
||||
@@ -59,6 +59,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
static int _deleted_methods_length;
|
||||
static int _added_methods_length;
|
||||
static Klass* _the_class_oop;
|
||||
+ static u8 _id_counter;
|
||||
|
||||
// The instance fields are used to pass information from
|
||||
// doit_prologue() to doit() and doit_epilogue().
|
||||
@@ -91,6 +92,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
elapsedTimer _timer_heap_iterate;
|
||||
elapsedTimer _timer_heap_full_gc;
|
||||
|
||||
+ // Redefinition id used by JFR
|
||||
+ u8 _id;
|
||||
+
|
||||
// These routines are roughly in call order unless otherwise noted.
|
||||
|
||||
// Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
@@ -118,15 +122,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
static void mark_as_scavengable(nmethod* nm);
|
||||
static void unregister_nmethod_g1(nmethod* nm);
|
||||
static void register_nmethod_g1(nmethod* nm);
|
||||
- static void unpatch_bytecode(Method* method);
|
||||
- static void fix_invoke_method(Method* method);
|
||||
+ static void unpatch_bytecode(Method* method, TRAPS);
|
||||
|
||||
// Figure out which new methods match old methods in name and signature,
|
||||
// which methods have been added, and which are no longer present
|
||||
void compute_added_deleted_matching_methods();
|
||||
|
||||
// Change jmethodIDs to point to the new methods
|
||||
- void update_jmethod_ids();
|
||||
+ void update_jmethod_ids(TRAPS);
|
||||
|
||||
// marking methods as old and/or obsolete
|
||||
void check_methods_and_mark_as_obsolete();
|
||||
@@ -141,6 +144,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
void flush_dependent_code(InstanceKlass* k_h, TRAPS);
|
||||
|
||||
+ u8 next_id();
|
||||
+
|
||||
static void check_class(InstanceKlass* k_oop, TRAPS);
|
||||
|
||||
static void dump_methods();
|
||||
@@ -181,6 +186,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
bool allow_nested_vm_operations() const { return true; }
|
||||
jvmtiError check_error() { return _res; }
|
||||
+ u8 id() { return _id; }
|
||||
|
||||
// Modifiable test must be shared between IsModifiableClass query
|
||||
// and redefine implementation
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
|
||||
index b6838ac034d..fba0f48abd7 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
|
||||
@@ -456,20 +456,23 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
|
||||
|
||||
EventRetransformClasses event;
|
||||
jvmtiError error;
|
||||
+ u8 op_id;
|
||||
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
MutexLocker sd_mutex(EnhancedRedefineClasses_lock);
|
||||
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
|
||||
VMThread::execute(&op);
|
||||
+ op_id = op.id();
|
||||
error = (op.check_error());
|
||||
} else {
|
||||
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
|
||||
VMThread::execute(&op);
|
||||
+ op_id = op.id();
|
||||
error = op.check_error();
|
||||
}
|
||||
if (error == JVMTI_ERROR_NONE) {
|
||||
event.set_classCount(class_count);
|
||||
- event.set_redefinitionId(op.id());
|
||||
+ event.set_redefinitionId(op_id);
|
||||
event.commit();
|
||||
}
|
||||
return error;
|
||||
@@ -484,19 +487,23 @@ JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_de
|
||||
EventRedefineClasses event;
|
||||
jvmtiError error;
|
||||
|
||||
+ u8 op_id;
|
||||
+
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
MutexLocker sd_mutex(EnhancedRedefineClasses_lock);
|
||||
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
VMThread::execute(&op);
|
||||
+ op_id = op.id();
|
||||
error = (op.check_error());
|
||||
} else {
|
||||
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
VMThread::execute(&op);
|
||||
+ op_id = op.id();
|
||||
error = op.check_error();
|
||||
}
|
||||
if (error == JVMTI_ERROR_NONE) {
|
||||
event.set_classCount(class_count);
|
||||
- event.set_redefinitionId(op.id());
|
||||
+ event.set_redefinitionId(op_id);
|
||||
event.commit();
|
||||
}
|
||||
return error;
|
||||
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
||||
index a7840848e10..346eac7c431 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
||||
@@ -1271,6 +1271,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
|
||||
the_class_loader,
|
||||
&st,
|
||||
cl_info,
|
||||
+ NULL,
|
||||
THREAD);
|
||||
// Clear class_being_redefined just to be sure.
|
||||
state->clear_class_being_redefined();
|
||||
diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp
|
||||
index 54f36202a5f..917d31efd77 100644
|
||||
--- a/src/hotspot/share/prims/methodHandles.hpp
|
||||
+++ b/src/hotspot/share/prims/methodHandles.hpp
|
||||
@@ -180,6 +180,9 @@ public:
|
||||
assert(ref_kind_is_valid(ref_kind), "");
|
||||
return (ref_kind & 1) != 0;
|
||||
}
|
||||
+ static bool ref_kind_is_static(int ref_kind) {
|
||||
+ return !ref_kind_has_receiver(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial);
|
||||
+ }
|
||||
|
||||
static int ref_kind_to_flags(int ref_kind);
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index d05a2893498..3a92b8869dc 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -2128,13 +2128,15 @@ bool Arguments::check_gc_consistency() {
|
||||
// of collectors.
|
||||
uint i = 0;
|
||||
if (UseSerialGC) i++;
|
||||
- if (UseConcMarkSweepGC) i++;
|
||||
- if (UseParallelGC || UseParallelOldGC) i++;
|
||||
+ if (UseParallelGC) i++;
|
||||
if (UseG1GC) i++;
|
||||
+ if (UseEpsilonGC) i++;
|
||||
+ if (UseZGC) i++;
|
||||
+ if (UseShenandoahGC) i++;
|
||||
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 && !UseG1GC) && i >= 1) {
|
||||
+ if (!UseSerialGC && !UseG1GC && i >= 1) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Must use the Serial or G1 GC with enhanced class redefinition.\n");
|
||||
return false;
|
||||
@@ -4494,18 +4496,18 @@ void Arguments::setup_hotswap_agent() {
|
||||
|
||||
// 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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_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++);
|
||||
+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp
|
||||
index 6f982072909..14a3ed730fe 100644
|
||||
--- a/src/hotspot/share/runtime/mutexLocker.cpp
|
||||
+++ b/src/hotspot/share/runtime/mutexLocker.cpp
|
||||
@@ -287,7 +287,7 @@ void mutex_init() {
|
||||
def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never);
|
||||
def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never);
|
||||
def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always);
|
||||
- def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel
|
||||
+ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, _safepoint_check_always); // for ensuring that class redefinition is not done in parallel
|
||||
def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions
|
||||
def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always);
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
25
jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch
Normal file
25
jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 336cab4f72c6e642e3077ea8d1a4860de33f5a4d Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Tue, 17 Nov 2020 17:40:24 +0100
|
||||
Subject: [PATCH 20/34] dcevm15 - G1 fixes
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
index 2f06b9617e4..476728a5d26 100644
|
||||
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
||||
@@ -240,7 +240,7 @@ void G1FullGCPrepareTask::prepare_serial_compaction_dcevm() {
|
||||
|
||||
// collect remaining, not forwarded rescued oops using serial compact point
|
||||
while (cp->last_rescued_oop() < cp->rescued_oops()->length()) {
|
||||
- HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, false, true);
|
||||
+ HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, HeapRegionType::Eden, true, G1NUMA::AnyNodeIndex);
|
||||
if (hr == NULL) {
|
||||
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "G1 - not enough of free regions after redefinition.");
|
||||
}
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
From cea4e2cca3c37233c728be7235f8f9d8be136cb5 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Tue, 17 Nov 2020 18:52:57 +0100
|
||||
Subject: [PATCH 21/34] dcevm15 - Fix flush dependent code
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 57 +++++++------------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 4 +-
|
||||
2 files changed, 25 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 619e3988e3a..efaf11e1666 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -508,7 +508,7 @@ 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) {
|
||||
- flush_dependent_code(NULL, thread);
|
||||
+ flush_dependent_code(thread);
|
||||
// }
|
||||
|
||||
// Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
@@ -647,17 +647,8 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
//MethodDataCleaner clean_weak_method_links;
|
||||
//ClassLoaderDataGraph::classes_do(&clean_weak_method_links);
|
||||
|
||||
- // Disable any dependent concurrent compilations
|
||||
- // SystemDictionary::notice_modification();
|
||||
-
|
||||
JvmtiExport::increment_redefinition_count();
|
||||
|
||||
- // Set flag indicating that some invariants are no longer true.
|
||||
- // See jvmtiExport.hpp for detailed explanation.
|
||||
-
|
||||
- // dcevm15: handled by _redefinition_count
|
||||
- // JvmtiExport::set_has_redefined_a_class();
|
||||
-
|
||||
#ifdef PRODUCT
|
||||
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
#endif
|
||||
@@ -1746,6 +1737,18 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst
|
||||
transfer.transfer_registrations(_matching_old_methods, _matching_methods_length);
|
||||
}
|
||||
|
||||
+// First step is to walk the code cache for each class redefined and mark
|
||||
+// dependent methods. Wait until all classes are processed to deoptimize everything.
|
||||
+void VM_EnhancedRedefineClasses::mark_dependent_code(InstanceKlass* ik) {
|
||||
+ assert_locked_or_safepoint(Compile_lock);
|
||||
+
|
||||
+ // All dependencies have been recorded from startup or this is a second or
|
||||
+ // subsequent use of RedefineClasses
|
||||
+ if (0 && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
+ CodeCache::mark_for_evol_deoptimization(ik);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// DCEVM - it always deoptimizes everything! (because it is very difficult to find only correct dependencies)
|
||||
// Deoptimize all compiled code that depends on this class.
|
||||
//
|
||||
@@ -1762,33 +1765,21 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst
|
||||
// subsequent calls to RedefineClasses need only throw away code
|
||||
// that depends on the class.
|
||||
//
|
||||
-void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) {
|
||||
+void VM_EnhancedRedefineClasses::flush_dependent_code(TRAPS) {
|
||||
assert_locked_or_safepoint(Compile_lock);
|
||||
|
||||
// All dependencies have been recorded from startup or this is a second or
|
||||
// subsequent use of RedefineClasses
|
||||
// FIXME: for now, deoptimize all!
|
||||
- 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();
|
||||
+ if (0 && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
+ int deopt = CodeCache::mark_dependents_for_evol_deoptimization();
|
||||
+ log_debug(redefine, class, nmethod)("Marked %d dependent nmethods for deopt", deopt);
|
||||
+ if (deopt != 0) {
|
||||
+ CodeCache::flush_evol_dependents();
|
||||
}
|
||||
} else {
|
||||
- CodeCache::mark_all_nmethods_for_deoptimization();
|
||||
-
|
||||
- ResourceMark rm(THREAD);
|
||||
- DeoptimizationMarker dm;
|
||||
-
|
||||
- // Deoptimize all activations depending on marked nmethods
|
||||
- Deoptimization::deoptimize_dependents();
|
||||
-
|
||||
- // Make the dependent methods not entrant
|
||||
- CodeCache::make_marked_nmethods_not_entrant();
|
||||
-
|
||||
- // From now on we know that the dependency information is complete
|
||||
+ CodeCache::mark_all_nmethods_for_evol_deoptimization();
|
||||
+ CodeCache::flush_evol_dependents();
|
||||
JvmtiExport::set_all_dependencies_are_recorded(true);
|
||||
}
|
||||
}
|
||||
@@ -1881,11 +1872,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
|
||||
jvmti_breakpoints.clearall_in_class_at_safepoint(the_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);
|
||||
-// }
|
||||
+ mark_dependent_code(the_class);
|
||||
|
||||
_old_methods = the_class->methods();
|
||||
_new_methods = new_class->methods();
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 0066088b3b0..bd5e7d153be 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -142,7 +142,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// and in all direct and indirect subclasses.
|
||||
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
||||
|
||||
- void flush_dependent_code(InstanceKlass* k_h, TRAPS);
|
||||
+ void mark_dependent_code(InstanceKlass* ik);
|
||||
+
|
||||
+ void flush_dependent_code(TRAPS);
|
||||
|
||||
u8 next_id();
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
From 4f88dcec830d39452f69d1117729469fdb768a8f Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 22 Nov 2020 12:05:26 +0100
|
||||
Subject: [PATCH 22/34] dcevm15 - fix ResolvedMethodTable
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/javaClasses.cpp | 5 -
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 1 -
|
||||
.../share/prims/resolvedMethodTable.cpp | 139 +++++++++++-------
|
||||
3 files changed, 84 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
index 9b086a241f7..9a627786d0f 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.cpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
@@ -3996,11 +3996,6 @@ void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop
|
||||
resolved_method->obj_field_put(_vmholder_offset, holder);
|
||||
}
|
||||
|
||||
-void java_lang_invoke_ResolvedMethodName::set_vmholder_offset(oop resolved_method, Method* m) {
|
||||
- assert(is_instance(resolved_method), "wrong type");
|
||||
- resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror());
|
||||
-}
|
||||
-
|
||||
oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) {
|
||||
const Method* method = m();
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index 9abf2e1d105..8f5993b7225 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -1107,7 +1107,6 @@ class java_lang_invoke_ResolvedMethodName : AllStatic {
|
||||
|
||||
static Method* vmtarget(oop resolved_method);
|
||||
static void set_vmtarget(oop resolved_method, Method* method);
|
||||
- static void set_vmholder_offset(oop resolved_method, Method* method);
|
||||
|
||||
static void set_vmholder(oop resolved_method, oop holder);
|
||||
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index eb9fcda44f3..d0f1667b967 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -375,6 +375,67 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
+class AdjustMethodEntriesDcevm : public StackObj {
|
||||
+ bool* _trace_name_printed;
|
||||
+ GrowableArray<oop>* _oops_to_add;
|
||||
+public:
|
||||
+ AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {};
|
||||
+ bool operator()(WeakHandle<vm_resolved_method_table_data>* entry) {
|
||||
+ oop mem_name = entry->peek();
|
||||
+ if (mem_name == NULL) {
|
||||
+ // Removed
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
+
|
||||
+ 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()) {
|
||||
+ newer_method = Universe::throw_no_such_method_error();
|
||||
+ } else {
|
||||
+ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
+
|
||||
+ log_debug(redefine, class, update)("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");
|
||||
+
|
||||
+ Thread* thread = Thread::current();
|
||||
+ ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method);
|
||||
+ ResolvedMethodGet rmg(thread, newer_method);
|
||||
+
|
||||
+ if (_local_table->get(thread, lookup, rmg)) {
|
||||
+ // old method was already adjusted if new method exists in _the_table
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
|
||||
+ java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror());
|
||||
+
|
||||
+ newer_klass->set_has_resolved_methods();
|
||||
+ _oops_to_add->append(mem_name);
|
||||
+
|
||||
+ ResourceMark rm;
|
||||
+ if (!(*_trace_name_printed)) {
|
||||
+ log_debug(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)",
|
||||
+ newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
// 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");
|
||||
@@ -382,73 +443,41 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
AdjustMethodEntries adjust(trace_name_printed);
|
||||
_local_table->do_safepoint_scan(adjust);
|
||||
}
|
||||
-#endif // INCLUDE_JVMTI
|
||||
|
||||
-// (DCEVM) It is called at safepoint only for RedefineClasses
|
||||
+// 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>();
|
||||
-
|
||||
- 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()) {
|
||||
-
|
||||
- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
- Method* newer_method;
|
||||
-
|
||||
- // Method* new_method;
|
||||
- if (old_method->is_deleted()) {
|
||||
- newer_method = Universe::throw_no_such_method_error();
|
||||
- } else {
|
||||
- newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
-
|
||||
- log_debug(redefine, class, update)("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");
|
||||
-
|
||||
- if (_the_table->lookup(newer_method) != NULL) {
|
||||
- // old method was already adjusted if new method exists in _the_table
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
+ GrowableArray<oop> oops_to_add(0);
|
||||
+ AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed);
|
||||
+ _local_table->do_safepoint_scan(adjust);
|
||||
+ Thread* thread = Thread::current();
|
||||
+ for (int i = 0; i < oops_to_add.length(); i++) {
|
||||
+ oop mem_name = oops_to_add.at(i);
|
||||
+ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
|
||||
- java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
|
||||
- java_lang_invoke_ResolvedMethodName::set_vmholder_offset(mem_name, newer_method);
|
||||
+ // The hash table takes ownership of the WeakHandle, even if it's not inserted.
|
||||
|
||||
- newer_klass->set_has_resolved_methods();
|
||||
- oops_to_add->append(mem_name);
|
||||
+ ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
|
||||
+ ResolvedMethodGet rmg(thread, method);
|
||||
|
||||
- ResourceMark rm;
|
||||
- if (!(*trace_name_printed)) {
|
||||
- log_debug(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)",
|
||||
- newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
|
||||
+ while (true) {
|
||||
+ if (_local_table->get(thread, lookup, rmg)) {
|
||||
+ break;
|
||||
+ }
|
||||
+ WeakHandle<vm_resolved_method_table_data> wh = WeakHandle<vm_resolved_method_table_data>::create(Handle(thread, mem_name));
|
||||
+ // The hash table takes ownership of the WeakHandle, even if it's not inserted.
|
||||
+ if (_local_table->insert(thread, lookup, wh)) {
|
||||
+ log_insert(method);
|
||||
+ wh.resolve();
|
||||
+ break;
|
||||
}
|
||||
- }
|
||||
- for (int i = 0; i < oops_to_add->length(); i++) {
|
||||
- oop mem_name = oops_to_add->at(i);
|
||||
- Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
- _the_table->basic_add(method, Handle(Thread::current(), mem_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+#endif // INCLUDE_JVMTI
|
||||
+
|
||||
// Verification
|
||||
class VerifyResolvedMethod : StackObj {
|
||||
public:
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
From 5379e56465d3d3930ec7ea91b1c64db2cdf70170 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 22 Nov 2020 12:05:50 +0100
|
||||
Subject: [PATCH 23/34] dcevm15 - fix Universe::root_oops_do
|
||||
|
||||
---
|
||||
src/hotspot/share/memory/universe.cpp | 38 +++++++++------------------
|
||||
1 file changed, 12 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
|
||||
index f6e4253b5a5..8dad437bd51 100644
|
||||
--- a/src/hotspot/share/memory/universe.cpp
|
||||
+++ b/src/hotspot/share/memory/universe.cpp
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "gc/shared/gcConfig.hpp"
|
||||
#include "gc/shared/gcLogPrecious.hpp"
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
+#include "gc/shared/weakProcessor.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@@ -75,6 +76,7 @@
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/timerTrace.hpp"
|
||||
#include "runtime/vmOperations.hpp"
|
||||
+#include "services/management.hpp"
|
||||
#include "services/memoryService.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/copy.hpp"
|
||||
@@ -180,45 +182,29 @@ void Universe::basic_type_classes_do(KlassClosure *closure) {
|
||||
|
||||
// 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 {
|
||||
- public:
|
||||
- void do_object(oop p) { ShouldNotReachHere(); }
|
||||
- bool do_object_b(oop p) { return true; }
|
||||
- };
|
||||
- AlwaysTrueClosure always_true;
|
||||
-
|
||||
Universe::oops_do(oopClosure);
|
||||
// ReferenceProcessor::oops_do(oopClosure); (tw) check why no longer there
|
||||
JNIHandles::oops_do(oopClosure); // Global (strong) JNI handles
|
||||
Threads::oops_do(oopClosure, NULL);
|
||||
ObjectSynchronizer::oops_do(oopClosure);
|
||||
- // TODO: review, flat profiler was removed in j10
|
||||
- // FlatProfiler::oops_do(oopClosure);
|
||||
- JvmtiExport::oops_do(oopClosure);
|
||||
+ // (DCEVM) TODO: Check if this is correct?
|
||||
+ Management::oops_do(oopClosure);
|
||||
+ OopStorageSet::vm_global()->oops_do(oopClosure);
|
||||
+ CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none);
|
||||
+ ClassLoaderDataGraph::cld_do(&cld_closure);
|
||||
|
||||
// Now adjust pointers in remaining weak roots. (All of which should
|
||||
// have been cleared if they pointed to non-surviving objects.)
|
||||
// Global (weak) JNI handles
|
||||
- JNIHandles::weak_oops_do(&always_true, oopClosure);
|
||||
+ WeakProcessor::oops_do(oopClosure);
|
||||
|
||||
CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations);
|
||||
CodeCache::blobs_do(&blobClosure);
|
||||
- StringTable::oops_do(oopClosure);
|
||||
+ AOT_ONLY(AOTLoader::oops_do(oopClosure);)
|
||||
+ // StringTable::oops_do was removed in j15
|
||||
+ // StringTable::oops_do(oopClosure);
|
||||
|
||||
- // (DCEVM) TODO: Check if this is correct?
|
||||
- //CodeCache::scavenge_root_nmethods_oops_do(oopClosure);
|
||||
- //Management::oops_do(oopClosure);
|
||||
- //ref_processor()->weak_oops_do(&oopClosure);
|
||||
- //PSScavenge::reference_processor()->weak_oops_do(&oopClosure);
|
||||
-
|
||||
-#if INCLUDE_AOT
|
||||
- if (UseAOT) {
|
||||
- AOTLoader::oops_do(oopClosure);
|
||||
- }
|
||||
-#endif
|
||||
- // SO_AllClasses
|
||||
- SystemDictionary::oops_do(oopClosure);
|
||||
+ // PSScavenge::reference_processor()->weak_oops_do(oopClosure);
|
||||
}
|
||||
|
||||
void Universe::oops_do(OopClosure* f) {
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
From c6ea68e66d37d70739f7b0ee74131322b4526a68 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 22 Nov 2020 12:03:32 +0100
|
||||
Subject: [PATCH 24/34] Cleanup dcevm comments
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/classLoaderDataGraph.hpp | 2 +-
|
||||
src/hotspot/share/classfile/systemDictionary.hpp | 2 +-
|
||||
src/hotspot/share/gc/shared/gcConfig.cpp | 2 +-
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp
|
||||
index f380aa3fa34..8ce94cccb47 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp
|
||||
@@ -104,7 +104,7 @@ class ClassLoaderDataGraph : public AllStatic {
|
||||
|
||||
static void dictionary_classes_do(KlassClosure* klass_closure);
|
||||
|
||||
- // Enhanced class redefinition
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
static void rollback_redefinition();
|
||||
|
||||
// VM_CounterDecay iteration support
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
index 931e655d631..1019dbd0d04 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
@@ -455,7 +455,7 @@ public:
|
||||
static bool is_well_known_klass(Symbol* class_name);
|
||||
#endif
|
||||
|
||||
- // Enhanced class redefinition
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
static void remove_from_hierarchy(InstanceKlass* k);
|
||||
static void update_constraints_after_redefinition();
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
index 5c1a09390f1..23fbf715378 100644
|
||||
--- a/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
@@ -99,7 +99,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() {
|
||||
|
||||
void GCConfig::select_gc_ergonomically() {
|
||||
if (AllowEnhancedClassRedefinition && !UseG1GC) {
|
||||
- // Enhanced class redefinition only supports serial GC at the moment
|
||||
+ // (DCEVM) Enhanced class redefinition only supports serial GC at the moment
|
||||
FLAG_SET_ERGO(UseSerialGC, true);
|
||||
} else if (os::is_server_class_machine()) {
|
||||
#if INCLUDE_G1GC
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index bd5e7d153be..5de375fb888 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -78,7 +78,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// have any entries.
|
||||
bool _any_class_has_resolved_methods;
|
||||
|
||||
- // Enhanced class redefinition, affected klasses contain all classes which should be redefined
|
||||
+ // (DCEVM) Enhanced class redefinition, affected klasses contain all classes which should be redefined
|
||||
// either because of redefine, class hierarchy or interface change
|
||||
GrowableArray<Klass*>* _affected_klasses;
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From 507d97966c7145d0ae2533459cc504c7b0d6d5b6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 22 Nov 2020 18:49:05 +0100
|
||||
Subject: [PATCH 25/34] Fix cpCache in not AllowEnhancedClassRedefinition mode
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/cpCache.hpp | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp
|
||||
index 121a13b1dda..64dcf6223f5 100644
|
||||
--- a/src/hotspot/share/oops/cpCache.hpp
|
||||
+++ b/src/hotspot/share/oops/cpCache.hpp
|
||||
@@ -148,13 +148,13 @@ class ConstantPoolCacheEntry {
|
||||
void set_bytecode_2(Bytecodes::Code code);
|
||||
void set_f1(Metadata* f1) {
|
||||
Metadata* existing_f1 = _f1; // read once
|
||||
- //assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change");
|
||||
+ assert(AllowEnhancedClassRedefinition || existing_f1 == NULL || existing_f1 == f1, "illegal field change");
|
||||
_f1 = f1;
|
||||
}
|
||||
void release_set_f1(Metadata* f1);
|
||||
void set_f2(intx f2) {
|
||||
intx existing_f2 = _f2; // read once
|
||||
- //assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change");
|
||||
+ assert(AllowEnhancedClassRedefinition || existing_f2 == 0 || existing_f2 == f2, "illegal field change");
|
||||
_f2 = f2;
|
||||
}
|
||||
void set_f2_as_vfinal_method(Method* f2) {
|
||||
@@ -215,7 +215,9 @@ class ConstantPoolCacheEntry {
|
||||
void initialize_resolved_reference_index(int ref_index) {
|
||||
assert(_f2 == 0, "set once"); // note: ref_index might be zero also
|
||||
_f2 = ref_index;
|
||||
- _flags = 1 << is_resolved_ref_shift;
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ _flags = 1 << is_resolved_ref_shift;
|
||||
+ }
|
||||
}
|
||||
|
||||
void set_field( // sets entry to resolved field state
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From b516b615c20fafa2094dfb9f4cb08245b26418d0 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 22 Nov 2020 19:51:46 +0100
|
||||
Subject: [PATCH 26/34] dcevm15 - add ClassLoaderDataGraph_lock on
|
||||
ClassLoaderDataGraph::classes_do
|
||||
|
||||
ClassLoaderDataGraph::classes_do need safepoint or lock,
|
||||
find_sorted_affected_classes is not in safepoint therefore it must be
|
||||
locked
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index efaf11e1666..197e1c0029f 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -2063,7 +2063,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
AffectedKlassClosure closure(_affected_klasses);
|
||||
// Updated in j10, from original SystemDictionary::classes_do
|
||||
|
||||
- ClassLoaderDataGraph::classes_do(&closure);
|
||||
+ {
|
||||
+ MutexLocker mcld(ClassLoaderDataGraph_lock);
|
||||
+ ClassLoaderDataGraph::classes_do(&closure);
|
||||
+ }
|
||||
//ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From c6498946006879314bdc6218ee72da5d9c88f237 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sat, 28 Nov 2020 19:29:42 +0100
|
||||
Subject: [PATCH 27/34] dcevm15 - check if has_nestmate_access_to has newest
|
||||
host class
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 5e40d78a87e..1d9623f2446 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -445,6 +445,11 @@ bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ // TODO: (DCEVM) check if it correct. It fix problems with lambdas (hidden)
|
||||
+ cur_host = InstanceKlass::cast(cur_host->newest_version());
|
||||
+ }
|
||||
+
|
||||
Klass* k_nest_host = k->nest_host(CHECK_false);
|
||||
if (k_nest_host == NULL) {
|
||||
return false;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 86c27155386c1c40642c99c63a242d1f5d8601a5 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sat, 28 Nov 2020 19:31:08 +0100
|
||||
Subject: [PATCH 28/34] Remove unused fieldType
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/vmSymbols.hpp | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
index 6a3b234b222..eb06684a288 100644
|
||||
--- a/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
+++ b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
@@ -465,7 +465,6 @@
|
||||
template(static_offset_name, "staticOffset") \
|
||||
template(static_base_name, "staticBase") \
|
||||
template(field_offset_name, "fieldOffset") \
|
||||
- template(field_type_name, "fieldType") \
|
||||
\
|
||||
/* name symbols needed by intrinsics */ \
|
||||
\
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 025d0d2903963fb79f83cf0d90418783d3ef6813 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 17:18:16 +0100
|
||||
Subject: [PATCH 29/34] mark_as_scavengable only alive methods
|
||||
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 197e1c0029f..e00fac1f693 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -223,19 +223,21 @@ class FieldCopier : public FieldClosure {
|
||||
|
||||
// TODO: review...
|
||||
void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
- ScavengableNMethods::register_nmethod(nm);
|
||||
+ if (nm->is_alive()) {
|
||||
+ ScavengableNMethods::register_nmethod(nm);
|
||||
+ }
|
||||
}
|
||||
|
||||
void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) {
|
||||
// It should work not only for G1 but also for another GCs, but this way is safer now
|
||||
- if (!nm->is_zombie() && !nm->is_unloaded()) {
|
||||
+ if (nm->is_alive()) {
|
||||
Universe::heap()->unregister_nmethod(nm);
|
||||
}
|
||||
}
|
||||
|
||||
void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) {
|
||||
// It should work not only for G1 but also for another GCs, but this way is safer now
|
||||
- if (!nm->is_zombie() && !nm->is_unloaded()) {
|
||||
+ if (nm->is_alive()) {
|
||||
Universe::heap()->register_nmethod(nm);
|
||||
}
|
||||
}
|
||||
@@ -511,9 +513,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(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);
|
||||
+ // 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) {
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
From 27aabfefe7d799545049bb81ba19d4ed2ff6379c Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 17:20:11 +0100
|
||||
Subject: [PATCH 30/34] dcevm15 - lock on
|
||||
ClassLoaderDataGraph::rollback_redefinition
|
||||
|
||||
rollback is not in safepoint, therefore must be locked
|
||||
---
|
||||
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 e00fac1f693..db5fb1c472b 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1382,7 +1382,9 @@ 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.
|
||||
void VM_EnhancedRedefineClasses::rollback() {
|
||||
log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res);
|
||||
+ ClassLoaderDataGraph_lock->lock();
|
||||
ClassLoaderDataGraph::rollback_redefinition();
|
||||
+ ClassLoaderDataGraph_lock->unlock();
|
||||
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
SystemDictionary::remove_from_hierarchy(_new_classes->at(i));
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
From 9b405cb642d5935c39c8dbd522ea2fdecfc29ef3 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 19:59:50 +0100
|
||||
Subject: [PATCH 31/34] ResourceMark in G1IterateObjectClosureTask fixing
|
||||
memory leaks
|
||||
|
||||
G1IterateObjectClosureTask is used only in redefinition full GC run
|
||||
---
|
||||
src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
|
||||
index a29d2dddc2d..2af6df6c1e4 100644
|
||||
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
|
||||
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
|
||||
@@ -2362,6 +2362,9 @@ class G1IterateObjectClosureTask : public AbstractGangTask {
|
||||
_cl(cl), _g1h(g1h), _hrclaimer(g1h->workers()->active_workers()) { }
|
||||
|
||||
virtual void work(uint worker_id) {
|
||||
+ Thread *thread = Thread::current();
|
||||
+ HandleMark hm(thread); // make sure any handles created are deleted
|
||||
+ ResourceMark rm(thread);
|
||||
IterateObjectClosureRegionClosure blk(_cl);
|
||||
_g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id);
|
||||
}
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
From 40fe40884d4efc50864bb3f2dd88f0a2e7122d5a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 20:05:03 +0100
|
||||
Subject: [PATCH 32/34] dcevm15 - fix hidded classes
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 41 ++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index db5fb1c472b..590f7fdfafe 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -722,7 +722,8 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
}
|
||||
|
||||
// Cannot redefine or retransform an anonymous class.
|
||||
- if (InstanceKlass::cast(k)->is_unsafe_anonymous()) {
|
||||
+ // TODO: check if is correct in j15
|
||||
+ if (InstanceKlass::cast(k)->is_unsafe_anonymous() || InstanceKlass::cast(k)->is_hidden()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -808,21 +809,27 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
|
||||
InstanceKlass* k;
|
||||
|
||||
- if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) {
|
||||
- const InstanceKlass* host_class = the_class->unsafe_anonymous_host();
|
||||
+ if (the_class->is_unsafe_anonymous() || the_class->is_hidden()) {
|
||||
+ InstanceKlass* dynamic_host_class = NULL;
|
||||
+ InstanceKlass* unsafe_anonymous_host = NULL;
|
||||
|
||||
- // Make sure it's the real host class, not another anonymous class.
|
||||
- while (host_class != NULL && host_class->is_unsafe_anonymous()) {
|
||||
- host_class = host_class->unsafe_anonymous_host();
|
||||
+ if (the_class->is_hidden()) {
|
||||
+ log_debug(redefine, class, load)("loading hidden class %s", the_class->name()->as_C_string());
|
||||
+ dynamic_host_class = the_class->nest_host(THREAD);
|
||||
+ }
|
||||
+
|
||||
+ if (the_class->is_unsafe_anonymous()) {
|
||||
+ log_debug(redefine, class, load)("loading usafe anonymous %s", the_class->name()->as_C_string());
|
||||
+ unsafe_anonymous_host = the_class->unsafe_anonymous_host();
|
||||
}
|
||||
|
||||
ClassLoadInfo cl_info(protection_domain,
|
||||
- host_class,
|
||||
- NULL, // dynamic_nest_host
|
||||
+ unsafe_anonymous_host,
|
||||
NULL, // cp_patches
|
||||
+ dynamic_host_class, // dynamic_nest_host
|
||||
Handle(), // classData
|
||||
- false, // is_hidden
|
||||
- false, // is_strong_hidden
|
||||
+ the_class->is_hidden(), // is_hidden
|
||||
+ !the_class->is_non_strong_hidden(), // is_strong_hidden
|
||||
true); // FIXME: check if correct. can_access_vm_annotations
|
||||
|
||||
k = SystemDictionary::parse_stream(the_class_sym,
|
||||
@@ -833,7 +840,17 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
THREAD);
|
||||
|
||||
k->class_loader_data()->exchange_holders(the_class->class_loader_data());
|
||||
- the_class->class_loader_data()->inc_keep_alive();
|
||||
+
|
||||
+ if (the_class->is_hidden()) {
|
||||
+ // from jvm_lookup_define_class() (jvm.cpp):
|
||||
+ // The hidden class loader data has been artificially been kept alive to
|
||||
+ // this point. The mirror and any instances of this class have to keep
|
||||
+ // it alive afterwards.
|
||||
+ the_class->class_loader_data()->dec_keep_alive();
|
||||
+ } else {
|
||||
+ the_class->class_loader_data()->inc_keep_alive();
|
||||
+ }
|
||||
+
|
||||
} else {
|
||||
k = SystemDictionary::resolve_from_stream(the_class_sym,
|
||||
the_class_loader,
|
||||
@@ -1475,6 +1492,8 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version()));
|
||||
}
|
||||
|
||||
+ // FIXME: check new nest_host for hidden
|
||||
+
|
||||
// Update implementor if there is only one, in this case implementor() can reference old class
|
||||
if (ik->is_interface()) {
|
||||
Klass* implKlass = ik->implementor();
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 29920b076b4ad96d85adbce0a1d947e5022ba3ad Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 20:08:57 +0100
|
||||
Subject: [PATCH 33/34] dcevm15 - DON'T clear F2 in CP cache after indy
|
||||
unevolving
|
||||
|
||||
It's not clear why it was cleared in dcevm7-11
|
||||
---
|
||||
src/hotspot/share/oops/cpCache.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
|
||||
index 79a38dbeff0..650e6fab42d 100644
|
||||
--- a/src/hotspot/share/oops/cpCache.cpp
|
||||
+++ b/src/hotspot/share/oops/cpCache.cpp
|
||||
@@ -650,7 +650,7 @@ void ConstantPoolCacheEntry::clear_entry() {
|
||||
|
||||
if (clearData) {
|
||||
if (!is_resolved_reference()) {
|
||||
- _f2 = 0;
|
||||
+ // _f2 = 0;
|
||||
}
|
||||
// FIXME: (DCEVM) we want to clear flags, but parameter size is actually used
|
||||
// after we return from the method, before entry is re-initialized. So let's
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From 1f13b20ab5553182680045b7d7324ff92da7e7f0 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
||||
Date: Sun, 29 Nov 2020 21:28:06 +0100
|
||||
Subject: [PATCH 34/34] dcevm15 - fix Universe::root_oops_do
|
||||
|
||||
Removed ClassLoaderDataGraph::cld_do was cause of crashes due multiple
|
||||
oop patching. ClassLoaderDataGraph::cld_do replaced in dcevm15
|
||||
previously used and removed SystemDictionary:oops_do
|
||||
---
|
||||
src/hotspot/share/memory/universe.cpp | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
|
||||
index 8dad437bd51..0199962a684 100644
|
||||
--- a/src/hotspot/share/memory/universe.cpp
|
||||
+++ b/src/hotspot/share/memory/universe.cpp
|
||||
@@ -190,21 +190,26 @@ void Universe::root_oops_do(OopClosure *oopClosure) {
|
||||
// (DCEVM) TODO: Check if this is correct?
|
||||
Management::oops_do(oopClosure);
|
||||
OopStorageSet::vm_global()->oops_do(oopClosure);
|
||||
- CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none);
|
||||
- ClassLoaderDataGraph::cld_do(&cld_closure);
|
||||
+ // CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none);
|
||||
+ // ClassLoaderDataGraph::cld_do(&cld_closure);
|
||||
|
||||
// Now adjust pointers in remaining weak roots. (All of which should
|
||||
// have been cleared if they pointed to non-surviving objects.)
|
||||
// Global (weak) JNI handles
|
||||
WeakProcessor::oops_do(oopClosure);
|
||||
|
||||
+ JvmtiExport::oops_do(oopClosure);
|
||||
+
|
||||
CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations);
|
||||
CodeCache::blobs_do(&blobClosure);
|
||||
+
|
||||
AOT_ONLY(AOTLoader::oops_do(oopClosure);)
|
||||
+
|
||||
// StringTable::oops_do was removed in j15
|
||||
// StringTable::oops_do(oopClosure);
|
||||
|
||||
- // PSScavenge::reference_processor()->weak_oops_do(oopClosure);
|
||||
+ // OopStorageSet::vm_global()->oops_do(oopClosure);
|
||||
+
|
||||
}
|
||||
|
||||
void Universe::oops_do(OopClosure* f) {
|
||||
--
|
||||
2.23.0
|
||||
|
||||
119
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
119
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# 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 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
|
||||
#
|
||||
# $ ./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)
|
||||
#
|
||||
# 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}
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
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 $__modules_path --no-man-pages --compress=2 \
|
||||
--add-modules $__modules --output $__bundle_name || do_exit $?
|
||||
|
||||
grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__bundle_name/release
|
||||
if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then
|
||||
sed 's/JBR/JBRSDK/g' $__bundle_name/release > release
|
||||
mv release $__bundle_name/release
|
||||
fi
|
||||
}
|
||||
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=windows-x86_64-server-release
|
||||
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=1
|
||||
;;
|
||||
"dcevm")
|
||||
HEAD_REVISION=$(git rev-parse HEAD)
|
||||
git am jb/project/tools/patches/dcevm/*.patch || do_exit $?
|
||||
do_reset_dcevm=1
|
||||
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
|
||||
|
||||
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
|
||||
make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $?
|
||||
else
|
||||
make LOG=info CONF=$RELEASE_NAME clean images || do_exit $?
|
||||
fi
|
||||
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$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
|
||||
|
||||
# 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 $?
|
||||
|
||||
# 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" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
do_exit 0
|
||||
63
jb/project/tools/windows/scripts/mkimages_x86.sh
Executable file
63
jb/project/tools/windows/scripts/mkimages_x86.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/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
|
||||
#
|
||||
# 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
|
||||
|
||||
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 \
|
||||
--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=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || 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-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}
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--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
|
||||
77
jb/project/tools/windows/scripts/pack_x64.sh
Executable file
77
jb/project/tools/windows/scripts/pack_x64.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# 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 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
|
||||
#
|
||||
# $ ./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)
|
||||
#
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
|
||||
function pack_jbr {
|
||||
|
||||
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 ...
|
||||
|
||||
/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/$RELEASE_NAME/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
[ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz"
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || do_exit $?
|
||||
fi
|
||||
|
||||
pack_jbr $bundle_type
|
||||
|
||||
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 || do_exit $?
|
||||
fi
|
||||
42
jb/project/tools/windows/scripts/pack_x86.sh
Executable file
42
jb/project/tools/windows/scripts/pack_x86.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/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
|
||||
#
|
||||
# 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
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
IMAGES_DIR=build/windows-x86-server-release/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
|
||||
JBR=$JBR_BASE_NAME-windows-x86-b$build_number
|
||||
echo Creating $JBR.tar.gz ...
|
||||
/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR ${JBR_BUNDLE} || exit 1
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x86-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
|
||||
68
jdk/test/jb/sun/lwawt/macosx/CThreading/IsAppKit.java
Normal file
68
jdk/test/jb/sun/lwawt/macosx/CThreading/IsAppKit.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary regression test on JRE-624 CThreading.isAppKit() fails to detect main app thread if it was renamed
|
||||
* @compile -XDignore.symbol.file IsAppKit.java
|
||||
* @requires os.family == "mac"
|
||||
* @run main/othervm IsAppKit
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.concurrent.*;
|
||||
import sun.lwawt.macosx.*;
|
||||
|
||||
/*
|
||||
* Description: The test checks detection of the main application thread
|
||||
*
|
||||
*/
|
||||
|
||||
public class IsAppKit {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
final CountDownLatch counter = new CountDownLatch(1);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
counter.countDown();
|
||||
});
|
||||
|
||||
counter.await();
|
||||
|
||||
CThreading.privilegedExecuteOnAppKit(() -> {
|
||||
String name = Thread.currentThread().getName();
|
||||
if (!"AWT-AppKit".equals(name)) {
|
||||
throw new RuntimeException("Unexpected thread name: " + name);
|
||||
}
|
||||
|
||||
Thread.currentThread().setName("Some other thread name");
|
||||
return null;
|
||||
});
|
||||
|
||||
|
||||
String name = CThreading.privilegedExecuteOnAppKit(() -> {
|
||||
return Thread.currentThread().getName();
|
||||
});
|
||||
|
||||
if (!"AWT-AppKit".equals(name)) {
|
||||
throw new RuntimeException("Unexpected thread name: " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -890,6 +890,15 @@ define SetupRunJtregTestBody
|
||||
$1_JTREG_BASIC_OPTIONS += -ea -esa
|
||||
endif
|
||||
|
||||
ifeq ($$(ASAN_ENABLED), yes)
|
||||
$1_JTREG_BASIC_OPTIONS += -e:ASAN_OPTIONS=handle_segv=0:handle_sigfpe=0:detect_leaks=false
|
||||
$1_JTREG_BASIC_OPTIONS += -e:LD_PRELOAD=libasan.so.5
|
||||
endif
|
||||
|
||||
ifeq ($$(USAN_ENABLED), yes)
|
||||
$1_JTREG_BASIC_OPTIONS += -e:LD_PRELOAD=libubsan.so.1
|
||||
endif
|
||||
|
||||
ifneq ($$($1_JTREG_NATIVEPATH), )
|
||||
$1_JTREG_BASIC_OPTIONS += -nativepath:$$($1_JTREG_NATIVEPATH)
|
||||
endif
|
||||
|
||||
@@ -217,6 +217,9 @@ JDKOPT_SETUP_CODE_COVERAGE
|
||||
# AddressSanitizer
|
||||
JDKOPT_SETUP_ADDRESS_SANITIZER
|
||||
|
||||
# UndefinedBehaviorSanitizer
|
||||
JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Check dependencies for external and internal libraries.
|
||||
|
||||
@@ -230,7 +230,7 @@ AC_DEFUN([FLAGS_SETUP_OPTIMIZATION],
|
||||
DISABLE_FORTIFY_CFLAGS="-U_FORTIFY_SOURCE"
|
||||
# ASan doesn't work well with _FORTIFY_SOURCE
|
||||
# See https://github.com/google/sanitizers/wiki/AddressSanitizer#faq
|
||||
if test "x$ASAN_ENABLED" = xyes; then
|
||||
if test "x$ASAN_ENABLED" = xyes || test "x$USAN_ENABLED" = xyes; then
|
||||
ENABLE_FORTIFY_CFLAGS="${DISABLE_FORTIFY_CFLAGS}"
|
||||
else
|
||||
ENABLE_FORTIFY_CFLAGS="-D_FORTIFY_SOURCE=2"
|
||||
|
||||
@@ -445,6 +445,45 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
|
||||
AC_SUBST(ASAN_ENABLED)
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# UndefinedBehaviorSanitizer
|
||||
#
|
||||
AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER],
|
||||
[
|
||||
UTIL_ARG_ENABLE(NAME: usan, DEFAULT: false,
|
||||
DESC: [enable UndefinedBehaviorSanitizer],
|
||||
CHECK_AVAILABLE: [
|
||||
AC_MSG_CHECKING([if UndefinedBehaviorSanitizer (usan) is available])
|
||||
if test "x$TOOLCHAIN_TYPE" = "xgcc" ||
|
||||
test "x$TOOLCHAIN_TYPE" = "xclang"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
],
|
||||
IF_ENABLED: [
|
||||
USAN_FLAGS="-fsanitize=undefined"
|
||||
USAN_CFLAGS="$USAN_FLAGS -fno-omit-frame-pointer"
|
||||
USAN_LDFLAGS="$USAN_FLAGS"
|
||||
JVM_CFLAGS="$JVM_CFLAGS $USAN_CFLAGS"
|
||||
JVM_LDFLAGS="$JVM_LDFLAGS $USAN_LDFLAGS"
|
||||
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $USAN_CFLAGS"
|
||||
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $USAN_CFLAGS"
|
||||
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $USAN_CFLAGS"
|
||||
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $USAN_CFLAGS"
|
||||
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $USAN_LDFLAGS"
|
||||
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $USAN_LDFLAGS"
|
||||
USAN_ENABLED="yes"
|
||||
],
|
||||
IF_DISABLED: [
|
||||
USAN_ENABLED="no"
|
||||
])
|
||||
|
||||
AC_SUBST(USAN_ENABLED)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Static build support. When enabled will generate static
|
||||
|
||||
@@ -421,7 +421,16 @@ JCOV_FILTERS=@JCOV_FILTERS@
|
||||
export ASAN_ENABLED:=@ASAN_ENABLED@
|
||||
export DEVKIT_LIB_DIR:=@DEVKIT_LIB_DIR@
|
||||
ifeq ($(ASAN_ENABLED), yes)
|
||||
export ASAN_OPTIONS=handle_segv=0 detect_leaks=0
|
||||
export ASAN_OPTIONS=handle_segv=0:handle_sigfpe=0:detect_leaks=false
|
||||
ifneq ($(DEVKIT_LIB_DIR),)
|
||||
export LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):$(DEVKIT_LIB_DIR)
|
||||
endif
|
||||
endif
|
||||
|
||||
# UndefinedBehaviorSanitizer
|
||||
export USAN_ENABLED:=@USAN_ENABLED@
|
||||
export DEVKIT_LIB_DIR:=@DEVKIT_LIB_DIR@
|
||||
ifeq ($(USAN_ENABLED), yes)
|
||||
ifneq ($(DEVKIT_LIB_DIR),)
|
||||
export LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):$(DEVKIT_LIB_DIR)
|
||||
endif
|
||||
|
||||
@@ -52,7 +52,7 @@ allfonts.myanmar=Myanmar Text
|
||||
allfonts.dingbats=Wingdings
|
||||
allfonts.symbol=Symbol
|
||||
allfonts.symbols=Segoe UI Symbol
|
||||
allfonts.thai=DokChampa
|
||||
allfonts.thai=Tahoma
|
||||
allfonts.georgian=Sylfaen
|
||||
|
||||
serif.plain.alphabetic=Times New Roman
|
||||
@@ -60,140 +60,140 @@ serif.plain.chinese-ms950=MingLiU
|
||||
serif.plain.chinese-ms950-extb=MingLiU-ExtB
|
||||
serif.plain.hebrew=David
|
||||
serif.plain.japanese=MS Mincho
|
||||
serif.plain.korean=Batang
|
||||
serif.plain.korean=Malgun Gothic
|
||||
|
||||
serif.bold.alphabetic=Times New Roman Bold
|
||||
serif.bold.chinese-ms950=PMingLiU
|
||||
serif.bold.chinese-ms950-extb=PMingLiU-ExtB
|
||||
serif.bold.hebrew=David Bold
|
||||
serif.bold.japanese=MS Mincho
|
||||
serif.bold.korean=Batang
|
||||
serif.bold.korean=Malgun Gothic
|
||||
|
||||
serif.italic.alphabetic=Times New Roman Italic
|
||||
serif.italic.chinese-ms950=PMingLiU
|
||||
serif.italic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
serif.italic.hebrew=David
|
||||
serif.italic.japanese=MS Mincho
|
||||
serif.italic.korean=Batang
|
||||
serif.italic.korean=Malgun Gothic
|
||||
|
||||
serif.bolditalic.alphabetic=Times New Roman Bold Italic
|
||||
serif.bolditalic.chinese-ms950=PMingLiU
|
||||
serif.bolditalic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
serif.bolditalic.hebrew=David Bold
|
||||
serif.bolditalic.japanese=MS Mincho
|
||||
serif.bolditalic.korean=Batang
|
||||
serif.bolditalic.korean=Malgun Gothic
|
||||
|
||||
sansserif.plain.alphabetic=Arial
|
||||
sansserif.plain.chinese-ms950=MingLiU
|
||||
sansserif.plain.chinese-ms950-extb=MingLiU-ExtB
|
||||
sansserif.plain.hebrew=David
|
||||
sansserif.plain.japanese=MS Gothic
|
||||
sansserif.plain.korean=Gulim
|
||||
sansserif.plain.korean=Malgun Gothic
|
||||
|
||||
sansserif.bold.alphabetic=Arial Bold
|
||||
sansserif.bold.chinese-ms950=PMingLiU
|
||||
sansserif.bold.chinese-ms950-extb=PMingLiU-ExtB
|
||||
sansserif.bold.hebrew=David Bold
|
||||
sansserif.bold.japanese=MS Gothic
|
||||
sansserif.bold.korean=Gulim
|
||||
sansserif.bold.korean=Malgun Gothic
|
||||
|
||||
sansserif.italic.alphabetic=Arial Italic
|
||||
sansserif.italic.chinese-ms950=PMingLiU
|
||||
sansserif.italic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
sansserif.italic.hebrew=David
|
||||
sansserif.italic.japanese=MS Gothic
|
||||
sansserif.italic.korean=Gulim
|
||||
sansserif.italic.korean=Malgun Gothic
|
||||
|
||||
sansserif.bolditalic.alphabetic=Arial Bold Italic
|
||||
sansserif.bolditalic.chinese-ms950=PMingLiU
|
||||
sansserif.bolditalic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
sansserif.bolditalic.hebrew=David Bold
|
||||
sansserif.bolditalic.japanese=MS Gothic
|
||||
sansserif.bolditalic.korean=Gulim
|
||||
sansserif.bolditalic.korean=Malgun Gothic
|
||||
|
||||
monospaced.plain.alphabetic=Courier New
|
||||
monospaced.plain.chinese-ms950=MingLiU
|
||||
monospaced.plain.chinese-ms950-extb=MingLiU-ExtB
|
||||
monospaced.plain.hebrew=Courier New
|
||||
monospaced.plain.japanese=MS Gothic
|
||||
monospaced.plain.korean=GulimChe
|
||||
monospaced.plain.korean=Malgun Gothic
|
||||
|
||||
monospaced.bold.alphabetic=Courier New Bold
|
||||
monospaced.bold.chinese-ms950=PMingLiU
|
||||
monospaced.bold.chinese-ms950-extb=PMingLiU-ExtB
|
||||
monospaced.bold.hebrew=Courier New Bold
|
||||
monospaced.bold.japanese=MS Gothic
|
||||
monospaced.bold.korean=GulimChe
|
||||
monospaced.bold.korean=Malgun Gothic
|
||||
|
||||
monospaced.italic.alphabetic=Courier New Italic
|
||||
monospaced.italic.chinese-ms950=PMingLiU
|
||||
monospaced.italic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
monospaced.italic.hebrew=Courier New
|
||||
monospaced.italic.japanese=MS Gothic
|
||||
monospaced.italic.korean=GulimChe
|
||||
monospaced.italic.korean=Malgun Gothic
|
||||
|
||||
monospaced.bolditalic.alphabetic=Courier New Bold Italic
|
||||
monospaced.bolditalic.chinese-ms950=PMingLiU
|
||||
monospaced.bolditalic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
monospaced.bolditalic.hebrew=Courier New Bold
|
||||
monospaced.bolditalic.japanese=MS Gothic
|
||||
monospaced.bolditalic.korean=GulimChe
|
||||
monospaced.bolditalic.korean=Malgun Gothic
|
||||
|
||||
dialog.plain.alphabetic=Arial
|
||||
dialog.plain.chinese-ms950=MingLiU
|
||||
dialog.plain.chinese-ms950-extb=MingLiU-ExtB
|
||||
dialog.plain.hebrew=David
|
||||
dialog.plain.japanese=MS Gothic
|
||||
dialog.plain.korean=Gulim
|
||||
dialog.plain.korean=Malgun Gothic
|
||||
|
||||
dialog.bold.alphabetic=Arial Bold
|
||||
dialog.bold.chinese-ms950=PMingLiU
|
||||
dialog.bold.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialog.bold.hebrew=David Bold
|
||||
dialog.bold.japanese=MS Gothic
|
||||
dialog.bold.korean=Gulim
|
||||
dialog.bold.korean=Malgun Gothic
|
||||
|
||||
dialog.italic.alphabetic=Arial Italic
|
||||
dialog.italic.chinese-ms950=PMingLiU
|
||||
dialog.italic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialog.italic.hebrew=David
|
||||
dialog.italic.japanese=MS Gothic
|
||||
dialog.italic.korean=Gulim
|
||||
dialog.italic.korean=Malgun Gothic
|
||||
|
||||
dialog.bolditalic.alphabetic=Arial Bold Italic
|
||||
dialog.bolditalic.chinese-ms950=PMingLiU
|
||||
dialog.bolditalic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialog.bolditalic.hebrew=David Bold
|
||||
dialog.bolditalic.japanese=MS Gothic
|
||||
dialog.bolditalic.korean=Gulim
|
||||
dialog.bolditalic.korean=Malgun Gothic
|
||||
|
||||
dialoginput.plain.alphabetic=Courier New
|
||||
dialoginput.plain.chinese-ms950=MingLiU
|
||||
dialoginput.plain.chinese-ms950-extb=MingLiU-ExtB
|
||||
dialoginput.plain.hebrew=David
|
||||
dialoginput.plain.japanese=MS Gothic
|
||||
dialoginput.plain.korean=Gulim
|
||||
dialoginput.plain.korean=Malgun Gothic
|
||||
|
||||
dialoginput.bold.alphabetic=Courier New Bold
|
||||
dialoginput.bold.chinese-ms950=PMingLiU
|
||||
dialoginput.bold.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialoginput.bold.hebrew=David Bold
|
||||
dialoginput.bold.japanese=MS Gothic
|
||||
dialoginput.bold.korean=Gulim
|
||||
dialoginput.bold.korean=Malgun Gothic
|
||||
|
||||
dialoginput.italic.alphabetic=Courier New Italic
|
||||
dialoginput.italic.chinese-ms950=PMingLiU
|
||||
dialoginput.italic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialoginput.italic.hebrew=David
|
||||
dialoginput.italic.japanese=MS Gothic
|
||||
dialoginput.italic.korean=Gulim
|
||||
dialoginput.italic.korean=Malgun Gothic
|
||||
|
||||
dialoginput.bolditalic.alphabetic=Courier New Bold Italic
|
||||
dialoginput.bolditalic.chinese-ms950=PMingLiU
|
||||
dialoginput.bolditalic.chinese-ms950-extb=PMingLiU-ExtB
|
||||
dialoginput.bolditalic.hebrew=David Bold
|
||||
dialoginput.bolditalic.japanese=MS Gothic
|
||||
dialoginput.bolditalic.korean=Gulim
|
||||
dialoginput.bolditalic.korean=Malgun Gothic
|
||||
|
||||
# Search Sequences
|
||||
|
||||
@@ -257,7 +257,7 @@ sequence.fallback=symbols,\
|
||||
|
||||
# Exclusion Ranges
|
||||
|
||||
exclusion.alphabetic=0700-1cff,1d80-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-f8ff
|
||||
exclusion.alphabetic=0700-1cff,1d80-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-24ff,2501-2501,2503-250b,250d-250f,2511-2513,2515-2517,2519-251b,251d-2523,2525-252b,252d-2533,2535-253b,253d-254f,256d-f8ff
|
||||
exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be
|
||||
exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
|
||||
|
||||
@@ -303,21 +303,18 @@ filename.MS_PMincho=MSMINCHO.TTC
|
||||
filename.MS_Gothic=MSGOTHIC.TTC
|
||||
filename.MS_PGothic=MSGOTHIC.TTC
|
||||
|
||||
filename.Gulim=gulim.TTC
|
||||
filename.Batang=batang.TTC
|
||||
filename.GulimChe=gulim.TTC
|
||||
|
||||
filename.Gautami=gautami.ttf
|
||||
filename.Iskoola_Pota=iskpota.ttf
|
||||
filename.Kalinga=kalinga.ttf
|
||||
filename.Kartika=kartika.ttf
|
||||
filename.Latha=latha.ttf
|
||||
filename.Malgun_Gothic=malgun.ttf
|
||||
filename.Mangal=MANGAL.TTF
|
||||
filename.Raavi=raavi.ttf
|
||||
filename.Shruti=shruti.ttf
|
||||
filename.Tahoma=tahoma.ttf
|
||||
filename.Tunga=TUNGA.TTF
|
||||
filename.Vrinda=vrinda.ttf
|
||||
filename.DokChampa=dokchamp.ttf
|
||||
filename.Khmer_UI=KhmerUI.ttf
|
||||
filename.Mongolian_Baiti=monbaiti.ttf
|
||||
filename.Myanmar_Text=mmrtext.ttf
|
||||
|
||||
@@ -82,3 +82,13 @@ $(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \
|
||||
TARGETS += $(COPY_LEGAL)
|
||||
|
||||
################################################################################
|
||||
|
||||
FONTFILE_SRC_DIR := $(TOPDIR)/src/java.desktop/share
|
||||
FONTFILE_SRCS := $(wildcard $(FONTFILE_SRC_DIR)/fonts/*.ttf) $(FONTFILE_SRC_DIR)/fonts/fonts.dir $(FONTFILE_SRC_DIR)/fonts/font.conf
|
||||
FONTFILE_TARGET_FILES := $(subst $(FONTFILE_SRC_DIR),$(LIB_DST_DIR),$(FONTFILE_SRCS))
|
||||
|
||||
$(LIB_DST_DIR)/fonts/%: $(FONTFILE_SRC_DIR)/fonts/%
|
||||
$(call install-file)
|
||||
|
||||
|
||||
TARGETS += $(FONTFILE_TARGET_FILES)
|
||||
|
||||
@@ -73,6 +73,7 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
$(TOPDIR)/src/$(MODULE)/share/native/common/font \
|
||||
$(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \
|
||||
$(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \
|
||||
$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/launcher \
|
||||
#
|
||||
endif
|
||||
|
||||
@@ -167,7 +168,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
LIBS_windows := kernel32.lib user32.lib gdi32.lib winspool.lib \
|
||||
imm32.lib ole32.lib uuid.lib shell32.lib \
|
||||
comdlg32.lib winmm.lib comctl32.lib shlwapi.lib \
|
||||
delayimp.lib jvm.lib $(WIN_JAVA_LIB) advapi32.lib, \
|
||||
delayimp.lib jvm.lib $(WIN_JAVA_LIB) advapi32.lib dwmapi.lib, \
|
||||
VERSIONINFO_RESOURCE := $(LIBAWT_VERSIONINFO_RESOURCE), \
|
||||
EXTRA_RCFLAGS := $(LIBAWT_RCFLAGS), \
|
||||
))
|
||||
@@ -499,10 +500,12 @@ else ifeq ($(call isTargetOs, macosx), true)
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \
|
||||
X11TextRenderer.c \
|
||||
fontpath.c \
|
||||
lcdglyph.c
|
||||
lcdglyph.c \
|
||||
lcdglyphDW.cpp
|
||||
else
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += fontpath.c \
|
||||
lcdglyph.c
|
||||
lcdglyph.c \
|
||||
lcdglyphDW.cpp
|
||||
endif
|
||||
|
||||
LIBFONTMANAGER_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS
|
||||
|
||||
54
modules.list
Normal file
54
modules.list
Normal file
@@ -0,0 +1,54 @@
|
||||
java.base,
|
||||
java.compiler,
|
||||
java.datatransfer,
|
||||
java.desktop,
|
||||
java.instrument,
|
||||
java.logging,
|
||||
java.management,
|
||||
java.management.rmi,
|
||||
java.naming,
|
||||
java.net.http,
|
||||
java.prefs,
|
||||
java.rmi,
|
||||
java.scripting,
|
||||
java.se,
|
||||
java.security.jgss,
|
||||
java.security.sasl,
|
||||
java.smartcardio,
|
||||
java.sql,
|
||||
java.sql.rowset,
|
||||
java.transaction.xa,
|
||||
java.xml,
|
||||
java.xml.crypto,
|
||||
jdk.accessibility,
|
||||
jdk.aot,
|
||||
jdk.attach,
|
||||
jdk.charsets,
|
||||
jdk.compiler,
|
||||
jdk.crypto.cryptoki,
|
||||
jdk.crypto.ec,
|
||||
jdk.dynalink,
|
||||
jdk.httpserver,
|
||||
jdk.internal.ed,
|
||||
jdk.internal.le,
|
||||
jdk.internal.vm.ci,
|
||||
jdk.internal.vm.compiler,
|
||||
jdk.internal.vm.compiler.management,
|
||||
jdk.jdi,
|
||||
jdk.jdwp.agent,
|
||||
jdk.jfr,
|
||||
jdk.jsobject,
|
||||
jdk.localedata,
|
||||
jdk.management,
|
||||
jdk.management.agent,
|
||||
jdk.management.jfr,
|
||||
jdk.naming.dns,
|
||||
jdk.naming.rmi,
|
||||
jdk.net,
|
||||
jdk.sctp,
|
||||
jdk.security.auth,
|
||||
jdk.security.jgss,
|
||||
jdk.unsupported,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
jdk.hotspot.agent
|
||||
@@ -532,12 +532,12 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
#if defined(LINUX)
|
||||
assert(strlen(tmpdirname) == 4, "No longer using /tmp - update buffer size");
|
||||
|
||||
char buffer[MAXPATHLEN + 1];
|
||||
// On Linux, if nspid != -1, look in /proc/{vmid}/root/tmp for directories
|
||||
// containing nspid, otherwise just look for vmid in /tmp.
|
||||
if (nspid == -1) {
|
||||
searchpid = vmid;
|
||||
} else {
|
||||
char buffer[MAXPATHLEN + 1];
|
||||
jio_snprintf(buffer, MAXPATHLEN, "/proc/%d/root%s", vmid, tmpdirname);
|
||||
tmpdirname = buffer;
|
||||
searchpid = nspid;
|
||||
|
||||
@@ -139,8 +139,7 @@ void G1ConcurrentMarkThread::run_service() {
|
||||
assert(in_progress(), "must be");
|
||||
|
||||
GCIdMark gc_id_mark;
|
||||
GCTraceConcTime(Info, gc) tt(FormatBuffer<128>("Concurrent %s Cycle",
|
||||
_state == FullMark ? "Mark" : "Undo"));
|
||||
GCTraceConcTime(Info, gc) tt(_state == FullMark ? "Concurrent Mark Cycle" : "Concurrent Undo Cycle");
|
||||
|
||||
concurrent_cycle_start();
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetTable* bot,
|
||||
HeapRegion* hr)
|
||||
: _bot(bot),
|
||||
_code_roots(),
|
||||
_m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrm_index()), true, Mutex::_safepoint_check_never),
|
||||
_m(Mutex::leaf, FormatBufferExternal(_m_name, sizeof(_m_name), "HeapRegionRemSet lock #%u", hr->hrm_index()), true, Mutex::_safepoint_check_never),
|
||||
_other_regions(&_m),
|
||||
_hr(hr),
|
||||
_state(Untracked)
|
||||
|
||||
@@ -282,6 +282,7 @@ private:
|
||||
// the region that owns this RSet.
|
||||
G1CodeRootSet _code_roots;
|
||||
|
||||
char _m_name[48];
|
||||
Mutex _m;
|
||||
|
||||
OtherRegionsTable _other_regions;
|
||||
|
||||
@@ -1147,7 +1147,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree *loop, ProjNode*
|
||||
Node* idx = cmp->in(1);
|
||||
assert(!invar.is_invariant(idx), "index is variant");
|
||||
Node* rng = cmp->in(2);
|
||||
assert(rng->Opcode() == Op_LoadRange || iff->is_RangeCheck() || _igvn.type(rng)->is_int()->_lo >= 0, "must be");
|
||||
// [tav: crash] assert(rng->Opcode() == Op_LoadRange || iff->is_RangeCheck() || _igvn.type(rng)->is_int()->_lo >= 0, "must be");
|
||||
assert(invar.is_invariant(rng), "range must be invariant");
|
||||
int scale = 1;
|
||||
Node* offset = zero;
|
||||
|
||||
@@ -961,6 +961,7 @@ bool os::print_function_and_library_name(outputStream* st,
|
||||
return have_function_name || have_library_name;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NO_SANITIZE_ADDRESS("Memory is read raw here without any regard for objects' boundaries")
|
||||
void os::print_hex_dump(outputStream* st, address start, address end, int unitsize,
|
||||
int bytes_per_line, address logical_start) {
|
||||
assert(unitsize == 1 || unitsize == 2 || unitsize == 4 || unitsize == 8, "just checking");
|
||||
|
||||
@@ -66,4 +66,10 @@
|
||||
#define PRAGMA_STRINGOP_TRUNCATION_IGNORED
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined (__GNUC__)
|
||||
# define ATTRIBUTE_NO_SANITIZE_ADDRESS(reason_for_exclusion) __attribute__((no_sanitize_address))
|
||||
#else
|
||||
# define ATTRIBUTE_NO_SANITIZE_ADDRESS(reason_for_exclusion)
|
||||
#endif
|
||||
|
||||
#endif // SHARE_UTILITIES_COMPILERWARNINGS_HPP
|
||||
|
||||
@@ -30,9 +30,17 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
FormatBufferResource::FormatBufferResource(const char * format, ...)
|
||||
: FormatBufferBase((char*)resource_allocate_bytes(FormatBufferBase::BufferSize)) {
|
||||
: FormatBufferBase((char*)resource_allocate_bytes(FormatBufferBase::DefaultBufferSize)) {
|
||||
va_list argp;
|
||||
va_start(argp, format);
|
||||
jio_vsnprintf(_buf, FormatBufferBase::BufferSize, format, argp);
|
||||
jio_vsnprintf(_buf, FormatBufferBase::DefaultBufferSize, format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
FormatBufferExternal::FormatBufferExternal(char* buf, size_t buf_size, const char * format, ...)
|
||||
: FormatBufferBase(buf) {
|
||||
va_list argp;
|
||||
va_start(argp, format);
|
||||
jio_vsnprintf(_buf, buf_size, format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include <stdarg.h>
|
||||
|
||||
// Simple class to format the ctor arguments into a fixed-sized buffer.
|
||||
// Simple classes to format the ctor arguments into a fixed-sized buffer.
|
||||
class FormatBufferBase {
|
||||
protected:
|
||||
char* _buf;
|
||||
inline FormatBufferBase(char* buf) : _buf(buf) {}
|
||||
public:
|
||||
static const int BufferSize = 256;
|
||||
static const int DefaultBufferSize = 256;
|
||||
operator const char *() const { return _buf; }
|
||||
};
|
||||
|
||||
@@ -45,11 +45,17 @@ class FormatBufferResource : public FormatBufferBase {
|
||||
FormatBufferResource(const char * format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||
};
|
||||
|
||||
// Use externally-provided area for buffer
|
||||
class FormatBufferExternal : public FormatBufferBase {
|
||||
public:
|
||||
FormatBufferExternal(char *buf, size_t buf_size, const char * format, ...) ATTRIBUTE_PRINTF(4, 5);
|
||||
};
|
||||
|
||||
class FormatBufferDummy {};
|
||||
|
||||
// Use stack for buffer
|
||||
template <size_t bufsz = FormatBufferBase::BufferSize>
|
||||
class FormatBuffer : public FormatBufferBase {
|
||||
template <size_t bufsz = FormatBufferBase::DefaultBufferSize>
|
||||
class FormatBuffer {
|
||||
public:
|
||||
inline FormatBuffer(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||
// since va_list is unspecified type (can be char*), we use FormatBufferDummy to disambiguate these constructors
|
||||
@@ -58,8 +64,9 @@ class FormatBuffer : public FormatBufferBase {
|
||||
inline void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||
inline void printv(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
|
||||
|
||||
char* buffer() { return _buf; }
|
||||
int size() { return bufsz; }
|
||||
operator const char *() const { return _buffer; }
|
||||
char* buffer() { return _buffer; }
|
||||
int size() const { return bufsz; }
|
||||
|
||||
private:
|
||||
FormatBuffer(const FormatBuffer &); // prevent copies
|
||||
@@ -70,42 +77,40 @@ class FormatBuffer : public FormatBufferBase {
|
||||
};
|
||||
|
||||
template <size_t bufsz>
|
||||
FormatBuffer<bufsz>::FormatBuffer(const char * format, ...) : FormatBufferBase(_buffer) {
|
||||
FormatBuffer<bufsz>::FormatBuffer(const char * format, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, format);
|
||||
jio_vsnprintf(_buf, bufsz, format, argp);
|
||||
jio_vsnprintf(_buffer, bufsz, format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
template <size_t bufsz>
|
||||
FormatBuffer<bufsz>::FormatBuffer(FormatBufferDummy dummy, const char * format, va_list ap) : FormatBufferBase(_buffer) {
|
||||
jio_vsnprintf(_buf, bufsz, format, ap);
|
||||
jio_vsnprintf(_buffer, bufsz, format, ap);
|
||||
}
|
||||
|
||||
template <size_t bufsz>
|
||||
FormatBuffer<bufsz>::FormatBuffer() : FormatBufferBase(_buffer) {
|
||||
_buf[0] = '\0';
|
||||
FormatBuffer<bufsz>::FormatBuffer() {
|
||||
_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
template <size_t bufsz>
|
||||
void FormatBuffer<bufsz>::print(const char * format, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, format);
|
||||
jio_vsnprintf(_buf, bufsz, format, argp);
|
||||
jio_vsnprintf(_buffer, bufsz, format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
template <size_t bufsz>
|
||||
void FormatBuffer<bufsz>::printv(const char * format, va_list argp) {
|
||||
jio_vsnprintf(_buf, bufsz, format, argp);
|
||||
jio_vsnprintf(_buffer, bufsz, format, argp);
|
||||
}
|
||||
|
||||
template <size_t bufsz>
|
||||
void FormatBuffer<bufsz>::append(const char* format, ...) {
|
||||
// Given that the constructor does a vsnprintf we can assume that
|
||||
// _buf is already initialized.
|
||||
size_t len = strlen(_buf);
|
||||
char* buf_end = _buf + len;
|
||||
size_t len = strnlen(_buffer, bufsz);
|
||||
char* buf_end = &_buffer[0] + len;
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, format);
|
||||
|
||||
@@ -430,6 +430,7 @@ void VMError::clear_step_start_time() {
|
||||
// could be nested report_and_die() calls on stack (see above). Only one
|
||||
// thread can report error, so large buffers are statically allocated in data
|
||||
// segment.
|
||||
ATTRIBUTE_NO_SANITIZE_ADDRESS("Memory is read raw here without any regard for objects' boundaries")
|
||||
void VMError::report(outputStream* st, bool _verbose) {
|
||||
|
||||
# define BEGIN if (_current_step == 0) { _current_step = __LINE__;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "version.rc"
|
||||
|
||||
#define IDI_ICON 2000
|
||||
#include "java_rc.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
6
src/java.base/windows/native/launcher/java_rc.h
Normal file
6
src/java.base/windows/native/launcher/java_rc.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _JAVA_RC_H_
|
||||
#define _JAVA_RC_H_
|
||||
|
||||
#define IDI_ICON 2000
|
||||
|
||||
#endif // _JAVA_RC_H_
|
||||
@@ -54,6 +54,7 @@ import javax.swing.JMenuBar;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.macosx.CPlatformWindow;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
/**
|
||||
* The {@code Application} class allows you to integrate your Java application with the native Mac OS X environment.
|
||||
@@ -74,6 +75,8 @@ import sun.lwawt.macosx.CPlatformWindow;
|
||||
* @since 1.4
|
||||
*/
|
||||
public class Application {
|
||||
private static final PlatformLogger focusRequestLog = PlatformLogger.getLogger("jb.focus.requests");
|
||||
|
||||
private static native void nativeInitializeApplicationDelegate();
|
||||
|
||||
static Application sApplication = null;
|
||||
@@ -296,6 +299,9 @@ public class Application {
|
||||
* @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
|
||||
*/
|
||||
public void requestForeground(final boolean allWindows) {
|
||||
if (focusRequestLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
focusRequestLog.fine("requestForeground(" + (allWindows ? "allWindows" : "") + ")", new Throwable());
|
||||
}
|
||||
_AppMiscHandlers.requestActivation(allWindows);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +82,11 @@ public class AquaImageFactory {
|
||||
}
|
||||
|
||||
static Image getGenericJavaIcon() {
|
||||
return java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() {
|
||||
return checkValidOrStub(java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() {
|
||||
public Image run() {
|
||||
return com.apple.eawt.Application.getApplication().getDockIconImage();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
static String getPathToThisApplication() {
|
||||
@@ -500,4 +500,23 @@ public class AquaImageFactory {
|
||||
public static Color getSelectedControlColorUIResource() {
|
||||
return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.SELECTED_CONTROL_TEXT_COLOR));
|
||||
}
|
||||
|
||||
private static class EmptyImage {
|
||||
static final BufferedImage INSTANCE;
|
||||
static {
|
||||
INSTANCE = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics g = INSTANCE.createGraphics();
|
||||
g.setColor(new Color(0, 0, 0, 0));
|
||||
g.fillRect(0, 0, 16, 16);
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// [tav] a workaround for JBR-1492
|
||||
private static Image checkValidOrStub(Image image) {
|
||||
if (image == null || image.getWidth(null) <= 0 || image.getHeight(null) <= 0) {
|
||||
return EmptyImage.INSTANCE;
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.Map;
|
||||
import sun.java2d.MacosxSurfaceManagerFactory;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.SurfaceManagerFactory;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
|
||||
/**
|
||||
* This is an implementation of a GraphicsEnvironment object for the default
|
||||
@@ -159,7 +160,15 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
private synchronized void initDevices() {
|
||||
Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
|
||||
devices.clear();
|
||||
mainDisplayID = getMainDisplayID();
|
||||
try {
|
||||
mainDisplayID = CThreading.privilegedExecuteOnAppKit(
|
||||
CGraphicsEnvironment::getMainDisplayID);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not get main display ID: " +
|
||||
e.getMessage() );
|
||||
}
|
||||
|
||||
// initialization of the graphics device may change list of displays on
|
||||
// hybrid systems via an activation of discrete video.
|
||||
@@ -169,7 +178,17 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID));
|
||||
}
|
||||
|
||||
int[] displayIDs = getDisplayIDs();
|
||||
int[] displayIDs;
|
||||
try {
|
||||
displayIDs = CThreading.privilegedExecuteOnAppKit(
|
||||
CGraphicsEnvironment::getDisplayIDs);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not get display IDs: " +
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
if (displayIDs.length == 0) {
|
||||
// we could throw AWTError in this case.
|
||||
displayIDs = new int[]{mainDisplayID};
|
||||
|
||||
@@ -28,6 +28,8 @@ package sun.font;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CCharToGlyphMapper extends CharToGlyphMapper {
|
||||
private static final int UNMAPPED_CHAR = Integer.MIN_VALUE;
|
||||
|
||||
private static native int countGlyphs(final long nativeFontPtr);
|
||||
|
||||
private Cache cache = new Cache();
|
||||
@@ -90,15 +92,16 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
|
||||
|
||||
public synchronized int charToGlyph(char unicode) {
|
||||
final int glyph = cache.get(unicode);
|
||||
if (glyph != 0) return glyph;
|
||||
if (glyph != 0) return glyph == UNMAPPED_CHAR ? 0 : glyph;
|
||||
|
||||
final char[] unicodeArray = new char[] { unicode };
|
||||
final int[] glyphArray = new int[1];
|
||||
|
||||
nativeCharsToGlyphs(fFont.getNativeFontPtr(), 1, unicodeArray, glyphArray);
|
||||
cache.put(unicode, glyphArray[0]);
|
||||
int result = glyphArray[0];
|
||||
cache.put(unicode, result == 0 ? UNMAPPED_CHAR : result);
|
||||
|
||||
return glyphArray[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized int charToGlyph(int unicode) {
|
||||
@@ -243,7 +246,7 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
|
||||
|
||||
final int value = get(code);
|
||||
if (value != 0 && value != -1) {
|
||||
values[i] = value;
|
||||
values[i] = value == UNMAPPED_CHAR ? 0 : value;
|
||||
if (code >= 0x10000) {
|
||||
values[i+1] = INVISIBLE_GLYPH_ID;
|
||||
i++;
|
||||
@@ -288,9 +291,10 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
|
||||
low - LO_SURROGATE_START + 0x10000;
|
||||
}
|
||||
}
|
||||
values[i] = glyphCodes[m];
|
||||
put(code, values[i]);
|
||||
if (code >= 0x10000) {
|
||||
values[i] = glyphCodes[m];
|
||||
int glyphCode = values[i];
|
||||
put(code, glyphCode == 0 ? UNMAPPED_CHAR : glyphCode);
|
||||
if (code >= 0x10000) {
|
||||
m++;
|
||||
values[i + 1] = INVISIBLE_GLYPH_ID;
|
||||
}
|
||||
|
||||
81
src/java.desktop/macosx/classes/sun/font/CCompositeFont.java
Normal file
81
src/java.desktop/macosx/classes/sun/font/CCompositeFont.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package sun.font;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class CCompositeFont extends CompositeFont {
|
||||
private final List<CFont> fallbackFonts = new ArrayList<>();
|
||||
|
||||
public CCompositeFont(CFont font) {
|
||||
super(new PhysicalFont[]{font});
|
||||
mapper = new CCompositeGlyphMapper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getNumSlots() {
|
||||
return super.getNumSlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CFont getSlotFont(int slot) {
|
||||
if (slot == 0) return (CFont) super.getSlotFont(0);
|
||||
synchronized (this) {
|
||||
return fallbackFonts.get(slot - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
|
||||
return super.getStrike(desc, copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized int getValidatedGlyphCode(int glyphCode) {
|
||||
return super.getValidatedGlyphCode(glyphCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSupplementaryChars() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAAForPtSize(int ptsize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized int findSlot(String fontName) {
|
||||
for (int slot = 0; slot < numSlots; slot++) {
|
||||
CFont slotFont = getSlotFont(slot);
|
||||
if (fontName.equals(slotFont.getNativeFontName())) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public synchronized int addSlot(CFont font) {
|
||||
int slot = findSlot(font.getNativeFontName());
|
||||
if (slot >= 0) return slot;
|
||||
fallbackFonts.add(font);
|
||||
lastFontStrike = new SoftReference<>(null);
|
||||
strikeCache.clear();
|
||||
return numSlots++;
|
||||
}
|
||||
}
|
||||
@@ -25,131 +25,55 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
|
||||
|
||||
private CompositeFont font;
|
||||
private CharToGlyphMapper[] slotMappers;
|
||||
|
||||
public CCompositeGlyphMapper(CompositeFont compFont) {
|
||||
public CCompositeGlyphMapper(CCompositeFont compFont) {
|
||||
super(compFont);
|
||||
font = compFont;
|
||||
slotMappers = new CharToGlyphMapper[font.numSlots];
|
||||
missingGlyph = 0;
|
||||
}
|
||||
|
||||
private CharToGlyphMapper getSlotMapper(int slot) {
|
||||
CharToGlyphMapper mapper = slotMappers[slot];
|
||||
if (mapper == null) {
|
||||
mapper = font.getSlotFont(slot).getMapper();
|
||||
slotMappers[slot] = mapper;
|
||||
@Override
|
||||
protected int convertToGlyph(int unicode) {
|
||||
CCompositeFont compositeFont = (CCompositeFont) font;
|
||||
CFont mainFont = (CFont) font.getSlotFont(0);
|
||||
String[] fallbackFontInfo = new String[2];
|
||||
int glyphCode = nativeCodePointToGlyph(mainFont.getNativeFontPtr(), unicode, fallbackFontInfo);
|
||||
if (glyphCode == missingGlyph) {
|
||||
setCachedGlyphCode(unicode, missingGlyph);
|
||||
return missingGlyph;
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
public boolean canDisplay(char ch) {
|
||||
int glyph = charToGlyph(ch);
|
||||
return glyph != missingGlyph;
|
||||
}
|
||||
|
||||
private int convertToGlyph(int unicode) {
|
||||
for (int slot = 0; slot < font.numSlots; slot++) {
|
||||
CharToGlyphMapper mapper = getSlotMapper(slot);
|
||||
int glyphCode = mapper.charToGlyph(unicode);
|
||||
// The CFont Mappers will return a negative code
|
||||
// for fonts that will fill the glyph from fallbacks
|
||||
// - cascading font in OSX-speak. But we need to be
|
||||
// know here that only the codes > 0 are really present.
|
||||
if (glyphCode > 0) {
|
||||
glyphCode = compositeGlyphCode(slot, glyphCode);
|
||||
return glyphCode;
|
||||
}
|
||||
}
|
||||
return missingGlyph;
|
||||
}
|
||||
|
||||
public int getNumGlyphs() {
|
||||
int numGlyphs = 0;
|
||||
for (int slot=0; slot<1 /*font.numSlots*/; slot++) {
|
||||
CharToGlyphMapper mapper = slotMappers[slot];
|
||||
if (mapper == null) {
|
||||
mapper = font.getSlotFont(slot).getMapper();
|
||||
slotMappers[slot] = mapper;
|
||||
}
|
||||
numGlyphs += mapper.getNumGlyphs();
|
||||
}
|
||||
return numGlyphs;
|
||||
}
|
||||
|
||||
public int charToGlyph(int unicode) {
|
||||
return convertToGlyph(unicode);
|
||||
}
|
||||
|
||||
public int charToGlyph(char unicode) {
|
||||
return convertToGlyph(unicode);
|
||||
}
|
||||
|
||||
public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
int code = unicodes[i]; // char is unsigned.
|
||||
|
||||
if (code >= HI_SURROGATE_START &&
|
||||
code <= HI_SURROGATE_END && i < count - 1) {
|
||||
char low = unicodes[i + 1];
|
||||
|
||||
if (low >= LO_SURROGATE_START &&
|
||||
low <= LO_SURROGATE_END) {
|
||||
code = (code - HI_SURROGATE_START) *
|
||||
0x400 + low - LO_SURROGATE_START + 0x10000;
|
||||
glyphs[i + 1] = INVISIBLE_GLYPH_ID;
|
||||
}
|
||||
}
|
||||
|
||||
glyphs[i] = convertToGlyph(code);
|
||||
|
||||
if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
|
||||
continue;
|
||||
}
|
||||
else if (FontUtilities.isComplexCharCode(code)) {
|
||||
return true;
|
||||
}
|
||||
else if (code >= 0x10000) {
|
||||
i += 1; // Empty glyph slot after surrogate
|
||||
continue;
|
||||
}
|
||||
String fallbackFontName = fallbackFontInfo[0];
|
||||
String fallbackFontFamilyName = fallbackFontInfo[1];
|
||||
if (fallbackFontName == null || fallbackFontFamilyName == null) {
|
||||
int result = compositeGlyphCode(0, glyphCode);
|
||||
setCachedGlyphCode(unicode, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
int slot = compositeFont.findSlot(fallbackFontName);
|
||||
|
||||
public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
|
||||
for (int i=0; i<count; i++) {
|
||||
int code = unicodes[i]; // char is unsigned.
|
||||
|
||||
if (code >= HI_SURROGATE_START &&
|
||||
code <= HI_SURROGATE_END && i < count - 1) {
|
||||
char low = unicodes[i + 1];
|
||||
|
||||
if (low >= LO_SURROGATE_START &&
|
||||
low <= LO_SURROGATE_END) {
|
||||
code = (code - HI_SURROGATE_START) *
|
||||
0x400 + low - LO_SURROGATE_START + 0x10000;
|
||||
|
||||
glyphs[i] = convertToGlyph(code);
|
||||
i += 1; // Empty glyph slot after surrogate
|
||||
glyphs[i] = INVISIBLE_GLYPH_ID;
|
||||
continue;
|
||||
}
|
||||
if (slot < 0) {
|
||||
Font2D fallbackFont = FontManagerFactory.getInstance().findFont2D(fallbackFontName,
|
||||
Font.PLAIN, FontManager.NO_FALLBACK);
|
||||
if (!(fallbackFont instanceof CFont) ||
|
||||
!fallbackFontName.equals(((CFont) fallbackFont).getNativeFontName())) {
|
||||
// Native font fallback mechanism can return "hidden" fonts - their names start with dot,
|
||||
// and they are not returned in a list of fonts available in system, but they can still be used
|
||||
// if requested explicitly.
|
||||
fallbackFont = new CFont(fallbackFontName, fallbackFontFamilyName);
|
||||
}
|
||||
|
||||
glyphs[i] = convertToGlyph(code);
|
||||
if (mainFont.isFakeItalic()) fallbackFont = ((CFont)fallbackFont).createItalicVariant(false);
|
||||
|
||||
slot = compositeFont.addSlot((CFont) fallbackFont);
|
||||
}
|
||||
|
||||
int result = compositeGlyphCode(slot, glyphCode);
|
||||
setCachedGlyphCode(unicode, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
|
||||
for (int i=0; i<count; i++) {
|
||||
glyphs[i] = convertToGlyph(unicodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// This invokes native font fallback mechanism, returning information about font (its Postscript and family names)
|
||||
// able to display a given character, and corresponding glyph code
|
||||
private static native int nativeCodePointToGlyph(long nativeFontPtr, int codePoint, String[] result);
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Right now this class is final to avoid a problem with native code.
|
||||
// For some reason the JNI IsInstanceOf was not working correctly
|
||||
@@ -174,12 +173,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
||||
isFakeItalic = other.isFakeItalic;
|
||||
}
|
||||
|
||||
public CFont createItalicVariant() {
|
||||
public CFont createItalicVariant(boolean updateStyle) {
|
||||
CFont font = new CFont(this, familyName);
|
||||
font.nativeFontName = fullName;
|
||||
font.fullName =
|
||||
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
|
||||
font.style |= Font.ITALIC;
|
||||
if (updateStyle) {
|
||||
font.style |= Font.ITALIC;
|
||||
}
|
||||
font.isFakeItalic = true;
|
||||
return font;
|
||||
}
|
||||
@@ -198,45 +199,11 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
||||
return getCGFontPtrNative(getNativeFontPtr());
|
||||
}
|
||||
|
||||
static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
|
||||
|
||||
private CompositeFont createCompositeFont() {
|
||||
ArrayList<String> listOfString = new ArrayList<String>();
|
||||
getCascadeList(nativeFontPtr, listOfString);
|
||||
|
||||
// In some italic cases the standard Mac cascade list is missing Arabic.
|
||||
listOfString.add("GeezaPro");
|
||||
FontManager fm = FontManagerFactory.getInstance();
|
||||
int numFonts = 1 + listOfString.size();
|
||||
PhysicalFont[] fonts = new PhysicalFont[numFonts];
|
||||
fonts[0] = this;
|
||||
int idx = 1;
|
||||
for (String s : listOfString) {
|
||||
if (s.equals(".AppleSymbolsFB")) {
|
||||
// Don't know why we get the weird name above .. replace.
|
||||
s = "AppleSymbols";
|
||||
}
|
||||
Font2D f2d = fm.findFont2D(s, Font.PLAIN, FontManager.NO_FALLBACK);
|
||||
if (f2d == null || f2d == this) {
|
||||
continue;
|
||||
}
|
||||
fonts[idx++] = (PhysicalFont)f2d;
|
||||
}
|
||||
if (idx < fonts.length) {
|
||||
PhysicalFont[] orig = fonts;
|
||||
fonts = new PhysicalFont[idx];
|
||||
System.arraycopy(orig, 0, fonts, 0, idx);
|
||||
}
|
||||
CompositeFont compFont = new CompositeFont(fonts);
|
||||
compFont.mapper = new CCompositeGlyphMapper(compFont);
|
||||
return compFont;
|
||||
}
|
||||
|
||||
private CompositeFont compFont;
|
||||
|
||||
public CompositeFont getCompositeFont2D() {
|
||||
if (compFont == null) {
|
||||
compFont = createCompositeFont();
|
||||
compFont = new CCompositeFont(this);
|
||||
}
|
||||
return compFont;
|
||||
}
|
||||
@@ -264,6 +231,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
||||
return new CStrike(this, desc);
|
||||
}
|
||||
|
||||
boolean isFakeItalic() {
|
||||
return isFakeItalic;
|
||||
}
|
||||
|
||||
String getNativeFontName() {
|
||||
return nativeFontName;
|
||||
}
|
||||
|
||||
// <rdar://problem/5321707> sun.font.Font2D caches the last used strike,
|
||||
// but does not check if the properties of the strike match the properties
|
||||
// of the incoming java.awt.Font object (size, style, etc).
|
||||
|
||||
@@ -190,10 +190,10 @@ public final class CFontManager extends SunFontManager {
|
||||
if (plain == null && bold == null) continue;
|
||||
if (italic != null && boldItalic != null) continue;
|
||||
if (plain != null && italic == null) {
|
||||
registerGenericFont(plain.createItalicVariant(), true);
|
||||
registerGenericFont(plain.createItalicVariant(true), true);
|
||||
}
|
||||
if (bold != null && boldItalic == null) {
|
||||
registerGenericFont(bold.createItalicVariant(), true);
|
||||
registerGenericFont(bold.createItalicVariant(true), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,13 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import sun.lwawt.macosx.concurrent.Dispatch;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.*;
|
||||
import java.util.*;
|
||||
|
||||
import sun.awt.SunHints;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
|
||||
public final class CStrike extends PhysicalStrike {
|
||||
|
||||
@@ -62,6 +64,11 @@ public final class CStrike extends PhysicalStrike {
|
||||
double x,
|
||||
double y);
|
||||
|
||||
private static native void getNativeGlyphOutlineBounds(long nativeStrikePtr,
|
||||
int glyphCode,
|
||||
Rectangle.Float result,
|
||||
double x, double y);
|
||||
|
||||
// returns the bounding rect for a glyph
|
||||
private static native void getNativeGlyphImageBounds(long nativeStrikePtr,
|
||||
int glyphCode,
|
||||
@@ -175,18 +182,8 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) {
|
||||
GeneralPath gp = getGlyphOutline(glyphCode, 0f, 0f);
|
||||
Rectangle2D r2d = gp.getBounds2D();
|
||||
Rectangle2D.Float r2df;
|
||||
if (r2d instanceof Rectangle2D.Float) {
|
||||
r2df = (Rectangle2D.Float)r2d;
|
||||
} else {
|
||||
float x = (float)r2d.getX();
|
||||
float y = (float)r2d.getY();
|
||||
float w = (float)r2d.getWidth();
|
||||
float h = (float)r2d.getHeight();
|
||||
r2df = new Rectangle2D.Float(x, y, w, h);
|
||||
}
|
||||
Rectangle2D.Float r2df = new Rectangle2D.Float();
|
||||
getNativeGlyphOutlineBounds(getNativeStrikePtr(), glyphCode, r2df, 0, 0);
|
||||
return r2df;
|
||||
}
|
||||
|
||||
@@ -357,7 +354,7 @@ public final class CStrike extends PhysicalStrike {
|
||||
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
|
||||
|
||||
// rdar://problem/5204197
|
||||
private boolean disposed = false;
|
||||
private final AtomicBoolean disposed = new AtomicBoolean(false);
|
||||
|
||||
private final long[] firstLayerCache;
|
||||
private SparseBitShiftingTwoLayerArray secondLayerCache;
|
||||
@@ -420,43 +417,56 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
// rdar://problem/5204197
|
||||
// Note that sun.font.Font2D.getStrike() actively disposes
|
||||
// cleared strikeRef. We need to check the disposed flag to
|
||||
// prevent double frees of native resources.
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
final Runnable command = () -> {
|
||||
// rdar://problem/5204197
|
||||
// Note that sun.font.Font2D.getStrike() actively disposes
|
||||
// cleared strikeRef. We need to check the disposed flag to
|
||||
// prevent double frees of native resources.
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
|
||||
super.dispose();
|
||||
super.dispose();
|
||||
|
||||
// clean out the first array
|
||||
disposeLongArray(firstLayerCache);
|
||||
// clean out the first array
|
||||
disposeLongArray(firstLayerCache);
|
||||
|
||||
// clean out the two layer arrays
|
||||
if (secondLayerCache != null) {
|
||||
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
|
||||
for (int i = 0; i < secondLayerLongArrayArray.length; i++) {
|
||||
final long[] longArray = secondLayerLongArrayArray[i];
|
||||
if (longArray != null) disposeLongArray(longArray);
|
||||
}
|
||||
}
|
||||
// clean out the two layer arrays
|
||||
if (secondLayerCache != null) {
|
||||
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
|
||||
for (final long[] longArray : secondLayerLongArrayArray) {
|
||||
if (longArray != null) disposeLongArray(longArray);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up everyone else
|
||||
if (generalCache != null) {
|
||||
final Iterator<Long> i = generalCache.values().iterator();
|
||||
while (i.hasNext()) {
|
||||
final long longValue = i.next().longValue();
|
||||
if (longValue != -1 && longValue != 0) {
|
||||
removeGlyphInfoFromCache(longValue);
|
||||
StrikeCache.freeLongPointer(longValue);
|
||||
// clean up everyone else
|
||||
if (generalCache != null) {
|
||||
for (Long aLong : generalCache.values()) {
|
||||
final long longValue = aLong;
|
||||
if (longValue != -1 && longValue != 0) {
|
||||
removeGlyphInfoFromCache(longValue);
|
||||
StrikeCache.freeLongPointer(longValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// rdar://problem/5204197
|
||||
// Finally, set the flag.
|
||||
disposed = true;
|
||||
// Move disposal code to AppKit thread in order to avoid the
|
||||
// following deadlock:
|
||||
// 1) CGLGraphicsConfig.getCGLConfigInfo (called from Java2D
|
||||
// disposal thread) takes RenderQueue.lock
|
||||
// 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
|
||||
// blocked on RenderQueue.lock
|
||||
// 1) invokes native block on AppKit and wait
|
||||
//
|
||||
// If dispatch instance is not available, run the code on
|
||||
// disposal thread as before
|
||||
|
||||
final Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (!CThreading.isAppKit() && dispatch != null)
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(command);
|
||||
else
|
||||
command.run();
|
||||
}
|
||||
|
||||
private static void disposeLongArray(final long[] longArray) {
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import sun.lwawt.macosx.concurrent.Dispatch;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/*
|
||||
* This keeps track of data that needs to be cleaned up once a
|
||||
* strike is freed.
|
||||
@@ -49,6 +54,7 @@ package sun.font;
|
||||
class CStrikeDisposer extends FontStrikeDisposer {
|
||||
|
||||
long pNativeScalerContext;
|
||||
private final AtomicBoolean disposed = new AtomicBoolean(false);
|
||||
|
||||
public CStrikeDisposer(Font2D font2D, FontStrikeDesc desc,
|
||||
long pContext, int[] images)
|
||||
@@ -76,12 +82,31 @@ class CStrikeDisposer extends FontStrikeDisposer {
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
if (!disposed) {
|
||||
if (pNativeScalerContext != 0L) {
|
||||
freeNativeScalerContext(pNativeScalerContext);
|
||||
final Runnable command = () -> {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
if (pNativeScalerContext != 0L) {
|
||||
freeNativeScalerContext(pNativeScalerContext);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
};
|
||||
// Move disposal code to AppKit thread in order to avoid the
|
||||
// following deadlock:
|
||||
// 1) CGLGraphicsConfig.getCGLConfigInfo (called from Java2D
|
||||
// disposal thread) takes RenderQueue.lock
|
||||
// 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
|
||||
// blocked on RenderQueue.lock
|
||||
// 1) invokes native block on AppKit and wait
|
||||
//
|
||||
// If dispatch instance is not available, run the code on
|
||||
// disposal thread as before
|
||||
|
||||
final Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (!CThreading.isAppKit() && dispatch != null)
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(command);
|
||||
else
|
||||
command.run();
|
||||
}
|
||||
|
||||
private native void freeNativeScalerContext(long pContext);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
package sun.java2d.opengl;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.AWTError;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
@@ -61,6 +62,9 @@ import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_DOUBLEBUFFERED;
|
||||
import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_EXT_FBOBJECT;
|
||||
import static sun.java2d.opengl.OGLSurfaceData.FBOBJECT;
|
||||
import static sun.java2d.opengl.OGLSurfaceData.TEXTURE;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public final class CGLGraphicsConfig extends CGraphicsConfig
|
||||
implements OGLGraphicsConfig
|
||||
@@ -124,38 +128,56 @@ public final class CGLGraphicsConfig extends CGraphicsConfig
|
||||
return null;
|
||||
}
|
||||
|
||||
long cfginfo = 0;
|
||||
int textureSize = 0;
|
||||
final String[] ids = new String[1];
|
||||
OGLRenderQueue rq = OGLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// getCGLConfigInfo() creates and destroys temporary
|
||||
// surfaces/contexts, so we should first invalidate the current
|
||||
// Java-level context and flush the queue...
|
||||
OGLContext.invalidateCurrentContext();
|
||||
cfginfo = getCGLConfigInfo();
|
||||
if (cfginfo != 0L) {
|
||||
textureSize = nativeGetMaxTextureSize();
|
||||
// 7160609: GL still fails to create a square texture of this
|
||||
// size. Half should be safe enough.
|
||||
// Explicitly not support a texture more than 2^14, see 8010999.
|
||||
textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
|
||||
OGLContext.setScratchSurface(cfginfo);
|
||||
rq.flushAndInvokeNow(() -> {
|
||||
ids[0] = OGLContext.getOGLIdString();
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
if (cfginfo == 0) {
|
||||
return null;
|
||||
}
|
||||
// Move CGLGraphicsConfig creation code to AppKit thread in order to avoid the
|
||||
// following deadlock:
|
||||
// 1) CGLGraphicsConfig.getCGLConfigInfo (called from EDT) takes RenderQueue.lock
|
||||
// 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
|
||||
// blocked on RenderQueue.lock
|
||||
// 1) invokes native block on AppKit and wait
|
||||
|
||||
int oglCaps = getOGLCapabilities(cfginfo);
|
||||
ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
|
||||
return new CGLGraphicsConfig(device, cfginfo, textureSize, caps);
|
||||
Callable<CGLGraphicsConfig> command = () -> {
|
||||
long cfginfo = 0;
|
||||
int textureSize = 0;
|
||||
final String[] ids = new String[1];
|
||||
OGLRenderQueue rq = OGLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// getCGLConfigInfo() creates and destroys temporary
|
||||
// surfaces/contexts, so we should first invalidate the current
|
||||
// Java-level context and flush the queue...
|
||||
OGLContext.invalidateCurrentContext();
|
||||
cfginfo = getCGLConfigInfo();
|
||||
if (cfginfo != 0L) {
|
||||
textureSize = nativeGetMaxTextureSize();
|
||||
// 7160609: GL still fails to create a square texture of this
|
||||
// size. Half should be safe enough.
|
||||
// Explicitly not support a texture more than 2^14, see 8010999.
|
||||
textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
|
||||
OGLContext.setScratchSurface(cfginfo);
|
||||
rq.flushAndInvokeNow(() -> {
|
||||
ids[0] = OGLContext.getOGLIdString();
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
if (cfginfo == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int oglCaps = getOGLCapabilities(cfginfo);
|
||||
ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
|
||||
return new CGLGraphicsConfig(device, cfginfo, textureSize, caps);
|
||||
};
|
||||
|
||||
return java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<CGLGraphicsConfig>) () -> {
|
||||
try {
|
||||
return CThreading.executeOnAppKit(command);
|
||||
} catch (Throwable throwable) {
|
||||
throw new AWTError(throwable.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isCGLAvailable() {
|
||||
|
||||
@@ -928,7 +928,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
|
||||
int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
|
||||
getTarget(), lightweightChild, temporary,
|
||||
focusedWindowChangeAllowed, time, cause);
|
||||
focusedWindowChangeAllowed, time, cause, false);
|
||||
switch (result) {
|
||||
case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
|
||||
return false;
|
||||
@@ -982,9 +982,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
|
||||
Component focusOwner = kfmPeer.getCurrentFocusOwner();
|
||||
return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
|
||||
getTarget(), temporary,
|
||||
focusedWindowChangeAllowed,
|
||||
time, cause, focusOwner);
|
||||
getTarget(), false, cause, focusOwner);
|
||||
|
||||
case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
|
||||
return true;
|
||||
|
||||
@@ -78,6 +78,7 @@ import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.lwawt.macosx.CPlatformWindow;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class LWWindowPeer
|
||||
@@ -1510,4 +1511,17 @@ public class LWWindowPeer
|
||||
public String toString() {
|
||||
return super.toString() + " [target is " + getTarget() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* [tav] Used externally.
|
||||
*/
|
||||
@Override
|
||||
public long getWindowHandle() {
|
||||
final long[] handle = new long[1];
|
||||
PlatformWindow window = getPlatformWindow();
|
||||
if (window instanceof CPlatformWindow) {
|
||||
((CPlatformWindow)window).execute(ptr -> handle[0] = ptr);
|
||||
}
|
||||
return handle[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
return accessible.getAccessibleContext();
|
||||
return accessible != null ? accessible.getAccessibleContext() : null;
|
||||
}
|
||||
|
||||
public void addNotificationListeners(Component c) {
|
||||
|
||||
@@ -29,12 +29,8 @@ package sun.lwawt.macosx;
|
||||
import java.awt.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import java.awt.datatransfer.*;
|
||||
@@ -159,8 +155,6 @@ public class CDataTransferer extends DataTransferer {
|
||||
// regular string that allows to translate data to target represantation
|
||||
// class by base method
|
||||
format = CF_STRING;
|
||||
} else if (format == CF_STRING) {
|
||||
bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8");
|
||||
}
|
||||
|
||||
return super.translateBytes(bytes, flavor, format, transferable);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import java.awt.im.spi.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.awt.*;
|
||||
import java.awt.peer.*;
|
||||
@@ -36,17 +37,21 @@ import java.lang.Character.Subset;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.im.InputMethodAdapter;
|
||||
import sun.lwawt.*;
|
||||
|
||||
import static sun.awt.AWTAccessor.ComponentAccessor;
|
||||
|
||||
public class CInputMethod extends InputMethodAdapter {
|
||||
private InputMethodContext fIMContext;
|
||||
private Component fAwtFocussedComponent;
|
||||
private volatile InputMethodContext fIMContext;
|
||||
private volatile Component fAwtFocussedComponent;
|
||||
private LWComponentPeer<?, ?> fAwtFocussedComponentPeer;
|
||||
private boolean isActive;
|
||||
|
||||
@@ -292,6 +297,18 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
if (component.getInputMethodRequests() == null) {
|
||||
imInstance = null;
|
||||
}
|
||||
|
||||
LWWindowPeer windowPeer = peer.getPlatformWindow().getPeer();
|
||||
if (windowPeer.isSimpleWindow()) {
|
||||
// A simple window gains focus. Cocoa won't dispatch IME events into the simple window, but into its owner.
|
||||
// This IM represents the focused component in the simple window. We will use the owner as IME proxy.
|
||||
// For that, this IM is set for the owner and is dropped for the simple window.
|
||||
Window owner = windowPeer.getTarget().getOwner();
|
||||
assert owner != null && owner.isActive();
|
||||
long ownerPtr = getNativeViewPtr((LWComponentPeer)AWTAccessor.getComponentAccessor().getPeer(owner));
|
||||
nativeNotifyPeer(ownerPtr, this);
|
||||
imInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (peer != null) {
|
||||
@@ -587,6 +604,7 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
final String[] retString = new String[1];
|
||||
|
||||
try {
|
||||
if (fIMContext != null)
|
||||
LWCToolkit.invokeAndWait(new Runnable() {
|
||||
public void run() { synchronized(retString) {
|
||||
int location = locationIn;
|
||||
@@ -639,6 +657,7 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
final int[] returnValue = new int[2];
|
||||
|
||||
try {
|
||||
if (fIMContext != null)
|
||||
LWCToolkit.invokeAndWait(new Runnable() {
|
||||
public void run() { synchronized(returnValue) {
|
||||
AttributedCharacterIterator theIterator = fIMContext.getSelectedText(null);
|
||||
@@ -714,36 +733,38 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
final int[] rect = new int[4];
|
||||
|
||||
try {
|
||||
LWCToolkit.invokeAndWait(new Runnable() {
|
||||
public void run() { synchronized(rect) {
|
||||
int insertOffset = fIMContext.getInsertPositionOffset();
|
||||
int composedTextOffset = absoluteTextOffset - insertOffset;
|
||||
if (composedTextOffset < 0) composedTextOffset = 0;
|
||||
Rectangle r = fIMContext.getTextLocation(TextHitInfo.beforeOffset(composedTextOffset));
|
||||
rect[0] = r.x;
|
||||
rect[1] = r.y;
|
||||
rect[2] = r.width;
|
||||
rect[3] = r.height;
|
||||
if (fIMContext != null) {
|
||||
FxInvoker.invoke(() -> {
|
||||
synchronized (rect) {
|
||||
int insertOffset = fIMContext.getInsertPositionOffset();
|
||||
int composedTextOffset = absoluteTextOffset - insertOffset;
|
||||
if (composedTextOffset < 0) composedTextOffset = 0;
|
||||
Rectangle r = fIMContext.getTextLocation(TextHitInfo.beforeOffset(composedTextOffset));
|
||||
rect[0] = r.x;
|
||||
rect[1] = r.y;
|
||||
rect[2] = r.width;
|
||||
rect[3] = r.height;
|
||||
|
||||
// This next if-block is a hack to work around a bug in JTextComponent. getTextLocation ignores
|
||||
// the TextHitInfo passed to it and always returns the location of the insertion point, which is
|
||||
// at the start of the composed text. We'll do some calculation so the candidate window for Kotoeri
|
||||
// follows the requested offset into the composed text.
|
||||
if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) {
|
||||
Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0));
|
||||
// This next if-block is a hack to work around a bug in JTextComponent. getTextLocation ignores
|
||||
// the TextHitInfo passed to it and always returns the location of the insertion point, which is
|
||||
// at the start of the composed text. We'll do some calculation so the candidate window for Kotoeri
|
||||
// follows the requested offset into the composed text.
|
||||
if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) {
|
||||
Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0));
|
||||
|
||||
if (r.equals(r2)) {
|
||||
// FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate
|
||||
// window off the right edge of the component.
|
||||
String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset);
|
||||
Graphics g = fAwtFocussedComponent.getGraphics();
|
||||
int xOffset = g.getFontMetrics().stringWidth(inProgressSubstring);
|
||||
rect[0] += xOffset;
|
||||
g.dispose();
|
||||
if (r.equals(r2) && fCurrentTextAsString != null) {
|
||||
// FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate
|
||||
// window off the right edge of the component.
|
||||
String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset);
|
||||
Graphics g = fAwtFocussedComponent.getGraphics();
|
||||
int xOffset = g.getFontMetrics().stringWidth(inProgressSubstring);
|
||||
rect[0] += xOffset;
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
}, fAwtFocussedComponent);
|
||||
}, (sun.awt.im.InputContext)fIMContext, fAwtFocussedComponent);
|
||||
}
|
||||
} catch (InvocationTargetException ite) { ite.printStackTrace(); }
|
||||
|
||||
synchronized(rect) { return rect; }
|
||||
@@ -758,12 +779,14 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
final int[] insertPositionOffset = new int[1];
|
||||
|
||||
try {
|
||||
LWCToolkit.invokeAndWait(new Runnable() {
|
||||
public void run() { synchronized(offsetInfo) {
|
||||
offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY);
|
||||
insertPositionOffset[0] = fIMContext.getInsertPositionOffset();
|
||||
}}
|
||||
}, fAwtFocussedComponent);
|
||||
if (fIMContext != null) {
|
||||
FxInvoker.invoke(() -> {
|
||||
synchronized (offsetInfo) {
|
||||
offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY);
|
||||
insertPositionOffset[0] = fIMContext.getInsertPositionOffset();
|
||||
}
|
||||
}, (sun.awt.im.InputContext)fIMContext, fAwtFocussedComponent);
|
||||
}
|
||||
} catch (InvocationTargetException ite) { ite.printStackTrace(); }
|
||||
|
||||
// This bit of gymnastics ensures that the returned location is within the composed text.
|
||||
@@ -813,4 +836,63 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
|
||||
// Initialize toolbox routines
|
||||
static native void nativeInit();
|
||||
|
||||
private static class FxInvoker {
|
||||
final static Method GET_CLIENT_COMPONENT_METHOD;
|
||||
static Class<?> JFX_PANEL_CLASS;
|
||||
|
||||
static {
|
||||
Method m = null;
|
||||
try {
|
||||
m = sun.awt.im.InputContext.class.getDeclaredMethod("getClientComponent");
|
||||
if (m != null) m.setAccessible(true);
|
||||
} catch (NoSuchMethodException ignore) {
|
||||
}
|
||||
GET_CLIENT_COMPONENT_METHOD = m;
|
||||
}
|
||||
|
||||
static Component getClientComponent(sun.awt.im.InputContext ctx) {
|
||||
if (GET_CLIENT_COMPONENT_METHOD != null) {
|
||||
try {
|
||||
return (Component)GET_CLIENT_COMPONENT_METHOD.invoke(ctx);
|
||||
} catch (IllegalAccessException | InvocationTargetException ignore) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean instanceofJFXPanel(Component clientComponent) {
|
||||
if (clientComponent != null) {
|
||||
if (JFX_PANEL_CLASS == null) {
|
||||
try {
|
||||
// the class is not available in the current class loader context, use the client class loader
|
||||
JFX_PANEL_CLASS = Class.forName("javafx.embed.swing.JFXPanel", false, clientComponent.getClass().getClassLoader());
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
}
|
||||
}
|
||||
if (JFX_PANEL_CLASS != null) {
|
||||
return JFX_PANEL_CLASS.isInstance(clientComponent);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Executed on AppKit
|
||||
static void invoke(Runnable runnable, sun.awt.im.InputContext inputContext, Component targetToAppContext) throws InvocationTargetException {
|
||||
AtomicBoolean runOnAppKit = new AtomicBoolean(false);
|
||||
|
||||
// 1) Do not run secondary msg loop in this case.
|
||||
// 2) Delegate runnable back to FX when applicable.
|
||||
LWCToolkit.invokeAndWait(() -> {
|
||||
runOnAppKit.set(instanceofJFXPanel(getClientComponent(inputContext)));
|
||||
if (!runOnAppKit.get()) {
|
||||
runnable.run();
|
||||
}
|
||||
}, targetToAppContext);
|
||||
|
||||
if (runOnAppKit.get()) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import java.awt.AWTError;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.DefaultKeyboardFocusManager;
|
||||
@@ -51,6 +52,7 @@ import java.util.Comparator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.RootPaneContainer;
|
||||
@@ -61,6 +63,7 @@ import com.apple.laf.ClientPropertyApplicator.Property;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.AWTAccessor.WindowAccessor;
|
||||
import sun.awt.InvokeOnToolkitHelper;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.lwawt.LWLightweightFramePeer;
|
||||
import sun.lwawt.LWToolkit;
|
||||
@@ -72,6 +75,7 @@ import sun.util.logging.PlatformLogger;
|
||||
public class CPlatformWindow extends CFRetainedResource implements PlatformWindow {
|
||||
private native long nativeCreateNSWindow(long nsViewPtr,long ownerPtr, long styleBits, double x, double y, double w, double h);
|
||||
private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data);
|
||||
private static native void nativeSetNSWindowAppearance(long nsWindowPtr, String appearanceName);
|
||||
private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr);
|
||||
private static native Insets nativeGetNSWindowInsets(long nsWindowPtr);
|
||||
private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h);
|
||||
@@ -122,6 +126,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
public static final String WINDOW_FULLSCREENABLE = "apple.awt.fullscreenable";
|
||||
public static final String WINDOW_FULL_CONTENT = "apple.awt.fullWindowContent";
|
||||
public static final String WINDOW_TRANSPARENT_TITLE_BAR = "apple.awt.transparentTitleBar";
|
||||
public static final String WINDOW_TITLE_VISIBLE = "apple.awt.windowTitleVisible";
|
||||
public static final String WINDOW_APPEARANCE = "apple.awt.windowAppearance";
|
||||
|
||||
// Yeah, I know. But it's easier to deal with ints from JNI
|
||||
static final int MODELESS = 0;
|
||||
@@ -164,10 +170,11 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
static final int DOCUMENT_MODIFIED = 1 << 21;
|
||||
static final int FULLSCREENABLE = 1 << 23;
|
||||
static final int TRANSPARENT_TITLE_BAR = 1 << 18;
|
||||
static final int TITLE_VISIBLE = 1 << 25;
|
||||
|
||||
static final int _METHOD_PROP_BITMASK = RESIZABLE | HAS_SHADOW | ZOOMABLE | ALWAYS_ON_TOP | HIDES_ON_DEACTIVATE
|
||||
| DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE
|
||||
| TRANSPARENT_TITLE_BAR;
|
||||
| TRANSPARENT_TITLE_BAR | TITLE_VISIBLE;
|
||||
|
||||
// corresponds to callback-based properties
|
||||
static final int SHOULD_BECOME_KEY = 1 << 12;
|
||||
@@ -248,6 +255,18 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
boolean isTransparentTitleBar = Boolean.parseBoolean(value.toString());
|
||||
c.setStyleBits(TRANSPARENT_TITLE_BAR, isTransparentTitleBar);
|
||||
}
|
||||
},
|
||||
new Property<CPlatformWindow>(WINDOW_TITLE_VISIBLE) {
|
||||
public void applyProperty(final CPlatformWindow c, final Object value) {
|
||||
c.setStyleBits(TITLE_VISIBLE, value == null ? true : Boolean.parseBoolean(value.toString()));
|
||||
}
|
||||
},
|
||||
new Property<CPlatformWindow>(WINDOW_APPEARANCE) {
|
||||
public void applyProperty(final CPlatformWindow c, final Object value) {
|
||||
if (value != null && (value instanceof String)) {
|
||||
c.execute(ptr -> nativeSetNSWindowAppearance(ptr, (String) value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}) {
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -323,26 +342,36 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
} else {
|
||||
bounds = _peer.constrainBounds(_target.getBounds());
|
||||
}
|
||||
AtomicLong ref = new AtomicLong();
|
||||
contentView.execute(viewPtr -> {
|
||||
boolean hasOwnerPtr = false;
|
||||
long nativeWindowPtr = java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Long>) () -> {
|
||||
try {
|
||||
return InvokeOnToolkitHelper.invokeAndBlock(() -> {
|
||||
AtomicLong ref = new AtomicLong();
|
||||
contentView.execute(viewPtr -> {
|
||||
boolean hasOwnerPtr = false;
|
||||
|
||||
if (owner != null) {
|
||||
hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> {
|
||||
ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits,
|
||||
bounds.x, bounds.y,
|
||||
bounds.width, bounds.height));
|
||||
return 1;
|
||||
if (owner != null) {
|
||||
hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> {
|
||||
ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits,
|
||||
bounds.x, bounds.y,
|
||||
bounds.width, bounds.height));
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasOwnerPtr) {
|
||||
ref.set(nativeCreateNSWindow(viewPtr, 0,
|
||||
styleBits, bounds.x, bounds.y,
|
||||
bounds.width, bounds.height));
|
||||
}
|
||||
});
|
||||
return ref.get();
|
||||
});
|
||||
} catch (Throwable throwable) {
|
||||
throw new AWTError(throwable.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasOwnerPtr) {
|
||||
ref.set(nativeCreateNSWindow(viewPtr, 0,
|
||||
styleBits, bounds.x, bounds.y,
|
||||
bounds.width, bounds.height));
|
||||
}
|
||||
});
|
||||
setPtr(ref.get());
|
||||
setPtr(nativeWindowPtr);
|
||||
|
||||
if (target instanceof javax.swing.RootPaneContainer) {
|
||||
final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
|
||||
@@ -374,7 +403,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
protected int getInitialStyleBits() {
|
||||
// defaults style bits
|
||||
int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE;
|
||||
int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE | TITLE_VISIBLE;
|
||||
|
||||
if (isNativelyFocusableWindow()) {
|
||||
styleBits = SET(styleBits, SHOULD_BECOME_KEY, true);
|
||||
@@ -496,6 +525,11 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
if (prop != null) {
|
||||
styleBits = SET(styleBits, TRANSPARENT_TITLE_BAR, Boolean.parseBoolean(prop.toString()));
|
||||
}
|
||||
|
||||
prop = rootpane.getClientProperty(WINDOW_TITLE_VISIBLE);
|
||||
if (prop != null) {
|
||||
styleBits = SET(styleBits, TITLE_VISIBLE, Boolean.parseBoolean(prop.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (isDialog) {
|
||||
@@ -1161,11 +1195,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return !peer.isSimpleWindow() && target.getFocusableWindowState();
|
||||
}
|
||||
|
||||
private boolean isBlocked() {
|
||||
LWWindowPeer blocker = (peer != null) ? peer.getBlocker() : null;
|
||||
return (blocker != null);
|
||||
}
|
||||
|
||||
/*
|
||||
* An utility method for the support of the auto request focus.
|
||||
* Updates the focusable state of the window under certain
|
||||
|
||||
148
src/java.desktop/macosx/classes/sun/lwawt/macosx/CThreading.java
Normal file
148
src/java.desktop/macosx/classes/sun/lwawt/macosx/CThreading.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 sun.lwawt.macosx;
|
||||
|
||||
import sun.lwawt.macosx.concurrent.Dispatch;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.AWTError;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
|
||||
public class CThreading {
|
||||
static String APPKIT_THREAD_NAME = "AWT-AppKit";
|
||||
|
||||
static boolean isEventQueue() {
|
||||
return EventQueue.isDispatchThread();
|
||||
}
|
||||
|
||||
private static native boolean isMainThread();
|
||||
|
||||
public static boolean isAppKit() {
|
||||
if (APPKIT_THREAD_NAME.equals(Thread.currentThread().getName())) return true;
|
||||
|
||||
if (isMainThread()) {
|
||||
Thread.currentThread().setName(APPKIT_THREAD_NAME);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static boolean assertEventQueue() {
|
||||
final boolean isEventQueue = isEventQueue();
|
||||
assert isEventQueue : "Threading violation: not EventQueue thread";
|
||||
return isEventQueue;
|
||||
}
|
||||
|
||||
static boolean assertNotEventQueue() {
|
||||
final boolean isNotEventQueue = isEventQueue();
|
||||
assert isNotEventQueue : "Threading violation: EventQueue thread";
|
||||
return isNotEventQueue;
|
||||
}
|
||||
|
||||
static boolean assertAppKit() {
|
||||
final boolean isAppKitThread = isAppKit();
|
||||
assert isAppKitThread : "Threading violation: not AppKit thread";
|
||||
return isAppKitThread;
|
||||
}
|
||||
|
||||
static boolean assertNotAppKit() {
|
||||
final boolean isNotAppKitThread = !isAppKit();
|
||||
assert isNotAppKitThread : "Threading violation: AppKit thread";
|
||||
return isNotAppKitThread;
|
||||
}
|
||||
|
||||
public static <V> V executeOnAppKit(final Callable<V> command) throws Throwable {
|
||||
if (!isAppKit()) {
|
||||
Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (dispatch == null) {
|
||||
throw new AWTError("Could not get Dispatch object");
|
||||
}
|
||||
|
||||
Callable<V> commandWithTNameFix = () -> {
|
||||
if (!APPKIT_THREAD_NAME.equals(Thread.currentThread().getName())) {
|
||||
Thread.currentThread().setName(APPKIT_THREAD_NAME);
|
||||
}
|
||||
|
||||
return command.call();
|
||||
};
|
||||
|
||||
FutureTask<V> future = new FutureTask<>(commandWithTNameFix);
|
||||
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(future);
|
||||
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new AWTError(e.getMessage());
|
||||
} catch (ExecutionException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
} else
|
||||
return command.call();
|
||||
}
|
||||
|
||||
public static <V> V privilegedExecuteOnAppKit(Callable<V> command)
|
||||
throws Exception {
|
||||
try {
|
||||
return java.security.AccessController.doPrivileged(
|
||||
(PrivilegedExceptionAction<V>) () -> {
|
||||
//noinspection TryWithIdenticalCatches
|
||||
try {
|
||||
return executeOnAppKit(command);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
throw e;
|
||||
} catch (Throwable throwable) {
|
||||
throw new Exception(throwable);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeOnAppKit(Runnable command) {
|
||||
if (!isAppKit()) {
|
||||
Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (dispatch != null) {
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(command);
|
||||
}
|
||||
else {
|
||||
throw new AWTError("Could not get Dispatch object");
|
||||
}
|
||||
} else
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
@@ -85,27 +85,15 @@ import java.awt.peer.TaskbarPeer;
|
||||
import java.awt.peer.TrayIconPeer;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.net.MalformedURLException;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.apple.laf.AquaMenuBarUI;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.awt.LightweightFrame;
|
||||
import sun.awt.PlatformGraphicsInfo;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.*;
|
||||
import sun.awt.datatransfer.DataTransferer;
|
||||
import sun.awt.dnd.SunDragSourceContextPeer;
|
||||
import sun.awt.util.ThreadGroupUtils;
|
||||
@@ -494,9 +482,9 @@ public final class LWCToolkit extends LWToolkit {
|
||||
public Insets getScreenInsets(final GraphicsConfiguration gc) {
|
||||
GraphicsDevice gd = gc.getDevice();
|
||||
if (!(gd instanceof CGraphicsDevice)) {
|
||||
return super.getScreenInsets(gc);
|
||||
return InvokeOnToolkitHelper.invokeAndBlock(() -> super.getScreenInsets(gc));
|
||||
}
|
||||
return ((CGraphicsDevice)gd).getScreenInsets();
|
||||
return InvokeOnToolkitHelper.invokeAndBlock(() -> ((CGraphicsDevice)gd).getScreenInsets());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -725,12 +713,19 @@ public final class LWCToolkit extends LWToolkit {
|
||||
},
|
||||
true);
|
||||
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
SunToolkit.postEvent(appContext, invocationEvent);
|
||||
// 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock
|
||||
SunToolkit.flushPendingEvents(appContext);
|
||||
doAWTRunLoop(mediator, false);
|
||||
if (!InvokeOnToolkitHelper.offer(invocationEvent)) {
|
||||
if (component != null) {
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
SunToolkit.postEvent(appContext, invocationEvent);
|
||||
|
||||
// 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock
|
||||
SunToolkit.flushPendingEvents(appContext);
|
||||
} else {
|
||||
// This should be the equivalent to EventQueue.invokeAndWait
|
||||
((LWCToolkit) Toolkit.getDefaultToolkit()).getSystemEventQueueImpl().postEvent(invocationEvent);
|
||||
}
|
||||
}
|
||||
doAWTRunLoop(mediator, false);
|
||||
checkException(invocationEvent);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Factory for {@link Executor}s and {@link ExecutorService}s backed by
|
||||
* libdispatch.
|
||||
*
|
||||
* Access is controlled through the Dispatch.getInstance() method, because
|
||||
* performed tasks occur on threads owned by libdispatch. These threads are
|
||||
* not owned by any particular AppContext or have any specific context
|
||||
* classloader installed.
|
||||
*
|
||||
* @since Java for Mac OS X 10.6 Update 2
|
||||
*/
|
||||
public final class Dispatch {
|
||||
/**
|
||||
* The priorities of the three default asynchronous queues.
|
||||
*/
|
||||
public enum Priority {
|
||||
LOW(-2), NORMAL(0), HIGH(2); // values from <dispatch/queue.h>
|
||||
|
||||
final int nativePriority;
|
||||
Priority(final int nativePriority) { this.nativePriority = nativePriority; }
|
||||
};
|
||||
|
||||
final static Dispatch instance = new Dispatch();
|
||||
|
||||
/**
|
||||
* Factory method returns an instnace of Dispatch if supported by the
|
||||
* underlying operating system, and if the caller's security manager
|
||||
* permits "canInvokeInSystemThreadGroup".
|
||||
*
|
||||
* @return a factory instance of Dispatch, or null if not available
|
||||
*/
|
||||
public static Dispatch getInstance() {
|
||||
checkSecurity();
|
||||
if (!LibDispatchNative.nativeIsDispatchSupported()) return null;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void checkSecurity() {
|
||||
final SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) security.checkPermission(new RuntimePermission("canInvokeInSystemThreadGroup"));
|
||||
}
|
||||
|
||||
private Dispatch() { }
|
||||
|
||||
/**
|
||||
* Creates an {@link Executor} that performs tasks asynchronously. The {@link Executor}
|
||||
* cannot be shutdown, and enqueued {@link Runnable}s cannot be canceled. Passing null
|
||||
* returns the {@link Priority.NORMAL} {@link Executor}.
|
||||
*
|
||||
* @param priority - the priority of the returned {@link Executor}
|
||||
* @return an asynchronous {@link Executor}
|
||||
*/
|
||||
public Executor getAsyncExecutor(Priority priority) {
|
||||
if (priority == null) priority = Priority.NORMAL;
|
||||
final long nativeQueue = LibDispatchNative.nativeCreateConcurrentQueue(priority.nativePriority);
|
||||
if (nativeQueue == 0L) return null;
|
||||
return new LibDispatchConcurrentQueue(nativeQueue);
|
||||
}
|
||||
|
||||
int queueIndex = 0;
|
||||
/**
|
||||
* Creates an {@link ExecutorService} that performs tasks synchronously in FIFO order.
|
||||
* Useful to protect a resource against concurrent modification, in lieu of a lock.
|
||||
* Passing null returns an {@link ExecutorService} with a uniquely labeled queue.
|
||||
*
|
||||
* @param label - a label to name the queue, shown in several debugging tools
|
||||
* @return a synchronous {@link ExecutorService}
|
||||
*/
|
||||
public ExecutorService createSerialExecutor(String label) {
|
||||
if (label == null) label = "";
|
||||
if (label.length() > 256) label = label.substring(0, 256);
|
||||
String queueName = "com.apple.java.concurrent.";
|
||||
if ("".equals(label)) {
|
||||
synchronized (this) {
|
||||
queueName += queueIndex++;
|
||||
}
|
||||
} else {
|
||||
queueName += label;
|
||||
}
|
||||
|
||||
final long nativeQueue = LibDispatchNative.nativeCreateSerialQueue(queueName);
|
||||
if (nativeQueue == 0) return null;
|
||||
return new LibDispatchSerialQueue(nativeQueue);
|
||||
}
|
||||
|
||||
Executor nonBlockingMainQueue = null;
|
||||
/**
|
||||
* Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
|
||||
* Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
|
||||
*
|
||||
* Submitting a Runnable to this {@link Executor} does not wait for the Runnable to complete.
|
||||
* @return an asynchronous {@link Executor} that is backed by the main queue
|
||||
*/
|
||||
public synchronized Executor getNonBlockingMainQueueExecutor() {
|
||||
if (nonBlockingMainQueue != null) return nonBlockingMainQueue;
|
||||
return nonBlockingMainQueue = new LibDispatchMainQueue.ASync();
|
||||
}
|
||||
|
||||
Executor blockingMainQueue = null;
|
||||
/**
|
||||
* Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
|
||||
* Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
|
||||
*
|
||||
* Submitting a Runnable to this {@link Executor} will block until the Runnable has completed.
|
||||
* @return an {@link Executor} that is backed by the main queue
|
||||
*/
|
||||
public synchronized Executor getBlockingMainQueueExecutor() {
|
||||
if (blockingMainQueue != null) return blockingMainQueue;
|
||||
return blockingMainQueue = new LibDispatchMainQueue.Sync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
class LibDispatchConcurrentQueue extends LibDispatchQueue implements Executor {
|
||||
LibDispatchConcurrentQueue(final long queuePtr) {
|
||||
super(queuePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteAsync(ptr, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void dispose() {
|
||||
// should not dispose the default concurrent queues
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
abstract class LibDispatchMainQueue extends LibDispatchQueue implements Executor {
|
||||
public LibDispatchMainQueue() {
|
||||
super(LibDispatchNative.nativeGetMainQueue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void dispose() {
|
||||
// should not dispose the main queue
|
||||
}
|
||||
|
||||
static class Sync extends LibDispatchMainQueue {
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteSync(ptr, task);
|
||||
}
|
||||
}
|
||||
|
||||
static class ASync extends LibDispatchMainQueue {
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteAsync(ptr, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
final class LibDispatchNative {
|
||||
static {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("osx");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static native boolean nativeIsDispatchSupported();
|
||||
static native long nativeGetMainQueue();
|
||||
static native long nativeCreateConcurrentQueue(int priority);
|
||||
static native long nativeCreateSerialQueue(String name);
|
||||
static native void nativeReleaseQueue(long nativeQueue);
|
||||
static native void nativeExecuteAsync(long nativeQueue, Runnable task);
|
||||
static native void nativeExecuteSync(long nativeQueue, Runnable task);
|
||||
|
||||
private LibDispatchNative() { }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
class LibDispatchQueue extends LibDispatchRetainedResource {
|
||||
LibDispatchQueue(final long queuePtr) {
|
||||
super(queuePtr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
class LibDispatchRetainedResource {
|
||||
protected long ptr;
|
||||
|
||||
protected LibDispatchRetainedResource(final long ptr) {
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
protected synchronized void dispose() {
|
||||
if (ptr != 0) LibDispatchNative.nativeReleaseQueue(ptr);
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 sun.lwawt.macosx.concurrent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class LibDispatchSerialQueue extends AbstractExecutorService {
|
||||
static final int RUNNING = 0;
|
||||
static final int SHUTDOWN = 1;
|
||||
// static final int STOP = 2; // not supported by GCD
|
||||
static final int TERMINATED = 3;
|
||||
|
||||
final Object lock = new Object();
|
||||
LibDispatchQueue nativeQueueWrapper;
|
||||
volatile int runState;
|
||||
|
||||
LibDispatchSerialQueue(final long queuePtr) {
|
||||
nativeQueueWrapper = new LibDispatchQueue(queuePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
if (nativeQueueWrapper == null) return;
|
||||
LibDispatchNative.nativeExecuteAsync(nativeQueueWrapper.ptr, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return runState != RUNNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return runState == TERMINATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
synchronized (lock) {
|
||||
if (runState != RUNNING) return;
|
||||
|
||||
runState = SHUTDOWN;
|
||||
execute(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (lock) {
|
||||
runState = TERMINATED;
|
||||
lock.notifyAll(); // for the benefit of awaitTermination()
|
||||
}
|
||||
}
|
||||
});
|
||||
nativeQueueWrapper = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
shutdown();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
|
||||
if (runState == TERMINATED) return true;
|
||||
|
||||
final long millis = unit.toMillis(timeout);
|
||||
if (millis <= 0) return false;
|
||||
|
||||
synchronized (lock) {
|
||||
if (runState == TERMINATED) return true;
|
||||
lock.wait(timeout);
|
||||
if (runState == TERMINATED) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -219,10 +219,19 @@ static BOOL shouldUsePressAndHold() {
|
||||
NSPoint localPoint = [self convertPoint: eventLocation fromView: nil];
|
||||
|
||||
if ([self mouse: localPoint inRect: [self bounds]]) {
|
||||
[self deliverJavaMouseEvent: event];
|
||||
} else {
|
||||
[[self nextResponder] mouseDown:event];
|
||||
NSWindow* eventWindow = [event window];
|
||||
NSPoint screenPoint = (eventWindow == nil)
|
||||
? eventLocation
|
||||
// SDK we build against is too old - it doesn't have convertPointToScreen
|
||||
: [eventWindow convertRectToScreen:NSMakeRect(eventLocation.x, eventLocation.y, 0, 0)].origin;
|
||||
// macOS can report mouseMoved events to a window even if it's not showing currently (see JBR-2702)
|
||||
// so we're performing an additional check here
|
||||
if (self.window.windowNumber == [NSWindow windowNumberAtPoint:screenPoint belowWindowWithWindowNumber:0]) {
|
||||
[self deliverJavaMouseEvent: event];
|
||||
return;
|
||||
}
|
||||
}
|
||||
[[self nextResponder] mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void) mouseDragged: (NSEvent *)event {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user