mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-15 22:09:41 +01:00
Compare commits
121 Commits
jb17.0.8-b
...
jb15_0_1-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1cea2ff04 | ||
|
|
ba02769ca6 | ||
|
|
8c8144a7c1 | ||
|
|
6a30c56138 | ||
|
|
93ad4f06dd | ||
|
|
d3018a1837 | ||
|
|
2bf43a57ab | ||
|
|
6769b27e53 | ||
|
|
e43cfd198f | ||
|
|
6e1c514c6c | ||
|
|
e2637199e9 | ||
|
|
47ff31ae82 | ||
|
|
a5e25d1ef9 | ||
|
|
eea293f4a4 | ||
|
|
e0475e9ba2 | ||
|
|
087ff34c2e | ||
|
|
0db7e948af | ||
|
|
b871188f44 | ||
|
|
51ce1d6427 | ||
|
|
7fb31a1665 | ||
|
|
e6752600a5 | ||
|
|
a5bd092449 | ||
|
|
b16ee45915 | ||
|
|
8c9402b60b | ||
|
|
2c0d6150d0 | ||
|
|
f309844f75 | ||
|
|
d45cab03b1 | ||
|
|
e33577c3a5 | ||
|
|
32e9c4d353 | ||
|
|
44d62b3234 | ||
|
|
0f0ab2c5ba | ||
|
|
1a807593ab | ||
|
|
241c14cb92 | ||
|
|
601064c09c | ||
|
|
2120a8a282 | ||
|
|
36ef23fb81 | ||
|
|
2afd3d4821 | ||
|
|
4b8e82db67 | ||
|
|
90d22980d5 | ||
|
|
0d1778962d | ||
|
|
276a53ba14 | ||
|
|
b483235e7f | ||
|
|
bc6ff706da | ||
|
|
27ffa822c1 | ||
|
|
9174496aa0 | ||
|
|
d7d16faf16 | ||
|
|
653e7a8101 | ||
|
|
fcb22de8b0 | ||
|
|
af0e3f69fa | ||
|
|
cd74581779 | ||
|
|
74ce667016 | ||
|
|
161a7eac4a | ||
|
|
54a2e76122 | ||
|
|
be4219caab | ||
|
|
4a3199dc9d | ||
|
|
b63b0ae668 | ||
|
|
7a084221ca | ||
|
|
4165ef6306 | ||
|
|
14b7c5adef | ||
|
|
71fa983bc1 | ||
|
|
8a2f49d98b | ||
|
|
c971c7fa88 | ||
|
|
b9996c7b47 | ||
|
|
f160303ec9 | ||
|
|
307d1c1fd7 | ||
|
|
25302b9289 | ||
|
|
1759eb2b89 | ||
|
|
d27d2e2baa | ||
|
|
c13fd2cb3e | ||
|
|
c1624ddd8d | ||
|
|
65affdb4f7 | ||
|
|
08f6a61016 | ||
|
|
edf629d075 | ||
|
|
d8d095563e | ||
|
|
486f078759 | ||
|
|
9b087fe5da | ||
|
|
bd606c0383 | ||
|
|
d05263d08c | ||
|
|
5629899859 | ||
|
|
d3107db64d | ||
|
|
e2901b99db | ||
|
|
d7723b6110 | ||
|
|
483e5158be | ||
|
|
5f3c9c11ba | ||
|
|
fd6e0efbd5 | ||
|
|
fbd999542a | ||
|
|
5a252a96f1 | ||
|
|
1b9c3ed57b | ||
|
|
8b32d4cc6f | ||
|
|
54152197f5 | ||
|
|
2588bb7a92 | ||
|
|
fb6a542b84 | ||
|
|
4606f42a4b | ||
|
|
6e29b5cd43 | ||
|
|
6c12492aef | ||
|
|
4ead63ebbe | ||
|
|
6934ca4826 | ||
|
|
f6b4e4d52d | ||
|
|
c49a889919 | ||
|
|
1ff8b4b6df | ||
|
|
748f55a971 | ||
|
|
3c594007b5 | ||
|
|
19482e0c9f | ||
|
|
c17f1e9ffe | ||
|
|
e6cae2dd1a | ||
|
|
8373d64d08 | ||
|
|
433d7d4681 | ||
|
|
9d03be4e29 | ||
|
|
0348537300 | ||
|
|
cd285c9022 | ||
|
|
4dcff472fa | ||
|
|
0b6cba009c | ||
|
|
fbb2e417c9 | ||
|
|
c866c331cd | ||
|
|
4c78467a0d | ||
|
|
6b0ad1c96f | ||
|
|
acb92a2a1a | ||
|
|
aea97028fb | ||
|
|
d6404cf65e | ||
|
|
20a26347e4 | ||
|
|
397f951cd2 |
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"
|
||||
10
jb/project/docker/x86/Dockerfile
Normal file
10
jb/project/docker/x86/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM i386/ubuntu:xenial
|
||||
|
||||
RUN linux32 apt-get update && apt-get install -y --no-install-recommends apt-utils
|
||||
RUN linux32 apt-get -y install file build-essential zip unzip tar wget curl libx11-dev libxext-dev \
|
||||
libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libasound2-data \
|
||||
libpng12-0 libasound2 libfreetype6 libfontconfig1-dev libasound2-dev autoconf git
|
||||
# Install Java 15
|
||||
RUN wget https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_i686.tar.gz \
|
||||
-O - | tar xz -C /
|
||||
RUN mv /zulu15.27.17-ca-jdk15.0.0-linux_i686 /jdk15.0.0
|
||||
49
jb/project/tools/common/scripts/common.sh
Normal file
49
jb/project/tools/common/scripts/common.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
VENDOR_NAME="JetBrains s.r.o."
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}"
|
||||
[ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}"
|
||||
|
||||
do_reset_changes=0
|
||||
function do_exit() {
|
||||
exit_code=$1
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
function update_jsdk_mods() {
|
||||
__jsdk=$1
|
||||
__jcef_mods=$2
|
||||
__orig_jsdk_mods=$3
|
||||
__updated_jsdk_mods=$4
|
||||
|
||||
# re-create java.desktop.jmod with updated module-info.class
|
||||
tmp=.java.desktop.$$.tmp
|
||||
mkdir "$tmp" || exit $?
|
||||
"$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.desktop.jmod || exit $?
|
||||
"$__jsdk"/bin/javac \
|
||||
--patch-module java.desktop="$__orig_jsdk_mods"/java.desktop.jmod \
|
||||
--module-path "$__jcef_mods" -d "$tmp"/classes src/java.desktop/share/classes/module-info.java || exit $?
|
||||
"$__jsdk"/bin/jmod \
|
||||
create --class-path "$tmp"/classes --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \
|
||||
java.desktop.jmod || exit $?
|
||||
mv java.desktop.jmod "$__updated_jsdk_mods" || exit $?
|
||||
rm -rf "$tmp"
|
||||
|
||||
# re-create java.base.jmod with updated hashes
|
||||
tmp=.java.base.$$.tmp
|
||||
mkdir "$tmp" || exit $?
|
||||
hash_modules=$("$JSDK"/bin/jmod describe "$__orig_jsdk_mods"/java.base.jmod | grep hashes | awk '{print $2}' | tr '\n' '|' | sed s/\|$//) || exit $?
|
||||
"$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.base.jmod || exit $?
|
||||
rm "$__updated_jsdk_mods"/java.base.jmod || exit $? # temp exclude from path
|
||||
"$__jsdk"/bin/jmod \
|
||||
create --module-path "$__updated_jsdk_mods" --hash-modules "$hash_modules" \
|
||||
--class-path "$tmp"/classes --cmds "$tmp"/bin --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \
|
||||
java.base.jmod || exit $?
|
||||
mv java.base.jmod "$__updated_jsdk_mods" || exit $?
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
function get_mods_list() {
|
||||
__mods=$1
|
||||
|
||||
return `ls "$__mods"` | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g
|
||||
}
|
||||
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 $?
|
||||
125
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
125
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/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"
|
||||
|
||||
# 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
|
||||
;;
|
||||
"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" == "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" == "fd" ]; 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>
|
||||
126
jb/project/tools/mac/scripts/mkimages.sh
Executable file
126
jb/project/tools/mac/scripts/mkimages.sh
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/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
|
||||
__modules_path=$2
|
||||
__modules=$3
|
||||
|
||||
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/$__bundle_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 $?
|
||||
|
||||
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
|
||||
cp "$JSDK"/../Info.plist "$JRE_CONTENTS"
|
||||
[ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?)
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__bundle_name" || do_exit $?
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=macosx-x86_64-server-release
|
||||
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
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" == "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}" $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" == "fd" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_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;
|
||||
5066
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
5066
jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
From 095315ce3f66bcf14ae1d06d84bbeb24bb068ae8 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:18:22 +0100
|
||||
Subject: [PATCH 02/48] We need to set classRedefinitionCount on new class, not
|
||||
old class.
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 83c0952de37..83cf0be090b 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1904,7 +1904,7 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
oop class_mirror = ik->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
- java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
|
||||
+ java_lang_Class::set_classRedefinedCount(ik->new_version()->java_mirror(), new_count);
|
||||
|
||||
if (class_oop != _the_class_oop) {
|
||||
// _the_class_oop count is printed at end of redefine_single_class()
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
From 9ddbbcdc73e653af7807ead68705c1c9267c9192 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:22:01 +0100
|
||||
Subject: [PATCH 03/48] Fix crashes in MetadataOnStackMark::~MetadataOnSta
|
||||
|
||||
MetadataOnStackMark shoukld not remove dcevm stuff. It was added
|
||||
accidentaly in dcevm9,
|
||||
and never was part of doit() in previous versions.
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 83cf0be090b..61af07d0f86 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -470,7 +470,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
|
||||
// Mark methods seen on stack and everywhere else so old methods are not
|
||||
// cleaned up if they're on the stack.
|
||||
- MetadataOnStackMark md_on_stack(true);
|
||||
+
|
||||
+ // FIXME: fails in enhanced redefinition
|
||||
+ // MetadataOnStackMark md_on_stack(true);
|
||||
HandleMark hm(thread); // make sure any handles created are deleted
|
||||
// before the stack walk again.
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From bb3eb4931818c3ef43c48d0781d73b8e2eb6dea9 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 3 Dec 2018 19:34:53 +0100
|
||||
Subject: [PATCH 04/48] Fix problem with nested members
|
||||
|
||||
Reported at : https://stackoverflow.com/questions/53370380/hotswapagent-incompatibleclasschangeerror-type-headerpanel1-is-not-a-nest-mem
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 8a262bc3735..9b6ba7e9304 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -178,6 +178,7 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
|
||||
}
|
||||
|
||||
Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
|
||||
+ k2 = k2->newest_version();
|
||||
if (k2 == k) {
|
||||
log_trace(class, nestmates)("- class is listed as a nest member");
|
||||
return true;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
26
jb/project/tools/patches/dcevm/0005-Use-init_mark_raw.patch
Normal file
26
jb/project/tools/patches/dcevm/0005-Use-init_mark_raw.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 90746a0267b2de4063667f5423093115f814bf08 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 10 Dec 2018 20:12:07 +0100
|
||||
Subject: [PATCH 05/48] Use init_mark_raw()
|
||||
|
||||
method changed since j8 - it used init_mark()
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 4394eff00c5..75d7e685edf 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -371,7 +371,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
} else {
|
||||
MarkSweep::update_fields(oop(cur_obj), oop(compaction_top));
|
||||
}
|
||||
- oop(compaction_top)->init_mark();
|
||||
+ oop(compaction_top)->init_mark_raw();
|
||||
assert(oop(compaction_top)->klass() != NULL, "should have a class");
|
||||
|
||||
debug_only(prev_obj = cur_obj);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
25
jb/project/tools/patches/dcevm/0006-Fix-methodHandles.patch
Normal file
25
jb/project/tools/patches/dcevm/0006-Fix-methodHandles.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 026346bfb72eaaae53e8998900d9f520da5ef74d Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 13 Dec 2018 20:51:09 +0100
|
||||
Subject: [PATCH 06/48] Fix methodHandles
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 61af07d0f86..1c7595787a1 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -248,7 +248,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
|
||||
if (MethodHandles::ref_kind_is_method(ref_kind)) {
|
||||
Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj);
|
||||
- if (m != NULL && m->method_holder()->new_version() != NULL) {
|
||||
+ if (m != NULL && m->method_holder()->is_redefining()) {
|
||||
// Let's try to re-resolve method
|
||||
InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version());
|
||||
Method* new_method = newest->find_method(m->name(), m->signature());
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
58
jb/project/tools/patches/dcevm/0007-Fix-field-method.patch
Normal file
58
jb/project/tools/patches/dcevm/0007-Fix-field-method.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From b99ebb71bce6119cd800d69848f84281f2fd2b16 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 15 Dec 2018 18:23:30 +0100
|
||||
Subject: [PATCH 07/48] Fix field method
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 19 ++++++++++++-------
|
||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 1c7595787a1..a3b65b273e5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -264,21 +264,26 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
}
|
||||
}
|
||||
} else if (MethodHandles::ref_kind_is_field(ref_kind)) {
|
||||
- Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj);
|
||||
+ oop clazz = java_lang_invoke_MemberName::clazz(obj);
|
||||
+ if (clazz == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
if (k == NULL) {
|
||||
return false; // Was cleared before, this MemberName is invalid.
|
||||
}
|
||||
|
||||
- if (k != NULL && k->new_version() != NULL) {
|
||||
+ if (k->is_redefining()) {
|
||||
// Let's try to re-resolve field
|
||||
+ InstanceKlass* old = InstanceKlass::cast(k->old_version());
|
||||
fieldDescriptor fd;
|
||||
int offset = java_lang_invoke_MemberName::vmindex(obj);
|
||||
bool is_static = MethodHandles::ref_kind_is_static(ref_kind);
|
||||
- InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
- if (ik->find_local_field_from_offset(offset, is_static, &fd)) {
|
||||
- InstanceKlass* newest = InstanceKlass::cast(k->newest_version());
|
||||
+ InstanceKlass* ik_old = InstanceKlass::cast(old);
|
||||
+ if (ik_old->find_local_field_from_offset(offset, is_static, &fd)) {
|
||||
+ InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version());
|
||||
fieldDescriptor fd_new;
|
||||
- if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
+ if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
Handle objHandle(Thread::current(), obj); // TODO : review thread
|
||||
MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind));
|
||||
} else {
|
||||
@@ -288,7 +293,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// Eventually, we probably want to replace them with something more meaningful,
|
||||
// like instance throwing NoSuchFieldError or DMH that will resort to dynamic
|
||||
// field resolution (with possibility of type conversion)
|
||||
- java_lang_invoke_MemberName::set_method(obj, NULL);
|
||||
+ java_lang_invoke_MemberName::set_clazz(obj, NULL);
|
||||
java_lang_invoke_MemberName::set_vmindex(obj, 0);
|
||||
return false;
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From dd57a1b40a83f7691c0fb9aa960f77c4428c0eec Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 15 Dec 2018 20:16:37 +0100
|
||||
Subject: [PATCH 08/48] Fix nonstatic field handles
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a3b65b273e5..c64d6bb1bb5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -337,6 +337,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (obj == NULL) {
|
||||
return;
|
||||
}
|
||||
+ bool oop_updated = false;
|
||||
if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) {
|
||||
Klass* klass = java_lang_Class::as_Klass(obj);
|
||||
if (klass != NULL && klass->is_instance_klass()) {
|
||||
@@ -344,13 +345,17 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (klass->new_version() != NULL) {
|
||||
obj = InstanceKlass::cast(klass->new_version())->java_mirror();
|
||||
S::oop_store(p, obj);
|
||||
+ oop_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
// JSR 292 support, uptade java.lang.invoke.MemberName instances
|
||||
if (java_lang_invoke_MemberName::is_instance(obj)) {
|
||||
- update_member_name(obj);
|
||||
+ if (oop_updated) {
|
||||
+ update_member_name(obj);
|
||||
+ }
|
||||
} else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) {
|
||||
if (!update_direct_method_handle(obj)) {
|
||||
// DMH is no longer valid, replace it with null reference.
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
From 333c0c639e12296d05a547b015c948516c8c504e Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 12 Dec 2018 19:38:28 +0100
|
||||
Subject: [PATCH 09/48] Support for Concurrent Mark Sweep (CMS) collector
|
||||
|
||||
---
|
||||
.../share/gc/cms/compactibleFreeListSpace.cpp | 139 ++++++++++++------
|
||||
.../share/gc/cms/compactibleFreeListSpace.hpp | 5 +-
|
||||
.../gc/cms/concurrentMarkSweepThread.cpp | 10 +-
|
||||
src/hotspot/share/gc/serial/markSweep.cpp | 2 +-
|
||||
src/hotspot/share/gc/shared/gcConfig.cpp | 2 +-
|
||||
src/hotspot/share/gc/shared/space.cpp | 16 +-
|
||||
src/hotspot/share/gc/shared/space.hpp | 6 +-
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 16 +-
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 12 +-
|
||||
src/hotspot/share/runtime/arguments.cpp | 6 +-
|
||||
10 files changed, 135 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
index a93f764f1b9..efaa09473a9 100644
|
||||
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp
|
||||
@@ -376,55 +376,58 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, M
|
||||
_used_stable = 0;
|
||||
}
|
||||
|
||||
+#define forward_compact_top_DEFN() \
|
||||
+ assert(this == cp->space, "'this' should be current compaction space."); \
|
||||
+ size_t compaction_max_size = pointer_delta(end(), compact_top); \
|
||||
+ assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), \
|
||||
+ "virtual adjustObjectSize_v() method is not correct"); \
|
||||
+ size_t adjusted_size = adjustObjectSize(size); \
|
||||
+ assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, \
|
||||
+ "no small fragments allowed"); \
|
||||
+ assert(minimum_free_block_size() == MinChunkSize, \
|
||||
+ "for de-virtualized reference below"); \
|
||||
+ /* Can't leave a nonzero size, residual fragment smaller than MinChunkSize */ \
|
||||
+ if (adjusted_size + MinChunkSize > compaction_max_size && \
|
||||
+ adjusted_size != compaction_max_size) { \
|
||||
+ do { \
|
||||
+ /* switch to next compaction space*/ \
|
||||
+ cp->space->set_compaction_top(compact_top); \
|
||||
+ cp->space = cp->space->next_compaction_space(); \
|
||||
+ if (cp->space == NULL) { \
|
||||
+ cp->gen = CMSHeap::heap()->young_gen(); \
|
||||
+ assert(cp->gen != NULL, "compaction must succeed"); \
|
||||
+ cp->space = cp->gen->first_compaction_space(); \
|
||||
+ assert(cp->space != NULL, "generation must have a first compaction space"); \
|
||||
+ } \
|
||||
+ compact_top = cp->space->bottom(); \
|
||||
+ cp->space->set_compaction_top(compact_top); \
|
||||
+ /* The correct adjusted_size may not be the same as that for this method */ \
|
||||
+ /* (i.e., cp->space may no longer be "this" so adjust the size again. */ \
|
||||
+ /* Use the virtual method which is not used above to save the virtual */ \
|
||||
+ /* dispatch. */ \
|
||||
+ adjusted_size = cp->space->adjust_object_size_v(size); \
|
||||
+ compaction_max_size = pointer_delta(cp->space->end(), compact_top); \
|
||||
+ assert(cp->space->minimum_free_block_size() == 0, "just checking"); \
|
||||
+ } while (adjusted_size > compaction_max_size); \
|
||||
+ }
|
||||
+
|
||||
+
|
||||
HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size,
|
||||
CompactPoint* cp, HeapWord* compact_top) {
|
||||
- ShouldNotReachHere();
|
||||
- return NULL;
|
||||
+ forward_compact_top_DEFN()
|
||||
+ return compact_top;
|
||||
}
|
||||
|
||||
// Like CompactibleSpace forward() but always calls cross_threshold() to
|
||||
// update the block offset table. Removed initialize_threshold call because
|
||||
// CFLS does not use a block offset array for contiguous spaces.
|
||||
HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
- // q is alive
|
||||
- // First check if we should switch compaction space
|
||||
- assert(this == cp->space, "'this' should be current compaction space.");
|
||||
- size_t compaction_max_size = pointer_delta(end(), compact_top);
|
||||
- assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size),
|
||||
- "virtual adjustObjectSize_v() method is not correct");
|
||||
- size_t adjusted_size = adjustObjectSize(size);
|
||||
- assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0,
|
||||
- "no small fragments allowed");
|
||||
- assert(minimum_free_block_size() == MinChunkSize,
|
||||
- "for de-virtualized reference below");
|
||||
- // Can't leave a nonzero size, residual fragment smaller than MinChunkSize
|
||||
- if (adjusted_size + MinChunkSize > compaction_max_size &&
|
||||
- adjusted_size != compaction_max_size) {
|
||||
- do {
|
||||
- // switch to next compaction space
|
||||
- cp->space->set_compaction_top(compact_top);
|
||||
- cp->space = cp->space->next_compaction_space();
|
||||
- if (cp->space == NULL) {
|
||||
- cp->gen = CMSHeap::heap()->young_gen();
|
||||
- assert(cp->gen != NULL, "compaction must succeed");
|
||||
- cp->space = cp->gen->first_compaction_space();
|
||||
- assert(cp->space != NULL, "generation must have a first compaction space");
|
||||
- }
|
||||
- compact_top = cp->space->bottom();
|
||||
- cp->space->set_compaction_top(compact_top);
|
||||
- // The correct adjusted_size may not be the same as that for this method
|
||||
- // (i.e., cp->space may no longer be "this" so adjust the size again.
|
||||
- // Use the virtual method which is not used above to save the virtual
|
||||
- // dispatch.
|
||||
- adjusted_size = cp->space->adjust_object_size_v(size);
|
||||
- compaction_max_size = pointer_delta(cp->space->end(), compact_top);
|
||||
- assert(cp->space->minimum_free_block_size() == 0, "just checking");
|
||||
- } while (adjusted_size > compaction_max_size);
|
||||
- }
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
+ forward_compact_top_DEFN()
|
||||
|
||||
// store the forwarding pointer into the mark word
|
||||
- if ((HeapWord*)q != compact_top) {
|
||||
+ // the size of object changed for: new_version() != NULL
|
||||
+ if (force_forward || (HeapWord*)q != compact_top || q->klass()->new_version() != NULL) {
|
||||
q->forward_to(oop(compact_top));
|
||||
assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
|
||||
} else {
|
||||
@@ -2196,13 +2199,60 @@ CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
|
||||
|
||||
// Support for compaction
|
||||
void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
|
||||
- scan_and_forward(this, cp, false);
|
||||
- // of the free lists doesn't work after.
|
||||
+ if (!Universe::is_redefining_gc_run()) {
|
||||
+ scan_and_forward(this, cp, false);
|
||||
+ } else {
|
||||
+ // Redefinition run
|
||||
+ scan_and_forward(this, cp, true);
|
||||
+ }
|
||||
// Prepare_for_compaction() uses the space between live objects
|
||||
// so that later phase can skip dead space quickly. So verification
|
||||
// of the free lists doesn't work after.
|
||||
}
|
||||
|
||||
+bool CompactibleFreeListSpace::must_rescue(oop old_obj, oop new_obj) {
|
||||
+ // Only redefined objects can have the need to be rescued.
|
||||
+ if (oop(old_obj)->klass()->new_version() == NULL) return false;
|
||||
+
|
||||
+ int new_size = adjustObjectSize(old_obj->size_given_klass(oop(old_obj)->klass()->new_version()));
|
||||
+ int original_size = adjustObjectSize(old_obj->size());
|
||||
+
|
||||
+ Generation* tenured_gen = CMSHeap::heap()->old_gen();
|
||||
+ bool old_in_tenured = tenured_gen->is_in_reserved(old_obj);
|
||||
+ bool new_in_tenured = tenured_gen->is_in_reserved(new_obj);
|
||||
+ if (old_in_tenured == new_in_tenured) {
|
||||
+ // Rescue if object may overlap with a higher memory address.
|
||||
+ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size);
|
||||
+ if (old_in_tenured) {
|
||||
+ // Old and new address are in same space, so just compare the address.
|
||||
+ // Must rescue if object moves towards the top of the space.
|
||||
+ assert(space_index(old_obj) == space_index(new_obj), "old_obj and new_obj must be in same space");
|
||||
+ } else {
|
||||
+ // In the new generation, eden is located before the from space, so a
|
||||
+ // simple pointer comparison is sufficient.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration");
|
||||
+ assert(overlap == (space_index(old_obj) < space_index(new_obj)), "slow and fast computation must yield same result");
|
||||
+ }
|
||||
+ return overlap;
|
||||
+
|
||||
+ } else {
|
||||
+ assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces");
|
||||
+ if (new_in_tenured) {
|
||||
+ // Must never rescue when moving from the new into the old generation.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
+ assert(space_index(old_obj) > space_index(new_obj), "must be");
|
||||
+ return false;
|
||||
+
|
||||
+ } else /* if (tenured_gen->is_in_reserved(old_obj)) */ {
|
||||
+ // Must always rescue when moving from the old into the new generation.
|
||||
+ assert(CMSHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration");
|
||||
+ assert(space_index(old_obj) < space_index(new_obj), "must be");
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void CompactibleFreeListSpace::adjust_pointers() {
|
||||
// In other versions of adjust_pointers(), a bail out
|
||||
// based on the amount of live data in the generation
|
||||
@@ -2215,7 +2265,12 @@ void CompactibleFreeListSpace::adjust_pointers() {
|
||||
}
|
||||
|
||||
void CompactibleFreeListSpace::compact() {
|
||||
- scan_and_compact(this, false);
|
||||
+ if(!Universe::is_redefining_gc_run()) {
|
||||
+ scan_and_compact(this, false);
|
||||
+ } else {
|
||||
+ // Redefinition run
|
||||
+ scan_and_compact(this, true);
|
||||
+ }
|
||||
}
|
||||
|
||||
// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2]
|
||||
diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
index 9fd2ea58320..d29b81f6fca 100644
|
||||
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp
|
||||
@@ -201,7 +201,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||
// Support for compacting cms
|
||||
HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
|
||||
HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top);
|
||||
- HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top);
|
||||
+ HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top, bool force_forward);
|
||||
|
||||
// Initialization helpers.
|
||||
void initializeIndexedFreeListArray();
|
||||
@@ -576,6 +576,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||
|
||||
// Support for compaction.
|
||||
void prepare_for_compaction(CompactPoint* cp);
|
||||
+
|
||||
+ bool must_rescue(oop old_obj, oop new_obj);
|
||||
+
|
||||
void adjust_pointers();
|
||||
void compact();
|
||||
// Reset the space to reflect the fact that a compaction of the
|
||||
diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
index 3ada5755875..b6e930922d7 100644
|
||||
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp
|
||||
@@ -78,10 +78,12 @@ void ConcurrentMarkSweepThread::run_service() {
|
||||
while (!should_terminate()) {
|
||||
sleepBeforeNextCycle();
|
||||
if (should_terminate()) break;
|
||||
- GCIdMark gc_id_mark;
|
||||
- GCCause::Cause cause = _collector->_full_gc_requested ?
|
||||
- _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
|
||||
- _collector->collect_in_background(cause);
|
||||
+ if (!Universe::is_redefining_gc_run()) {
|
||||
+ GCIdMark gc_id_mark;
|
||||
+ GCCause::Cause cause = _collector->_full_gc_requested ?
|
||||
+ _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
|
||||
+ _collector->collect_in_background(cause);
|
||||
+ }
|
||||
}
|
||||
|
||||
// Check that the state of any protocol for synchronization
|
||||
diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
index d0ff86c8215..b4ed59f020c 100644
|
||||
--- a/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
+++ b/src/hotspot/share/gc/serial/markSweep.cpp
|
||||
@@ -247,7 +247,7 @@ void MarkSweep::copy_rescued_objects_back() {
|
||||
|
||||
FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size);
|
||||
|
||||
- new_obj->init_mark();
|
||||
+ new_obj->init_mark_raw();
|
||||
assert(oopDesc::is_oop(new_obj), "must be a valid oop");
|
||||
}
|
||||
_rescued_oops->clear();
|
||||
diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
index 8aac2b39e1e..39364a64cb2 100644
|
||||
--- a/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp
|
||||
@@ -101,7 +101,7 @@ void GCConfig::fail_if_unsupported_gc_is_selected() {
|
||||
}
|
||||
|
||||
void GCConfig::select_gc_ergonomically() {
|
||||
- if (AllowEnhancedClassRedefinition) {
|
||||
+ if (AllowEnhancedClassRedefinition && !UseConcMarkSweepGC) {
|
||||
// Enhanced class redefinition only supports serial GC at the moment
|
||||
FLAG_SET_ERGO(bool, UseSerialGC, true);
|
||||
} else if (os::is_server_class_machine()) {
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 763abc91a39..947dff8ae0c 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -388,11 +388,11 @@ HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, H
|
||||
}
|
||||
|
||||
HeapWord* CompactibleSpace::forward(oop q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
compact_top = forward_compact_top(size, cp, compact_top);
|
||||
|
||||
// store the forwarding pointer into the mark word
|
||||
- if ((HeapWord*)q != compact_top || (size_t)q->size() != size) {
|
||||
+ if (force_forward || (HeapWord*)q != compact_top || (size_t)q->size() != size) {
|
||||
q->forward_to(oop(compact_top));
|
||||
assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
|
||||
} else {
|
||||
@@ -514,7 +514,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) {
|
||||
|
||||
} else {
|
||||
assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces");
|
||||
- if (tenured_gen->is_in_reserved(new_obj)) {
|
||||
+ if (new_in_tenured) {
|
||||
// Must never rescue when moving from the new into the old generation.
|
||||
assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration");
|
||||
assert(space_index(old_obj) > space_index(new_obj), "must be");
|
||||
@@ -858,14 +858,14 @@ void OffsetTableContigSpace::verify() const {
|
||||
// Compute the forward sizes and leave out objects whose position could
|
||||
// possibly overlap other objects.
|
||||
HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
- CompactPoint* cp, HeapWord* compact_top) {
|
||||
+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) {
|
||||
size_t forward_size = size;
|
||||
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) {
|
||||
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
- assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
forward_size = new_size;
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
return compact_top;
|
||||
}
|
||||
|
||||
- return forward(oop(q), forward_size, cp, compact_top);
|
||||
+ return forward(oop(q), forward_size, cp, compact_top, force_forward);
|
||||
}
|
||||
|
||||
// Compute the forwarding addresses for the objects that need to be rescued.
|
||||
@@ -895,11 +895,11 @@ HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
if (oop(q)->klass()->new_version() != NULL) {
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
- assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
size = new_size;
|
||||
}
|
||||
|
||||
- compact_top = cp->space->forward(oop(q), size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward(oop(q), size, cp, compact_top, true);
|
||||
assert(compact_top <= end(), "must not write over end of space!");
|
||||
}
|
||||
MarkSweep::_rescued_oops->clear();
|
||||
diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp
|
||||
index 8eb5669fb79..901c89d8a30 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.hpp
|
||||
@@ -421,7 +421,7 @@ public:
|
||||
virtual void prepare_for_compaction(CompactPoint* cp) = 0;
|
||||
// MarkSweep support phase3
|
||||
DEBUG_ONLY(int space_index(oop obj));
|
||||
- bool must_rescue(oop old_obj, oop new_obj);
|
||||
+ virtual bool must_rescue(oop old_obj, oop new_obj);
|
||||
HeapWord* rescue(HeapWord* old_obj);
|
||||
virtual void adjust_pointers();
|
||||
// MarkSweep support phase4
|
||||
@@ -452,11 +452,11 @@ public:
|
||||
// function of the then-current compaction space, and updates "cp->threshold
|
||||
// accordingly".
|
||||
virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp,
|
||||
- HeapWord* compact_top);
|
||||
+ HeapWord* compact_top, bool force_forward);
|
||||
// (DCEVM) same as forwad, but can rescue objects. Invoked only during
|
||||
// redefinition runs
|
||||
HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp,
|
||||
- HeapWord* compact_top);
|
||||
+ HeapWord* compact_top, bool force_forward);
|
||||
|
||||
HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top);
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 75d7e685edf..26e56ae6f7e 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -163,6 +163,8 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
HeapWord* cur_obj = space->bottom();
|
||||
HeapWord* scan_limit = space->scan_limit();
|
||||
|
||||
+ bool force_forward = false;
|
||||
+
|
||||
while (cur_obj < scan_limit) {
|
||||
assert(!space->scanned_block_is_obj(cur_obj) ||
|
||||
oop(cur_obj)->mark_raw()->is_marked() || oop(cur_obj)->mark_raw()->is_unlocked() ||
|
||||
@@ -174,14 +176,15 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
size_t size = space->scanned_block_size(cur_obj);
|
||||
|
||||
if (redefinition_run) {
|
||||
- compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top, force_forward);
|
||||
if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) {
|
||||
/* Was moved (otherwise, forward would reset mark),
|
||||
set first_dead to here */
|
||||
first_dead = cur_obj;
|
||||
+ force_forward = true;
|
||||
}
|
||||
} else {
|
||||
- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top);
|
||||
+ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top, false);
|
||||
}
|
||||
|
||||
cur_obj += size;
|
||||
@@ -197,9 +200,9 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
|
||||
// see if we might want to pretend this object is alive so that
|
||||
// we don't have to compact quite as often.
|
||||
- if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) {
|
||||
+ if (!redefinition_run && cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) {
|
||||
oop obj = oop(cur_obj);
|
||||
- compact_top = cp->space->forward(obj, obj->size(), cp, compact_top);
|
||||
+ compact_top = cp->space->forward(obj, obj->size(), cp, compact_top, force_forward);
|
||||
end_of_live = end;
|
||||
} else {
|
||||
// otherwise, it really is a free region.
|
||||
@@ -351,7 +354,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
HeapWord* compaction_top = (HeapWord*)oop(cur_obj)->forwardee();
|
||||
|
||||
if (redefinition_run && space->must_rescue(oop(cur_obj), oop(cur_obj)->forwardee())) {
|
||||
- space->rescue(cur_obj);
|
||||
+ space->rescue(cur_obj);
|
||||
debug_only(Copy::fill_to_words(cur_obj, size, 0));
|
||||
cur_obj += size;
|
||||
continue;
|
||||
@@ -361,8 +364,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti
|
||||
Prefetch::write(compaction_top, copy_interval);
|
||||
|
||||
// copy object and reinit its mark
|
||||
- assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL,
|
||||
- "everything in this pass should be moving");
|
||||
+ assert(redefinition_run || cur_obj != compaction_top, "everything in this pass should be moving");
|
||||
if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) {
|
||||
Klass* new_version = oop(cur_obj)->klass()->new_version();
|
||||
if (new_version->update_information() == NULL) {
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index c64d6bb1bb5..9b8678a53fb 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "oops/constantPool.inline.hpp"
|
||||
+#include "gc/cms/cmsHeap.hpp"
|
||||
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_old_methods = NULL;
|
||||
Array<Method*>* VM_EnhancedRedefineClasses::_new_methods = NULL;
|
||||
@@ -420,13 +421,11 @@ public:
|
||||
Klass* new_klass = obj->klass()->new_version();
|
||||
|
||||
if (new_klass->update_information() != NULL) {
|
||||
- int size_diff = obj->size() - obj->size_given_klass(new_klass);
|
||||
-
|
||||
- // Either new size is bigger or gap is to small to be filled
|
||||
- if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) {
|
||||
+ if (obj->size() - obj->size_given_klass(new_klass) != 0) {
|
||||
// We need an instance update => set back to old klass
|
||||
_needs_instance_update = true;
|
||||
} else {
|
||||
+ // Either new size is bigger or gap is to small to be filled
|
||||
oop src = obj;
|
||||
if (new_klass->is_copying_backwards()) {
|
||||
copy_to_tmp(obj);
|
||||
@@ -436,11 +435,6 @@ public:
|
||||
// FIXME: instance updates...
|
||||
//guarantee(false, "instance updates!");
|
||||
MarkSweep::update_fields(obj, src, new_klass->update_information());
|
||||
-
|
||||
- if (size_diff > 0) {
|
||||
- HeapWord* dead_space = ((HeapWord *)obj) + obj->size();
|
||||
- CollectedHeap::fill_with_object(dead_space, size_diff);
|
||||
- }
|
||||
}
|
||||
} else {
|
||||
obj->set_klass(obj->klass()->new_version());
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index ca57b524593..2ca6dde069d 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -2047,14 +2047,14 @@ bool Arguments::check_gc_consistency() {
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
// Must use serial GC. This limitation applies because the instance size changing GC modifications
|
||||
// are only built into the mark and compact algorithm.
|
||||
- if (!UseSerialGC && i >= 1) {
|
||||
+ if ((!UseSerialGC && !UseConcMarkSweepGC) && i >= 1) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
- "Must use the serial GC with enhanced class redefinition\n");
|
||||
+ "Must use the serial or concurrent mark sweep GC with enhanced class redefinition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
- if (i > 1) {
|
||||
+ if (i > 2) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Conflicting collector combinations in option list; "
|
||||
"please refer to the release notes for the combinations "
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
257
jb/project/tools/patches/dcevm/0010-Code-cleanup.patch
Normal file
257
jb/project/tools/patches/dcevm/0010-Code-cleanup.patch
Normal file
@@ -0,0 +1,257 @@
|
||||
From b9ceda6f7c230750a87e8a686d833ce853d84712 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 13:22:29 +0100
|
||||
Subject: [PATCH 10/48] Code cleanup
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 125 ++++++------------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 3 -
|
||||
2 files changed, 40 insertions(+), 88 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 9b8678a53fb..0aa1ac4ff80 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
-#include "gc/serial/markSweep.hpp" // FIXME: other GC?
|
||||
+#include "gc/serial/markSweep.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "oops/klassVtable.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
@@ -485,7 +485,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
|
||||
// Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache)
|
||||
- flush_dependent_code(NULL, thread);
|
||||
+ //if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
+ flush_dependent_code(NULL, thread);
|
||||
+ //}
|
||||
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
@@ -593,17 +595,28 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// See jvmtiExport.hpp for detailed explanation.
|
||||
JvmtiExport::set_has_redefined_a_class();
|
||||
|
||||
- // check_class() is optionally called for product bits, but is
|
||||
- // always called for non-product bits.
|
||||
#ifdef PRODUCT
|
||||
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
#endif
|
||||
- log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
- CheckClass check_class(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&check_class);
|
||||
+ for (int i=0; i<_affected_klasses->length(); i++) {
|
||||
+ Klass* the_class = _affected_klasses->at(i);
|
||||
+ assert(the_class->new_version() != NULL, "Must have been redefined");
|
||||
+ Klass* new_version = the_class->new_version();
|
||||
+ assert(new_version->new_version() == NULL, "Must be newest version");
|
||||
+
|
||||
+ if (!(new_version->super() == NULL || new_version->super()->new_version() == NULL)) {
|
||||
+ new_version->print();
|
||||
+ new_version->super()->print();
|
||||
+ }
|
||||
+ assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version");
|
||||
+ }
|
||||
+ log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
+ CheckClass check_class(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&check_class);
|
||||
#ifdef PRODUCT
|
||||
}
|
||||
#endif
|
||||
+
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1279,24 +1292,23 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
GrowableArray<int> result = cl.finish();
|
||||
ik->store_update_information(result);
|
||||
ik->set_copying_backwards(cl.does_copy_backwards());
|
||||
-/* TODO logging
|
||||
- if (RC_TRACE_ENABLED(0x00000001)) {
|
||||
- RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string()));
|
||||
+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
+ log_trace(redefine, class, obsolete, metadata)("Instance update information for %s:", new_version->name()->as_C_string());
|
||||
if (cl.does_copy_backwards()) {
|
||||
- RC_TRACE(0x00000001, ("\tDoes copy backwards!"));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\tDoes copy backwards!");
|
||||
}
|
||||
for (int i=0; i<result.length(); i++) {
|
||||
int curNum = result.at(i);
|
||||
if (curNum < 0) {
|
||||
- RC_TRACE(0x00000001, ("\t%d CLEAN", curNum));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\t%d CLEAN", curNum);
|
||||
} else if (curNum > 0) {
|
||||
- RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1)));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\t%d COPY from %d", curNum, result.at(i + 1));
|
||||
i++;
|
||||
} else {
|
||||
- RC_TRACE(0x00000001, ("\tEND"));
|
||||
+ log_trace(redefine, class, obsolete, metadata)("\tEND");
|
||||
}
|
||||
}
|
||||
- }*/
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1813,6 +1825,7 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
/**
|
||||
FIXME - swap_annotations is never called, check that annotations work
|
||||
*/
|
||||
+// TODO : delete it
|
||||
void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
InstanceKlass* new_class) {
|
||||
// FIXME - probably original implementation only
|
||||
@@ -1822,7 +1835,6 @@ void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
new_class->set_annotations(old_annotations);
|
||||
}
|
||||
|
||||
-
|
||||
// Install the redefinition of a class:
|
||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||
// dependent compiled code)
|
||||
@@ -1853,7 +1865,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
|
||||
// DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined
|
||||
// Deoptimize all compiled code that depends on this class
|
||||
- // flush_dependent_code(the_class, THREAD);
|
||||
+ //if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
+ //flush_dependent_code(the_class, THREAD);
|
||||
+ //}
|
||||
|
||||
_old_methods = the_class->methods();
|
||||
_new_methods = new_class->methods();
|
||||
@@ -1928,64 +1942,15 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
}
|
||||
}
|
||||
|
||||
-// FIXME - class check is currently disabled
|
||||
void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
- return;
|
||||
- bool no_old_methods = true; // be optimistic
|
||||
-
|
||||
- // Both array and instance classes have vtables.
|
||||
- // a vtable should never contain old or obsolete methods
|
||||
- ResourceMark rm(_thread);
|
||||
- if (k->vtable_length() > 0 &&
|
||||
- !k->vtable().check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- k->signature_name());
|
||||
- k->vtable().dump_vtable();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
-
|
||||
- if (k->is_instance_klass()) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
+ HandleMark hm(_thread);
|
||||
+ InstanceKlass *ik = (InstanceKlass *) k;
|
||||
+ assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
|
||||
- // an itable should never contain old or obsolete methods
|
||||
- if (ik->itable_length() > 0 &&
|
||||
- !ik->itable().check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- ik->signature_name());
|
||||
- ik->itable().dump_itable();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
-
|
||||
- // the constant pool cache should never contain non-deleted old or obsolete methods
|
||||
- if (ik->constants() != NULL &&
|
||||
- ik->constants()->cache() != NULL &&
|
||||
- !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- log_trace(redefine, class, obsolete, metadata)
|
||||
- ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s",
|
||||
- ik->signature_name());
|
||||
- ik->constants()->cache()->dump_cache();
|
||||
- }
|
||||
- no_old_methods = false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // print and fail guarantee if old methods are found.
|
||||
- if (!no_old_methods) {
|
||||
- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
- dump_methods();
|
||||
- } else {
|
||||
- log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option "
|
||||
- "to see more info about the following guarantee() failure.");
|
||||
- }
|
||||
- guarantee(false, "OLD and/or OBSOLETE method(s) found");
|
||||
+ if (ik->vtable_length() > 0) {
|
||||
+ ResourceMark rm(_thread);
|
||||
+ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
+ ik->vtable().verify(tty, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2051,15 +2016,6 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
}
|
||||
|
||||
-// TODO - is it called anywhere?
|
||||
-void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const {
|
||||
- VM_Operation::print_on_error(st);
|
||||
- if (_the_class_oop != NULL) {
|
||||
- ResourceMark rm;
|
||||
- st->print_cr(", redefining class %s", _the_class_oop->external_name());
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/**
|
||||
Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
*/
|
||||
@@ -2093,7 +2049,7 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string());
|
||||
klass->set_redefinition_flag(Klass::MarkedAsAffected);
|
||||
_affected_klasses->append(klass);
|
||||
- return;
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2125,7 +2081,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
|
||||
// Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined)
|
||||
AffectedKlassClosure closure(_affected_klasses);
|
||||
- // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure);
|
||||
+ // Updated in j10, from original SystemDictionary::classes_do
|
||||
ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
@@ -2160,7 +2116,6 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
-
|
||||
For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
|
||||
TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index b712d69a193..37e63a1810f 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -195,8 +195,5 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// Modifiable test must be shared between IsModifiableClass query
|
||||
// and redefine implementation
|
||||
static bool is_modifiable_class(oop klass_mirror);
|
||||
-
|
||||
- // Error printing
|
||||
- void print_on_error(outputStream* st) const;
|
||||
};
|
||||
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
118
jb/project/tools/patches/dcevm/0011-Fix-check_class.patch
Normal file
118
jb/project/tools/patches/dcevm/0011-Fix-check_class.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 1d147a5db94b531fa027d5e13e4dd5cbaef62952 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 16:05:25 +0100
|
||||
Subject: [PATCH 11/48] Fix check_class
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 39 +++++++------------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 5 +--
|
||||
2 files changed, 16 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 0aa1ac4ff80..c08b3e82b2e 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1,4 +1,4 @@
|
||||
-/*
|
||||
+ /*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/verifier.hpp"
|
||||
+#include "classfile/dictionary.hpp"
|
||||
#include "interpreter/oopMapCache.hpp"
|
||||
#include "interpreter/rewriter.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@@ -611,8 +612,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version");
|
||||
}
|
||||
log_trace(redefine, class, obsolete, metadata)("calling check_class");
|
||||
- CheckClass check_class(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&check_class);
|
||||
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do(check_class, thread);
|
||||
#ifdef PRODUCT
|
||||
}
|
||||
#endif
|
||||
@@ -1822,19 +1822,6 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity");
|
||||
}
|
||||
|
||||
-/**
|
||||
- FIXME - swap_annotations is never called, check that annotations work
|
||||
-*/
|
||||
-// TODO : delete it
|
||||
-void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class,
|
||||
- InstanceKlass* new_class) {
|
||||
- // FIXME - probably original implementation only
|
||||
- // Swap annotation fields values
|
||||
- Annotations* old_annotations = the_class->annotations();
|
||||
- the_class->set_annotations(new_class->annotations());
|
||||
- new_class->set_annotations(old_annotations);
|
||||
-}
|
||||
-
|
||||
// Install the redefinition of a class:
|
||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||
// dependent compiled code)
|
||||
@@ -1942,15 +1929,17 @@ void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAP
|
||||
}
|
||||
}
|
||||
|
||||
-void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = (InstanceKlass *) k;
|
||||
- assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
+void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
+ if (ik->is_instance_klass() && ik->old_version() != NULL) {
|
||||
+ HandleMark hm(THREAD);
|
||||
+
|
||||
+ assert(ik->new_version() == NULL, "must be latest version in system dictionary");
|
||||
|
||||
- if (ik->vtable_length() > 0) {
|
||||
- ResourceMark rm(_thread);
|
||||
- assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
- ik->vtable().verify(tty, true);
|
||||
+ if (ik->vtable_length() > 0) {
|
||||
+ ResourceMark rm(THREAD);
|
||||
+ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found");
|
||||
+ ik->vtable().verify(tty, true);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2017,7 +2006,7 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
|
||||
/**
|
||||
- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
+ Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
*/
|
||||
class AffectedKlassClosure : public KlassClosure {
|
||||
private:
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 37e63a1810f..5b3ebc13661 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -144,15 +144,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// Install the redefinition of a class
|
||||
void redefine_single_class(InstanceKlass* new_class_oop, TRAPS);
|
||||
|
||||
- void swap_annotations(InstanceKlass* new_class,
|
||||
- InstanceKlass* scratch_class);
|
||||
-
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
||||
|
||||
void flush_dependent_code(InstanceKlass* k_h, TRAPS);
|
||||
|
||||
+ static void check_class(InstanceKlass* k_oop, TRAPS);
|
||||
+
|
||||
static void dump_methods();
|
||||
|
||||
// Check that there are no old or obsolete methods
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 84777c09ddbbbbd6a90de5b1f17a4101c8f076b8 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 17:58:39 +0100
|
||||
Subject: [PATCH 12/48] Fix force_forward in dead space
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.inline.hpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
index 26e56ae6f7e..8c255d6d428 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.inline.hpp
|
||||
@@ -213,6 +213,7 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
// see if this is the first dead region.
|
||||
if (first_dead == NULL) {
|
||||
first_dead = cur_obj;
|
||||
+ force_forward = true;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
25
jb/project/tools/patches/dcevm/0013-Cleanup.patch
Normal file
25
jb/project/tools/patches/dcevm/0013-Cleanup.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 4d973861fbcd13dc50bd603f731c75d2013034c6 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 1 Mar 2019 18:45:13 +0100
|
||||
Subject: [PATCH 13/48] Cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/gc/shared/space.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
||||
index 947dff8ae0c..56b144b46f1 100644
|
||||
--- a/src/hotspot/share/gc/shared/space.cpp
|
||||
+++ b/src/hotspot/share/gc/shared/space.cpp
|
||||
@@ -862,7 +862,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size,
|
||||
size_t forward_size = size;
|
||||
|
||||
// (DCEVM) There is a new version of the class of q => different size
|
||||
- if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) {
|
||||
+ if (oop(q)->klass()->new_version() != NULL) {
|
||||
|
||||
size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version());
|
||||
// assert(size != new_size, "instances without changed size have to be updated prior to GC run");
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From 5f31460556d86fa0233e7998112a65483034fd45 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 29 Dec 2018 17:38:27 +0100
|
||||
Subject: [PATCH 14/48] Add codecache flush optimization, but just flush all
|
||||
cache.
|
||||
|
||||
Redefined class can define a new method that overrides
|
||||
method in superclass which is already used in codecache for
|
||||
optimized non-virtual calls, etc...
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++++------
|
||||
1 file changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index c08b3e82b2e..4ca638548dc 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -486,9 +486,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
|
||||
// Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache)
|
||||
- //if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
+ // if (_max_redefinition_flags > Klass::ModifyClass) {
|
||||
flush_dependent_code(NULL, thread);
|
||||
- //}
|
||||
+ // }
|
||||
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
@@ -1736,8 +1736,14 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
// All dependencies have been recorded from startup or this is a second or
|
||||
// subsequent use of RedefineClasses
|
||||
// FIXME: for now, deoptimize all!
|
||||
- if (0 && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
+ if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) {
|
||||
CodeCache::flush_evol_dependents_on(k_h);
|
||||
+ Klass* superCl = k_h->super();
|
||||
+ // Deoptimize super classes since redefined class can has a new method override
|
||||
+ while (superCl != NULL && !superCl->is_redefining()) {
|
||||
+ CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl));
|
||||
+ superCl = superCl->super();
|
||||
+ }
|
||||
} else {
|
||||
CodeCache::mark_all_nmethods_for_deoptimization();
|
||||
|
||||
@@ -1852,9 +1858,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
|
||||
// DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined
|
||||
// Deoptimize all compiled code that depends on this class
|
||||
- //if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
- //flush_dependent_code(the_class, THREAD);
|
||||
- //}
|
||||
+// if (_max_redefinition_flags <= Klass::ModifyClass) {
|
||||
+// flush_dependent_code(the_class, THREAD);
|
||||
+// }
|
||||
|
||||
_old_methods = the_class->methods();
|
||||
_new_methods = new_class->methods();
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
From d457702275bc47f3f9ea416dc794be403bc6eb94 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Wed, 14 Nov 2018 21:20:08 +0100
|
||||
Subject: [PATCH 15/48] HotswapAgent integration
|
||||
|
||||
It include:
|
||||
|
||||
- option to compile DCEVM only version with -DDCEVM_ONLY added
|
||||
to CFLAGS (bash configure --with-extra-cflags="-DDCEVM_ONLY"), by
|
||||
default compilation goes with HotswapAgent
|
||||
|
||||
Add --add-opens for necessary modules/packages
|
||||
- java.base/java.lang - for reflection access to Proxy.proxyCache
|
||||
- java.base/jdk.internal.loader - for access proxyCache class
|
||||
- java.desktop/java.beans - for reflection access to Introspector
|
||||
|
||||
- be quiet if HotswapAgent is not found in lib/, it is compatible with
|
||||
old DCEVM
|
||||
- disable hotswapagent for -Xshare:dump
|
||||
- disable HotswapAgent in jvm tools
|
||||
---
|
||||
make/launcher/Launcher-java.rmi.gmk | 2 +
|
||||
make/launcher/Launcher-java.scripting.gmk | 3 +-
|
||||
make/launcher/Launcher-java.security.jgss.gmk | 3 +
|
||||
make/launcher/Launcher-jdk.aot.gmk | 2 +
|
||||
make/launcher/Launcher-jdk.compiler.gmk | 5 +-
|
||||
make/launcher/Launcher-jdk.hotspot.agent.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jartool.gmk | 2 +
|
||||
make/launcher/Launcher-jdk.javadoc.gmk | 3 +-
|
||||
make/launcher/Launcher-jdk.jcmd.gmk | 13 +++-
|
||||
make/launcher/Launcher-jdk.jconsole.gmk | 3 +-
|
||||
make/launcher/Launcher-jdk.jdeps.gmk | 3 +
|
||||
make/launcher/Launcher-jdk.jdi.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jlink.gmk | 5 +-
|
||||
make/launcher/Launcher-jdk.jshell.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.jstatd.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.pack.gmk | 1 +
|
||||
make/launcher/Launcher-jdk.rmic.gmk | 1 +
|
||||
.../Launcher-jdk.scripting.nashorn.shell.gmk | 3 +-
|
||||
src/hotspot/share/runtime/arguments.cpp | 59 +++++++++++++++++++
|
||||
src/hotspot/share/runtime/arguments.hpp | 3 +
|
||||
src/hotspot/share/runtime/globals.hpp | 12 +++-
|
||||
21 files changed, 117 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/make/launcher/Launcher-java.rmi.gmk b/make/launcher/Launcher-java.rmi.gmk
|
||||
index a69a90bcc81..07046232275 100644
|
||||
--- a/make/launcher/Launcher-java.rmi.gmk
|
||||
+++ b/make/launcher/Launcher-java.rmi.gmk
|
||||
@@ -27,8 +27,10 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmid, \
|
||||
MAIN_CLASS := sun.rmi.server.Activation, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmiregistry, \
|
||||
MAIN_CLASS := sun.rmi.registry.RegistryImpl, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-java.scripting.gmk b/make/launcher/Launcher-java.scripting.gmk
|
||||
index 057d2bf3aca..cf100e20789 100644
|
||||
--- a/make/launcher/Launcher-java.scripting.gmk
|
||||
+++ b/make/launcher/Launcher-java.scripting.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jrunscript, \
|
||||
MAIN_CLASS := com.sun.tools.script.shell.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-java.security.jgss.gmk b/make/launcher/Launcher-java.security.jgss.gmk
|
||||
index 7411e1a21c4..2b856bfccb4 100644
|
||||
--- a/make/launcher/Launcher-java.security.jgss.gmk
|
||||
+++ b/make/launcher/Launcher-java.security.jgss.gmk
|
||||
@@ -28,13 +28,16 @@ include LauncherCommon.gmk
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
$(eval $(call SetupBuildLauncher, kinit, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, klist, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, ktab, \
|
||||
MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
endif
|
||||
diff --git a/make/launcher/Launcher-jdk.aot.gmk b/make/launcher/Launcher-jdk.aot.gmk
|
||||
index 10717a5e1c5..2c52c31a555 100644
|
||||
--- a/make/launcher/Launcher-jdk.aot.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.aot.gmk
|
||||
@@ -31,6 +31,7 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, jaotc, \
|
||||
MAIN_CLASS := jdk.tools.jaotc.Main, \
|
||||
EXTRA_JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \
|
||||
+ -XX:+DisableHotswapAgent \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
@@ -40,6 +41,7 @@ $(eval $(call SetupBuildLauncher, jaotc, \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
, \
|
||||
JAVA_ARGS := --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
+ -XX:+DisableHotswapAgent \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \
|
||||
diff --git a/make/launcher/Launcher-jdk.compiler.gmk b/make/launcher/Launcher-jdk.compiler.gmk
|
||||
index f71c37adf74..744969546de 100644
|
||||
--- a/make/launcher/Launcher-jdk.compiler.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.compiler.gmk
|
||||
@@ -27,12 +27,14 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javac, \
|
||||
MAIN_CLASS := com.sun.tools.javac.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, serialver, \
|
||||
MAIN_CLASS := sun.tools.serialver.SerialVer, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
@@ -41,6 +43,7 @@ ifeq ($(ENABLE_SJAVAC), yes)
|
||||
# into any real images
|
||||
$(eval $(call SetupBuildLauncher, sjavac, \
|
||||
MAIN_CLASS := com.sun.tools.sjavac.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.hotspot.agent.gmk b/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
index 76da3600368..9f12b05b172 100644
|
||||
--- a/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.hotspot.agent.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jhsdb, \
|
||||
MAIN_CLASS := sun.jvm.hotspot.SALauncher, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jartool.gmk b/make/launcher/Launcher-jdk.jartool.gmk
|
||||
index f74e82bfdae..647d82b65b1 100644
|
||||
--- a/make/launcher/Launcher-jdk.jartool.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jartool.gmk
|
||||
@@ -27,8 +27,10 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jar, \
|
||||
MAIN_CLASS := sun.tools.jar.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jarsigner, \
|
||||
MAIN_CLASS := sun.security.tools.jarsigner.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.javadoc.gmk b/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
index 889028a2b17..c3d2093be04 100644
|
||||
--- a/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.javadoc.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javadoc, \
|
||||
MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jcmd.gmk b/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
index 7117fa78059..761a52d8466 100644
|
||||
--- a/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jcmd.gmk
|
||||
@@ -30,6 +30,7 @@ $(eval $(call SetupBuildLauncher, jinfo, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
-Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
@@ -37,28 +38,36 @@ $(eval $(call SetupBuildLauncher, jmap, \
|
||||
MAIN_CLASS := sun.tools.jmap.JMap, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
- -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jps, \
|
||||
MAIN_CLASS := sun.tools.jps.Jps, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstack, \
|
||||
MAIN_CLASS := sun.tools.jstack.JStack, \
|
||||
JAVA_ARGS := \
|
||||
-Dsun.jvm.hotspot.debugger.useProcDebugger \
|
||||
- -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \
|
||||
+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
MACOSX_PRIVILEGED := true, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstat, \
|
||||
MAIN_CLASS := sun.tools.jstat.Jstat, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jcmd, \
|
||||
MAIN_CLASS := sun.tools.jcmd.JCmd, \
|
||||
+ JAVA_ARGS := \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
diff --git a/make/launcher/Launcher-jdk.jconsole.gmk b/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
index 6205ae63d16..5ca6a0c123b 100644
|
||||
--- a/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jconsole.gmk
|
||||
@@ -28,7 +28,8 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, jconsole, \
|
||||
MAIN_CLASS := sun.tools.jconsole.JConsole, \
|
||||
JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \
|
||||
- -Djconsole.showOutputViewer, \
|
||||
+ -Djconsole.showOutputViewer \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS_windows := -DJAVAW, \
|
||||
LIBS_windows := user32.lib, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jdeps.gmk b/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
index 217523c48cc..5448278dae7 100644
|
||||
--- a/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jdeps.gmk
|
||||
@@ -27,15 +27,18 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javap, \
|
||||
MAIN_CLASS := com.sun.tools.javap.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdeps, \
|
||||
MAIN_CLASS := com.sun.tools.jdeps.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdeprscan, \
|
||||
MAIN_CLASS := com.sun.tools.jdeprscan.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jdi.gmk b/make/launcher/Launcher-jdk.jdi.gmk
|
||||
index fcce98cf430..27bd448e3ae 100644
|
||||
--- a/make/launcher/Launcher-jdk.jdi.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jdi.gmk
|
||||
@@ -27,4 +27,5 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jdb, \
|
||||
MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jlink.gmk b/make/launcher/Launcher-jdk.jlink.gmk
|
||||
index df2173996d7..9e61edeb2c8 100644
|
||||
--- a/make/launcher/Launcher-jdk.jlink.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jlink.gmk
|
||||
@@ -27,18 +27,21 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jimage,\
|
||||
MAIN_CLASS := jdk.tools.jimage.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jlink,\
|
||||
MAIN_CLASS := jdk.tools.jlink.internal.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES \
|
||||
-DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jmod,\
|
||||
MAIN_CLASS := jdk.tools.jmod.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES \
|
||||
-DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jshell.gmk b/make/launcher/Launcher-jdk.jshell.gmk
|
||||
index 349eb88e9eb..7287f8f998a 100644
|
||||
--- a/make/launcher/Launcher-jdk.jshell.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jshell.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jshell, \
|
||||
MAIN_CLASS := jdk.internal.jshell.tool.JShellToolProvider, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.jstatd.gmk b/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
index e9286d63094..e1657910c67 100644
|
||||
--- a/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.jstatd.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jstatd, \
|
||||
MAIN_CLASS := sun.tools.jstatd.Jstatd, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk
|
||||
index a93fd2a9017..64bbbb7c949 100644
|
||||
--- a/make/launcher/Launcher-jdk.pack.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.pack.gmk
|
||||
@@ -28,6 +28,7 @@ include LauncherCommon.gmk
|
||||
$(eval $(call SetupBuildLauncher, pack200, \
|
||||
MAIN_MODULE := java.base, \
|
||||
MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
diff --git a/make/launcher/Launcher-jdk.rmic.gmk b/make/launcher/Launcher-jdk.rmic.gmk
|
||||
index d60c3d9b60b..b8a55900b0e 100644
|
||||
--- a/make/launcher/Launcher-jdk.rmic.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.rmic.gmk
|
||||
@@ -27,5 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmic, \
|
||||
MAIN_CLASS := sun.rmi.rmic.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
||||
diff --git a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
index 82311e69fd6..bd39f8595b2 100644
|
||||
--- a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
+++ b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk
|
||||
@@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jjs, \
|
||||
MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
|
||||
- JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
+ JAVA_ARGS := --add-modules ALL-DEFAULT \
|
||||
+ -XX:+DisableHotswapAgent, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 2ca6dde069d..c75bb5d8f49 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -3937,6 +3937,8 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
||||
// Set object alignment values.
|
||||
set_object_alignment();
|
||||
|
||||
+ setup_hotswap_agent();
|
||||
+
|
||||
#if !INCLUDE_CDS
|
||||
if (DumpSharedSpaces || RequireSharedSpaces) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
@@ -4270,3 +4272,60 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen,
|
||||
*b = '\0';
|
||||
return (p == src_end); // return false if not all of the source was copied
|
||||
}
|
||||
+
|
||||
+void Arguments::setup_hotswap_agent() {
|
||||
+
|
||||
+ if (DumpSharedSpaces)
|
||||
+ return;
|
||||
+
|
||||
+ if (!AllowEnhancedClassRedefinition)
|
||||
+ return;
|
||||
+
|
||||
+ // Set HotswapAgent
|
||||
+ if (!DisableHotswapAgent) {
|
||||
+
|
||||
+ char ext_path_str[JVM_MAXPATHLEN];
|
||||
+
|
||||
+ os::jvm_path(ext_path_str, sizeof(ext_path_str));
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ char *end = strrchr(ext_path_str, *os::file_separator());
|
||||
+ if (end != NULL) *end = '\0';
|
||||
+ }
|
||||
+ size_t ext_path_length = strlen(ext_path_str);
|
||||
+ if (ext_path_length >= 3) {
|
||||
+ if (strcmp(ext_path_str + ext_path_length - 3, "lib") != 0) {
|
||||
+ if (ext_path_length < JVM_MAXPATHLEN - 4) {
|
||||
+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, "%slib", os::file_separator());
|
||||
+ ext_path_length += 4;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (ext_path_length < JVM_MAXPATHLEN - 10) {
|
||||
+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length,
|
||||
+ "%shotswap%shotswap-agent.jar", os::file_separator(), os::file_separator());
|
||||
+ }
|
||||
+
|
||||
+ int fd = ::open(ext_path_str, O_RDONLY);
|
||||
+ if (fd >= 0) {
|
||||
+ os::close(fd);
|
||||
+ size_t length = strlen(ext_path_str) + 1;
|
||||
+ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
|
||||
+ jio_snprintf(options, length, "%s", ext_path_str);
|
||||
+ add_init_agent("instrument", ext_path_str, false);
|
||||
+ jio_fprintf(defaultStream::output_stream(), "Starting HotswapAgent '%s'\n", ext_path_str);
|
||||
+ }
|
||||
+// else
|
||||
+// {
|
||||
+// jio_fprintf(defaultStream::error_stream(), "HotswapAgent not found on path:'%s'\n", ext_path_str);
|
||||
+// }
|
||||
+ }
|
||||
+
|
||||
+ // TODO: open it only for org.hotswap.agent module
|
||||
+ // Use to access java.lang.reflect.Proxy/proxyCache
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
||||
+ // Class of field java.lang.reflect.Proxy/proxyCache
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
+ // java.beans.Introspector access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
+
|
||||
+}
|
||||
diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp
|
||||
index 46450cce5c9..3dc5b3d4bae 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.hpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.hpp
|
||||
@@ -506,6 +506,9 @@ class Arguments : AllStatic {
|
||||
|
||||
static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; }
|
||||
|
||||
+ // Initialize HotswapAgent
|
||||
+ static void setup_hotswap_agent();
|
||||
+
|
||||
// Return the maximum size a heap with compressed oops can take
|
||||
static size_t max_heap_for_compressed_oops();
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
|
||||
index f3cf08fffb6..5f6c7b8e388 100644
|
||||
--- a/src/hotspot/share/runtime/globals.hpp
|
||||
+++ b/src/hotspot/share/runtime/globals.hpp
|
||||
@@ -32,6 +32,12 @@
|
||||
|
||||
#include <float.h> // for DBL_MAX
|
||||
|
||||
+#ifdef DCEVM_ONLY
|
||||
+#define DISABLED_HOTSWAP_AGENT true
|
||||
+#else
|
||||
+#define DISABLED_HOTSWAP_AGENT false
|
||||
+#endif
|
||||
+
|
||||
// The larger HeapWordSize for 64bit requires larger heaps
|
||||
// for the same application running in 64bit. See bug 4967770.
|
||||
// The minimum alignment to a heap word size is done. Other
|
||||
@@ -2675,8 +2681,10 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
|
||||
\
|
||||
product(bool, AllowEnhancedClassRedefinition, true, \
|
||||
"Allow enhanced class redefinition beyond swapping method " \
|
||||
- "bodies")
|
||||
-
|
||||
+ "bodies") \
|
||||
+ \
|
||||
+ product(bool, DisableHotswapAgent, DISABLED_HOTSWAP_AGENT, \
|
||||
+ "Disable integrated Hotswap Agent (HotswapVM only)")
|
||||
#define VM_FLAGS(develop, \
|
||||
develop_pd, \
|
||||
product, \
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From 603b446449aa715aa3f409fb49ed00169b89fd91 Mon Sep 17 00:00:00 2001
|
||||
From: skybber <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 16 Dec 2018 09:55:31 +0100
|
||||
Subject: [PATCH 16/48] Add dcevm distro name
|
||||
|
||||
---
|
||||
make/autoconf/version-numbers | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers
|
||||
index b5a23138213..5c0a3242c80 100644
|
||||
--- a/make/autoconf/version-numbers
|
||||
+++ b/make/autoconf/version-numbers
|
||||
@@ -43,7 +43,7 @@ PRODUCT_NAME=OpenJDK
|
||||
PRODUCT_SUFFIX="Runtime Environment"
|
||||
JDK_RC_PLATFORM_NAME=Platform
|
||||
COMPANY_NAME=N/A
|
||||
-HOTSPOT_VM_DISTRO="OpenJDK"
|
||||
+HOTSPOT_VM_DISTRO="Dynamic Code Evolution"
|
||||
|
||||
# Might need better names for these
|
||||
MACOSX_BUNDLE_NAME_BASE="OpenJDK"
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 6869b6f67f8c8db57d91ea0ef9f33aaf44def1db Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 Nov 2019 19:58:27 +0100
|
||||
Subject: [PATCH 17/48] java.desktop/com.sun.beans=ALL-UNNAMED
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index c75bb5d8f49..ba6e78d6daa 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4327,5 +4327,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
+ // java.beans.Introspector access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
From bbcbaa9d5814017565b8f7f0d86844e9f64905c1 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 Nov 2019 21:07:59 +0100
|
||||
Subject: [PATCH 18/48] increment_class_counter() using orig dcevm code
|
||||
|
||||
Probably it is cause of SISEGV on:
|
||||
_
|
||||
VM_EnhancedRedefineClasses::redefine_single_class->java_mirror()
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 39 ++++++-------------
|
||||
1 file changed, 12 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 4ca638548dc..efb9e806508 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1146,9 +1146,9 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
}
|
||||
|
||||
|
||||
-/**
|
||||
+/**
|
||||
Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
-
|
||||
+
|
||||
@param the_class definition of a class, either existing class or new_class
|
||||
@param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
@param class_byte_count - size of class_bytes
|
||||
@@ -1460,7 +1460,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
//
|
||||
// ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
// }
|
||||
-
|
||||
+
|
||||
constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
|
||||
// Update host klass of anonymous classes (for example, produced by lambdas) to newest version.
|
||||
@@ -1764,7 +1764,7 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
/**
|
||||
Compare _old_methods and _new_methods arrays and store the result into
|
||||
_matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
-
|
||||
+
|
||||
Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
*/
|
||||
void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
@@ -1898,13 +1898,13 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
ResourceMark rm(THREAD);
|
||||
// increment the classRedefinedCount field in the_class and in any
|
||||
// direct and indirect subclasses of the_class
|
||||
- increment_class_counter(the_class, THREAD);
|
||||
+ increment_class_counter(new_class, THREAD);
|
||||
log_info(redefine, class, load)
|
||||
("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
|
||||
- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10);
|
||||
+ new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), os::available_memory() >> 10);
|
||||
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
|
||||
- the_class->external_name(),
|
||||
- java_lang_Class::classRedefinedCount(the_class->java_mirror()));
|
||||
+ new_class->external_name(),
|
||||
+ java_lang_Class::classRedefinedCount(new_class->java_mirror()));
|
||||
|
||||
}
|
||||
_timer_rsc_phase2.stop();
|
||||
@@ -1914,25 +1914,10 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) {
|
||||
- oop class_mirror = ik->java_mirror();
|
||||
+ oop class_mirror = ik->old_version()->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
- java_lang_Class::set_classRedefinedCount(ik->new_version()->java_mirror(), new_count);
|
||||
-
|
||||
- if (class_oop != _the_class_oop) {
|
||||
- // _the_class_oop count is printed at end of redefine_single_class()
|
||||
- log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
|
||||
- }
|
||||
-
|
||||
- for (Klass *subk = ik->subklass(); subk != NULL;
|
||||
- subk = subk->next_sibling()) {
|
||||
- if (subk->is_instance_klass()) {
|
||||
- // Only update instanceKlasses
|
||||
- InstanceKlass *subik = InstanceKlass::cast(subk);
|
||||
- // recursively do subclasses of the current subclass
|
||||
- increment_class_counter(subik, THREAD);
|
||||
- }
|
||||
- }
|
||||
+ java_lang_Class::set_classRedefinedCount(ik->java_mirror(), new_count);
|
||||
}
|
||||
|
||||
void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
@@ -2063,7 +2048,7 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
|
||||
/**
|
||||
Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
- Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
+ Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
*/
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
for (int i = 0; i < _class_count; i++) {
|
||||
@@ -2112,7 +2097,7 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
-
|
||||
+
|
||||
TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
*/
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
From 62c65c226bbc4fadbc598db1a2ac7d05d17ae731 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 21 Nov 2019 19:30:07 +0100
|
||||
Subject: [PATCH 19/48] Allow 11715ha class initializer calls
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/vmSymbols.hpp | 1 +
|
||||
src/hotspot/share/interpreter/linkResolver.cpp | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
index e2bac31b27f..6eeda3b8f68 100644
|
||||
--- a/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
+++ b/src/hotspot/share/classfile/vmSymbols.hpp
|
||||
@@ -340,6 +340,7 @@
|
||||
/* common method and field names */ \
|
||||
template(object_initializer_name, "<init>") \
|
||||
template(class_initializer_name, "<clinit>") \
|
||||
+ template(ha_class_initializer_name, "$$ha$clinit") \
|
||||
template(println_name, "println") \
|
||||
template(printStackTrace_name, "printStackTrace") \
|
||||
template(main_name, "main") \
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index b9ccdee8cca..cb76d2ef50c 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -1009,7 +1009,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||
assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
|
||||
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
|
||||
fd.is_static() &&
|
||||
- !m()->is_static_initializer());
|
||||
+ !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name()));
|
||||
bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
|
||||
!fd.is_static() &&
|
||||
!m->is_object_initializer());
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 88b6f7a27e35d9ed3b82418b82c1cb1fe14f61e6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 26 Nov 2019 22:13:07 +0100
|
||||
Subject: [PATCH 20/48] Disable HA in keytool
|
||||
|
||||
---
|
||||
make/launcher/Launcher-java.base.gmk | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/make/launcher/Launcher-java.base.gmk b/make/launcher/Launcher-java.base.gmk
|
||||
index 5ee4530004b..88c1a14b2aa 100644
|
||||
--- a/make/launcher/Launcher-java.base.gmk
|
||||
+++ b/make/launcher/Launcher-java.base.gmk
|
||||
@@ -63,6 +63,7 @@ endif
|
||||
|
||||
$(eval $(call SetupBuildLauncher, keytool, \
|
||||
MAIN_CLASS := sun.security.tools.keytool.Main, \
|
||||
+ JAVA_ARGS := -XX:+DisableHotswapAgent, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 7fb12fc40a76a37ce67b051276a7ef582de1b04a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Thu, 28 Nov 2019 18:53:11 +0100
|
||||
Subject: [PATCH 21/48] Open jdk module to access ClassInfo.CACHE
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index ba6e78d6daa..0081f688120 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4329,5 +4329,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
+ // com.sun.beans.introspect.ClassInfo access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From d3d53f242337bd3bc79917f922ff569c0a112f3b Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 8 Dec 2019 17:55:01 +0100
|
||||
Subject: [PATCH 22/48] Open java.base/java.io module
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 0081f688120..0cdd8c88315 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4325,6 +4325,8 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
||||
// Class of field java.lang.reflect.Proxy/proxyCache
|
||||
create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
||||
+ // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream
|
||||
+ create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
||||
// java.beans.Introspector access
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 833ef503677e066b3639e7418a22587992df1829 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Fri, 6 Mar 2020 09:28:24 +0100
|
||||
Subject: [PATCH 23/48] Fix fieldDescriptor.inline.hpp
|
||||
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index efb9e806508..a404fd3f016 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/relocator.hpp"
|
||||
+#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
@@ -490,6 +491,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
+
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1890,9 +1896,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
@@ -1905,7 +1908,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
|
||||
new_class->external_name(),
|
||||
java_lang_Class::classRedefinedCount(new_class->java_mirror()));
|
||||
-
|
||||
}
|
||||
_timer_rsc_phase2.stop();
|
||||
} // end redefine_single_class()
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
From 1af8b1f3f891388a37cc71076c324d3905ab2a46 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Fri, 6 Mar 2020 15:46:51 +0100
|
||||
Subject: [PATCH 24/48] Fix clear_cpool_cache
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a404fd3f016..1f5a67f8866 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -491,11 +491,6 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
-
|
||||
-
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1896,6 +1891,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
From def550828411b677ed2d7807e51cc5ffe70331fc Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Mon, 9 Mar 2020 09:54:04 +0100
|
||||
Subject: [PATCH 25/48] Refactor ClearCpoolCacheAndUnpatch
|
||||
|
||||
Call it after redefinition of all classes
|
||||
---
|
||||
make/common/MakeBase.gmk | 4 +-
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 98 ++++---------------
|
||||
2 files changed, 21 insertions(+), 81 deletions(-)
|
||||
|
||||
diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk
|
||||
index a040effe83a..c33a7d52ddb 100644
|
||||
--- a/make/common/MakeBase.gmk
|
||||
+++ b/make/common/MakeBase.gmk
|
||||
@@ -1044,7 +1044,9 @@ DependOnVariableHelper = \
|
||||
$(info NewVariable $1: >$(strip $($1))<) \
|
||||
$(info OldVariable $1: >$(strip $($1_old))<)) \
|
||||
$(call WriteFile, $1_old:=$(call DoubleDollar,$(call EscapeHash,$($1))), \
|
||||
- $($1_filename))) \
|
||||
+ $($1_filename)) \
|
||||
+ $(eval $($1_filename): ) \
|
||||
+ ) \
|
||||
$($1_filename) \
|
||||
)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 1f5a67f8866..24fb76b6de4 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -491,6 +491,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
flush_dependent_code(NULL, thread);
|
||||
// }
|
||||
|
||||
+ // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
||||
+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
+
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -1383,86 +1388,23 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
||||
}
|
||||
}
|
||||
|
||||
-// Unevolving classes may point to methods of the_class directly
|
||||
+// Unevolving classes may point to old methods directly
|
||||
// from their constant pool caches, itables, and/or vtables. We
|
||||
-// use the ClassLoaderDataGraph::classes_do() facility and this helper
|
||||
-// to fix up these pointers.
|
||||
-// Adjust cpools and vtables closure
|
||||
+// use the SystemDictionary::classes_do() facility and this helper
|
||||
+// to fix up these pointers. Additional field offsets and vtable indices
|
||||
+// in the constant pool cache entries are fixed.
|
||||
+//
|
||||
+// Note: We currently don't support updating the vtable in
|
||||
+// arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp.
|
||||
void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
- // This is a very busy routine. We don't want too much tracing
|
||||
- // printed out.
|
||||
- bool trace_name_printed = false;
|
||||
- InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop);
|
||||
-
|
||||
- // If the class being redefined is java.lang.Object, we need to fix all
|
||||
- // array class vtables also
|
||||
- if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) {
|
||||
- k->vtable().adjust_method_entries(the_class, &trace_name_printed);
|
||||
- } else if (k->is_instance_klass()) {
|
||||
- HandleMark hm(_thread);
|
||||
- InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
+ if (!k->is_instance_klass()) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- // HotSpot specific optimization! HotSpot does not currently
|
||||
- // support delegation from the bootstrap class loader to a
|
||||
- // user-defined class loader. This means that if the bootstrap
|
||||
- // class loader is the initiating class loader, then it will also
|
||||
- // be the defining class loader. This also means that classes
|
||||
- // loaded by the bootstrap class loader cannot refer to classes
|
||||
- // loaded by a user-defined class loader. Note: a user-defined
|
||||
- // class loader can delegate to the bootstrap class loader.
|
||||
- //
|
||||
- // If the current class being redefined has a user-defined class
|
||||
- // loader as its defining class loader, then we can skip all
|
||||
- // classes loaded by the bootstrap class loader.
|
||||
- bool is_user_defined =
|
||||
- InstanceKlass::cast(_the_class_oop)->class_loader() != NULL;
|
||||
- if (is_user_defined && ik->class_loader() == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Fix the vtable embedded in the_class and subclasses of the_class,
|
||||
- // if one exists. We discard scratch_class and we don't keep an
|
||||
- // InstanceKlass around to hold obsolete methods so we don't have
|
||||
- // any other InstanceKlass embedded vtables to update. The vtable
|
||||
- // holds the Method*s for virtual (but not final) methods.
|
||||
- // Default methods, or concrete methods in interfaces are stored
|
||||
- // in the vtable, so if an interface changes we need to check
|
||||
- // adjust_method_entries() for every InstanceKlass, which will also
|
||||
- // adjust the default method vtable indices.
|
||||
- // We also need to adjust any default method entries that are
|
||||
- // not yet in the vtable, because the vtable setup is in progress.
|
||||
- // This must be done after we adjust the default_methods and
|
||||
- // default_vtable_indices for methods already in the vtable.
|
||||
- // If redefining Unsafe, walk all the vtables looking for entries.
|
||||
-// FIXME - code from standard redefine - if needed, it should switch to new_class
|
||||
-// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
|
||||
-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
|
||||
-// || ik->is_subtype_of(_the_class_oop))) {
|
||||
-// // ik->vtable() creates a wrapper object; rm cleans it up
|
||||
-// ResourceMark rm(_thread);
|
||||
-//
|
||||
-// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
-// ik->adjust_default_methods(the_class, &trace_name_printed);
|
||||
-// }
|
||||
-
|
||||
- // If the current class has an itable and we are either redefining an
|
||||
- // interface or if the current class is a subclass of the_class, then
|
||||
- // we potentially have to fix the itable. If we are redefining an
|
||||
- // interface, then we have to call adjust_method_entries() for
|
||||
- // every InstanceKlass that has an itable since there isn't a
|
||||
- // subclass relationship between an interface and an InstanceKlass.
|
||||
- // If redefining Unsafe, walk all the itables looking for entries.
|
||||
-// FIXME - code from standard redefine - if needed, it should switch to new_class
|
||||
-// if (ik->itable_length() > 0 && (_the_class_oop->is_interface()
|
||||
-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
|
||||
-// || ik->is_subclass_of(_the_class_oop))) {
|
||||
-// // ik->itable() creates a wrapper object; rm cleans it up
|
||||
-// ResourceMark rm(_thread);
|
||||
-//
|
||||
-// ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
-// }
|
||||
+ HandleMark hm(_thread);
|
||||
+ InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
|
||||
- constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
+ constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
||||
|
||||
// Update host klass of anonymous classes (for example, produced by lambdas) to newest version.
|
||||
if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) {
|
||||
@@ -1491,7 +1433,6 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
if (RewriteBytecodes) {
|
||||
ik->methods_do(unpatch_bytecode);
|
||||
}
|
||||
- }
|
||||
}
|
||||
|
||||
// Clean method data for this class
|
||||
@@ -1891,9 +1832,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
- // Adjust constantpool caches for all classes that reference methods of the evolved class.
|
||||
- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD);
|
||||
- ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 5f416d7a25bd23399b9189cc94ab5d5887e6b4d4 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <vladimir.dvorak@mailprofiler.com>
|
||||
Date: Wed, 11 Mar 2020 14:19:34 +0100
|
||||
Subject: [PATCH 26/48] Fix class cast exception on redefinition of class A,
|
||||
that is superclass of B that has anonymous class C
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 9b6ba7e9304..8cbd4b8edf2 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -788,7 +788,10 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
- {
|
||||
+ // In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
+ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
+ // on redefinition.
|
||||
+ if (!newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From 9a7abdf08bf207f5265a552500446c3178bf5794 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 23:28:07 +0200
|
||||
Subject: [PATCH 27/48] Update klass reference in Klass.implementor()
|
||||
|
||||
If interface X is removed from class Y then old reference to Y could be
|
||||
stored in X.implementor()
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 12 ++++++++++++
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.hpp | 11 -----------
|
||||
2 files changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 24fb76b6de4..f6d2d3a40fe 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1411,6 +1411,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version()));
|
||||
}
|
||||
|
||||
+ // Update implementor if there is only one, in this case implementor() can reference old class
|
||||
+ if (ik->is_interface()) {
|
||||
+ Klass* implKlass = ik->implementor();
|
||||
+ if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) {
|
||||
+ InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version());
|
||||
+ ik->init_implementor();
|
||||
+ if (newest_impl->implements_interface(ik)) {
|
||||
+ ik->add_implementor(newest_impl);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for (int i = 0; i < other_cp->length(); i++) {
|
||||
if (other_cp->tag_at(i).is_klass()) {
|
||||
Klass* klass = other_cp->resolved_klass_at(i);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 5b3ebc13661..2d114635ee5 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -69,17 +69,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// RetransformClasses. Indicate which.
|
||||
JvmtiClassLoadKind _class_load_kind;
|
||||
|
||||
- // _index_map_count is just an optimization for knowing if
|
||||
- // _index_map_p contains any entries.
|
||||
- int _index_map_count;
|
||||
- intArray * _index_map_p;
|
||||
-
|
||||
- // _operands_index_map_count is just an optimization for knowing if
|
||||
- // _operands_index_map_p contains any entries.
|
||||
- int _operands_cur_length;
|
||||
- int _operands_index_map_count;
|
||||
- intArray * _operands_index_map_p;
|
||||
-
|
||||
GrowableArray<InstanceKlass*>* _new_classes;
|
||||
jvmtiError _res;
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
From 8f13d3b4ba9aecd847b7da306055ba53ee2e29d0 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 23:30:21 +0200
|
||||
Subject: [PATCH 28/48] Fix DirectMethodHandle accessors klasses
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/javaClasses.cpp | 28 +++++++++++++++------
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 4 +++
|
||||
2 files changed, 24 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
index a89443d22ea..ea0588e5388 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.cpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.cpp
|
||||
@@ -3641,14 +3641,20 @@ void java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(oop d
|
||||
dmh->long_field_put(_static_offset_offset, static_offset);
|
||||
}
|
||||
|
||||
+#define DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(macro) \
|
||||
+ macro(_static_offset_offset, k, vmSymbols::static_offset_name(), long_signature, false)
|
||||
|
||||
void java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets() {
|
||||
- Klass* klass_oop = SystemDictionary::DirectMethodHandle_StaticAccessor_klass();
|
||||
- if (klass_oop != NULL) {
|
||||
- compute_offset(_static_offset_offset, InstanceKlass::cast(klass_oop), vmSymbols::static_offset_name(), vmSymbols::long_signature());
|
||||
- }
|
||||
+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_StaticAccessor_klass();
|
||||
+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
+void java_lang_invoke_DirectMethodHandle_StaticAccessor::serialize_offsets(SerializeClosure* f) {
|
||||
+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Support for java_lang_invoke_DirectMethodHandle$Accessor
|
||||
|
||||
int java_lang_invoke_DirectMethodHandle_Accessor::_field_offset_offset;
|
||||
@@ -3663,14 +3669,20 @@ void java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(oop dmh, int
|
||||
dmh->int_field_put(_field_offset_offset, field_offset);
|
||||
}
|
||||
|
||||
+#define DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(macro) \
|
||||
+ macro(_field_offset_offset, k, vmSymbols::field_offset_name(), int_signature, false)
|
||||
|
||||
void java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets() {
|
||||
- Klass* klass_oop = SystemDictionary::DirectMethodHandle_Accessor_klass();
|
||||
- if (klass_oop != NULL) {
|
||||
- compute_offset(_field_offset_offset, InstanceKlass::cast(klass_oop), vmSymbols::field_offset_name(), vmSymbols::int_signature());
|
||||
- }
|
||||
+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_Accessor_klass();
|
||||
+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
+void java_lang_invoke_DirectMethodHandle_Accessor::serialize_offsets(SerializeClosure* f) {
|
||||
+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Support for java_lang_invoke_MethodHandle
|
||||
|
||||
int java_lang_invoke_MethodHandle::_type_offset;
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index ceb1670df5d..55f9fa62e2b 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -67,6 +67,8 @@
|
||||
f(java_lang_invoke_LambdaForm) \
|
||||
f(java_lang_invoke_MethodType) \
|
||||
f(java_lang_invoke_CallSite) \
|
||||
+ f(java_lang_invoke_DirectMethodHandle_StaticAccessor) \
|
||||
+ f(java_lang_invoke_DirectMethodHandle_Accessor) \
|
||||
f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \
|
||||
f(java_security_AccessControlContext) \
|
||||
f(java_lang_reflect_AccessibleObject) \
|
||||
@@ -1077,6 +1079,7 @@ class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic {
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.DirectMethodHandle$Accessor objects
|
||||
@@ -1101,6 +1104,7 @@ class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic {
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From cbad9c34bf8920d772c646d041d4fc04fea203cc Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 11 Apr 2020 12:07:43 +0200
|
||||
Subject: [PATCH 29/48] cleanup direct method handles code
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/javaClasses.hpp | 10 ++++------
|
||||
src/hotspot/share/classfile/javaClasses.inline.hpp | 8 ++++++++
|
||||
2 files changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
index 55f9fa62e2b..da004d1b307 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
||||
@@ -1076,9 +1076,8 @@ class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic {
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_StaticAccessor_klass());
|
||||
}
|
||||
- static bool is_instance(oop obj) {
|
||||
- return obj != NULL && is_subclass(obj->klass());
|
||||
- }
|
||||
+ static bool is_instance(oop obj);
|
||||
+
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
@@ -1101,9 +1100,8 @@ class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic {
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_Accessor_klass());
|
||||
}
|
||||
- static bool is_instance(oop obj) {
|
||||
- return obj != NULL && is_subclass(obj->klass());
|
||||
- }
|
||||
+ static bool is_instance(oop obj);
|
||||
+
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
index 6c5787f4b70..ba9cffa8c62 100644
|
||||
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp
|
||||
@@ -175,6 +175,14 @@ inline bool java_lang_invoke_DirectMethodHandle::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
+inline bool java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(oop obj) {
|
||||
+ return obj != NULL && is_subclass(obj->klass());
|
||||
+}
|
||||
+
|
||||
+inline bool java_lang_invoke_DirectMethodHandle_Accessor::is_instance(oop obj) {
|
||||
+ return obj != NULL && is_subclass(obj->klass());
|
||||
+}
|
||||
+
|
||||
inline bool java_lang_Module::is_instance(oop obj) {
|
||||
return obj != NULL && obj->klass() == SystemDictionary::Module_klass();
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
From e3b94671ce5108a91e3a3e92b01eea07731c7639 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 11 Apr 2020 17:52:13 +0200
|
||||
Subject: [PATCH 30/48] Add init_implementor_from_redefine, that skips compiler
|
||||
lock assert
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 10 +++++++++-
|
||||
src/hotspot/share/oops/instanceKlass.hpp | 1 +
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
3 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index 8cbd4b8edf2..c04bdf5abfc 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -789,7 +789,7 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
// In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
- // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
+ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
// on redefinition.
|
||||
if (!newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
@@ -1139,6 +1139,14 @@ void InstanceKlass::init_implementor() {
|
||||
}
|
||||
}
|
||||
|
||||
+void InstanceKlass::init_implementor_from_redefine() {
|
||||
+ assert(is_interface(), "not interface");
|
||||
+ Klass** addr = adr_implementor();
|
||||
+ assert(addr != NULL, "null addr");
|
||||
+ if (addr != NULL) {
|
||||
+ *addr = NULL;
|
||||
+ }
|
||||
+}
|
||||
|
||||
void InstanceKlass::process_interfaces(Thread *thread) {
|
||||
// link this class into the implementors list of every interface it implements
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
index 2cc98b636f1..e8107a39813 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.hpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.hpp
|
||||
@@ -1020,6 +1020,7 @@ public:
|
||||
int nof_implementors() const;
|
||||
void add_implementor(Klass* k); // k is a new class that implements this interface
|
||||
void init_implementor(); // initialize
|
||||
+ void init_implementor_from_redefine(); // initialize
|
||||
|
||||
// link this class into the implementors list of every interface it implements
|
||||
void process_interfaces(Thread *thread);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index f6d2d3a40fe..aac9ba0911f 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1416,7 +1416,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
Klass* implKlass = ik->implementor();
|
||||
if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) {
|
||||
InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version());
|
||||
- ik->init_implementor();
|
||||
+ ik->init_implementor_from_redefine();
|
||||
if (newest_impl->implements_interface(ik)) {
|
||||
ik->add_implementor(newest_impl);
|
||||
}
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
From a95c3daf0a1db23e2dcc977f427faa7be41007c9 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Mon, 13 Apr 2020 20:59:35 +0200
|
||||
Subject: [PATCH 31/48] not nullable oop_store_not_null() method+handle NULL in
|
||||
mem_name in dmh
|
||||
|
||||
---
|
||||
.../share/prims/jvmtiEnhancedRedefineClasses.cpp | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index aac9ba0911f..8d861ef43c9 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -225,13 +225,15 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
// TODO comment
|
||||
struct StoreBarrier {
|
||||
// TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store
|
||||
- template <class T> static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store_not_null(T* p, oop v) { HeapAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store(T* p) { HeapAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
|
||||
// TODO comment
|
||||
struct StoreNoBarrier {
|
||||
- template <class T> static void oop_store(T* p, oop v) { RawAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store_not_null(T* p, oop v) { RawAccess<IS_NOT_NULL>::oop_store(p, v); }
|
||||
+ template <class T> static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -309,6 +311,9 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
bool update_direct_method_handle(oop obj) {
|
||||
// Always update member name first.
|
||||
oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj);
|
||||
+ if (mem_name == NULL) {
|
||||
+ return true;
|
||||
+ }
|
||||
if (!update_member_name(mem_name)) {
|
||||
return false;
|
||||
}
|
||||
@@ -347,7 +352,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking");
|
||||
if (klass->new_version() != NULL) {
|
||||
obj = InstanceKlass::cast(klass->new_version())->java_mirror();
|
||||
- S::oop_store(p, obj);
|
||||
+ S::oop_store_not_null(p, obj);
|
||||
oop_updated = true;
|
||||
}
|
||||
}
|
||||
@@ -363,7 +368,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
if (!update_direct_method_handle(obj)) {
|
||||
// DMH is no longer valid, replace it with null reference.
|
||||
// See note above. We probably want to replace this with something more meaningful.
|
||||
- S::oop_store(p, NULL);
|
||||
+ S::oop_store(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1430,8 +1435,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
||||
// Constant pool entry points to redefined class -- update to the new version
|
||||
other_cp->klass_at_put(i, klass->newest_version());
|
||||
}
|
||||
- klass = other_cp->resolved_klass_at(i);
|
||||
- assert(klass->new_version() == NULL, "Must be new klass!");
|
||||
+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!");
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 15690197a276a86054e1ec9724c877d6d871ca01 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Khvastunov <artem.khvastunov@jetbrains.com>
|
||||
Date: Tue, 14 Apr 2020 19:11:35 +0200
|
||||
Subject: [PATCH 32/48] add jvmtiEnhancedRedefineClasses.* to CMakeLists.txt
|
||||
|
||||
---
|
||||
jb/project/hotspot-cmake/CMakeLists.txt | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/jb/project/hotspot-cmake/CMakeLists.txt b/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
index 8b552c27206..6516e39058f 100644
|
||||
--- a/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
+++ b/jb/project/hotspot-cmake/CMakeLists.txt
|
||||
@@ -1663,6 +1663,7 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiAgentThread.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp
|
||||
+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
../../../src/hotspot/share/prims/stackwalk.cpp
|
||||
../../../src/hotspot/share/prims/privilegedStack.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiUtil.hpp
|
||||
@@ -1684,6 +1685,7 @@ set(SOURCE_FILES
|
||||
../../../src/hotspot/share/prims/stackwalk.hpp
|
||||
../../../src/hotspot/share/prims/privilegedStack.cpp
|
||||
../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.hpp
|
||||
+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
../../../src/hotspot/share/prims/jvmtiUtil.cpp
|
||||
../../../src/hotspot/share/prims/jvmtiEnvBase.cpp
|
||||
../../../src/hotspot/share/prims/methodHandles.cpp
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From dab6a53de4c25aae95667c78b8e1f1097ab47130 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Khvastunov <artem.khvastunov@jetbrains.com>
|
||||
Date: Sun, 19 Apr 2020 11:36:12 +0200
|
||||
Subject: [PATCH 33/48] migrate DCEVM to 11.0.7
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 2d114635ee5..6cabdca9c27 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
-#include "runtime/vm_operations.hpp"
|
||||
+#include "runtime/vmOperations.hpp"
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 70d53ce28f9df75d9e50819d2b6654855da0d533 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 8 May 2020 21:07:50 +0200
|
||||
Subject: [PATCH 34/48] Fix 11.0.7 compilation issues
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 6cabdca9c27..ed44f0e27ce 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -16,6 +16,8 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
+ *
|
||||
+ *
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
@@ -30,7 +32,6 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
-#include "runtime/vmOperations.hpp"
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 805b588bc4bd45e61b81c90e23b71337072e9549 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 9 May 2020 10:08:17 +0200
|
||||
Subject: [PATCH 35/48] Use INCLUDE_CDS condition on "UseSharedSpaces" block
|
||||
from master
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 8d861ef43c9..660bf3a2e97 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -467,6 +467,7 @@ public:
|
||||
void VM_EnhancedRedefineClasses::doit() {
|
||||
Thread *thread = Thread::current();
|
||||
|
||||
+#if INCLUDE_CDS
|
||||
if (UseSharedSpaces) {
|
||||
// Sharing is enabled so we remap the shared readonly space to
|
||||
// shared readwrite, private just in case we need to redefine
|
||||
@@ -478,6 +479,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
|
||||
// Mark methods seen on stack and everywhere else so old methods are not
|
||||
// cleaned up if they're on the stack.
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
From 78619004206d224b319d68493672bee2c97f0946 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 16 May 2020 15:11:40 +0200
|
||||
Subject: [PATCH 36/48] Access com.sun.beans.util - HotswapAgent patch
|
||||
|
||||
---
|
||||
src/hotspot/share/runtime/arguments.cpp | 2 ++
|
||||
.../sun/beans/introspect/package-info.java | 26 +++++++++++++++++++
|
||||
.../classes/com/sun/beans/package-info.java | 26 +++++++++++++++++++
|
||||
.../com/sun/beans/util/package-info.java | 26 +++++++++++++++++++
|
||||
.../share/classes/module-info.java | 3 +++
|
||||
5 files changed, 83 insertions(+)
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
create mode 100644 src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
|
||||
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
||||
index 0cdd8c88315..72580b384dd 100644
|
||||
--- a/src/hotspot/share/runtime/arguments.cpp
|
||||
+++ b/src/hotspot/share/runtime/arguments.cpp
|
||||
@@ -4333,5 +4333,7 @@ void Arguments::setup_hotswap_agent() {
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
||||
// com.sun.beans.introspect.ClassInfo access
|
||||
create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
||||
+ // com.sun.beans.introspect.util.Cache access
|
||||
+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++);
|
||||
|
||||
}
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..6636e4dd62a
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans.introspect;
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/package-info.java b/src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..5c097eeaa53
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans;
|
||||
diff --git a/src/java.desktop/share/classes/com/sun/beans/util/package-info.java b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
new file mode 100644
|
||||
index 00000000000..2d5d735ffa8
|
||||
--- /dev/null
|
||||
+++ b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
+ *
|
||||
+ * This code is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 only, as
|
||||
+ * published by the Free Software Foundation. Oracle designates this
|
||||
+ * particular file as subject to the "Classpath" exception as provided
|
||||
+ * by Oracle in the LICENSE file that accompanied this code.
|
||||
+ *
|
||||
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||||
+ * accompanied this code).
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License version
|
||||
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||||
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
+ * or visit www.oracle.com if you need additional information or have any
|
||||
+ * questions.
|
||||
+ */
|
||||
+
|
||||
+package com.sun.beans.util;
|
||||
diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java
|
||||
index f9cf021311f..e61ba7572cf 100644
|
||||
--- a/src/java.desktop/share/classes/module-info.java
|
||||
+++ b/src/java.desktop/share/classes/module-info.java
|
||||
@@ -104,6 +104,9 @@ module java.desktop {
|
||||
exports javax.swing.text.rtf;
|
||||
exports javax.swing.tree;
|
||||
exports javax.swing.undo;
|
||||
+ exports com.sun.beans;
|
||||
+ exports com.sun.beans.introspect;
|
||||
+ exports com.sun.beans.util;
|
||||
|
||||
// qualified exports may be inserted at build time
|
||||
// see make/GensrcModuleInfo.gmk
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From baf26456579eb0e560471d3bcb150005492f69f4 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 17 May 2020 12:19:18 +0200
|
||||
Subject: [PATCH 37/48] Skip verifier only in AllowEnhancedClassRedefinition
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index c04bdf5abfc..e14aaee21c4 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -788,10 +788,10 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
|
||||
if (!is_linked()) {
|
||||
if (!is_rewritten()) {
|
||||
- // In cases, if class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
+ // (DCEVM): If class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C
|
||||
// then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification
|
||||
// on redefinition.
|
||||
- if (!newest_version()->is_redefining()) {
|
||||
+ if (!AllowEnhancedClassRedefinition || !newest_version()->is_redefining()) {
|
||||
bool verify_ok = verify_code(throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
From 46dc38a58ac8afafab4e04ee47a1ed2b9e65c1e1 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 17 May 2020 18:18:52 +0200
|
||||
Subject: [PATCH 38/48] Use original code for adjust_method_entries in standard
|
||||
redefinition
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 2 +-
|
||||
.../share/prims/resolvedMethodTable.cpp | 46 ++++++++++++++++++-
|
||||
.../share/prims/resolvedMethodTable.hpp | 1 +
|
||||
3 files changed, 47 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 660bf3a2e97..0ca675e8ee6 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -506,7 +506,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
- ResolvedMethodTable::adjust_method_entries(&trace_name_printed);
|
||||
+ ResolvedMethodTable::adjust_method_entries_dcevm(&trace_name_printed);
|
||||
}
|
||||
|
||||
ChangePointersOopClosure<StoreNoBarrier> oopClosureNoBarrier;
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index a9057893368..af2ec48c2e1 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -197,8 +197,52 @@ void ResolvedMethodTable::print() {
|
||||
#endif // PRODUCT
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
-// It is called at safepoint only for RedefineClasses
|
||||
+
|
||||
void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
+ // For each entry in RMT, change to new method
|
||||
+ for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
+ for (ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
+ entry != NULL;
|
||||
+ entry = entry->next()) {
|
||||
+
|
||||
+ oop mem_name = entry->object_no_keepalive();
|
||||
+ // except ones removed
|
||||
+ if (mem_name == NULL) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
+
|
||||
+ if (old_method->is_old()) {
|
||||
+
|
||||
+ Method* new_method;
|
||||
+ if (old_method->is_deleted()) {
|
||||
+ new_method = Universe::throw_no_such_method_error();
|
||||
+ } else {
|
||||
+ InstanceKlass* holder = old_method->method_holder();
|
||||
+ new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
+ assert(holder == new_method->method_holder(), "call after swapping redefined guts");
|
||||
+ assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
+ assert(old_method != new_method, "sanity check");
|
||||
+ }
|
||||
+
|
||||
+ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
|
||||
+
|
||||
+ ResourceMark rm;
|
||||
+ if (!(*trace_name_printed)) {
|
||||
+ log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
+ *trace_name_printed = true;
|
||||
+ }
|
||||
+ log_debug(redefine, class, update, constantpool)
|
||||
+ ("ResolvedMethod method update: %s(%s)",
|
||||
+ new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// (DCEVM) It is called at safepoint only for RedefineClasses
|
||||
+void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
// For each entry in RMT, change to new method
|
||||
GrowableArray<oop>* oops_to_add = new GrowableArray<oop>();
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.hpp b/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
index 841ae4ae585..543d4ffa485 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
#if INCLUDE_JVMTI
|
||||
// It is called at safepoint only for RedefineClasses
|
||||
static void adjust_method_entries(bool * trace_name_printed);
|
||||
+ static void adjust_method_entries_dcevm(bool * trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Cleanup cleared entries
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 6ac099d1b07fcc0d3c17ebd5d3335bcb6ceaedc9 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 09:41:36 +0200
|
||||
Subject: [PATCH 39/48] Revert code for !AllowEnhancedClassRedefinition
|
||||
|
||||
---
|
||||
.../share/classfile/classLoaderData.cpp | 23 ++++++++++---------
|
||||
1 file changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index 25103fff2c0..f5b877b432b 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -1387,12 +1387,13 @@ bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
|
||||
// Klassesoto delete.
|
||||
|
||||
// FIXME: dcevm - block asserts in MetadataOnStackMark
|
||||
- /*
|
||||
- bool walk_all_metadata = clean_previous_versions &&
|
||||
- JvmtiExport::has_redefined_a_class() &&
|
||||
- InstanceKlass::has_previous_versions_and_reset();
|
||||
- MetadataOnStackMark md_on_stack(walk_all_metadata);
|
||||
- */
|
||||
+ bool walk_all_metadata = false;
|
||||
+ if (!AllowEnhancedClassRedefinition) {
|
||||
+ walk_all_metadata = clean_previous_versions &&
|
||||
+ JvmtiExport::has_redefined_a_class() &&
|
||||
+ InstanceKlass::has_previous_versions_and_reset();
|
||||
+ MetadataOnStackMark md_on_stack(walk_all_metadata);
|
||||
+ }
|
||||
|
||||
// Save previous _unloading pointer for CMS which may add to unloading list before
|
||||
// purging and we don't want to rewalk the previously unloaded class loader data.
|
||||
@@ -1402,12 +1403,12 @@ bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
|
||||
while (data != NULL) {
|
||||
if (data->is_alive()) {
|
||||
// clean metaspace
|
||||
- /*
|
||||
- if (walk_all_metadata) {
|
||||
- data->classes_do(InstanceKlass::purge_previous_versions);
|
||||
+ if (!AllowEnhancedClassRedefinition) {
|
||||
+ if (walk_all_metadata) {
|
||||
+ data->classes_do(InstanceKlass::purge_previous_versions);
|
||||
+ }
|
||||
+ data->free_deallocate_list();
|
||||
}
|
||||
- data->free_deallocate_list();
|
||||
- */
|
||||
prev = data;
|
||||
data = data->next();
|
||||
loaders_processed++;
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
278
jb/project/tools/patches/dcevm/0040-Code-cleanup.patch
Normal file
278
jb/project/tools/patches/dcevm/0040-Code-cleanup.patch
Normal file
@@ -0,0 +1,278 @@
|
||||
From de04154ee21d33c1ac1b74b2740f2fda117c0430 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 09:29:39 +0200
|
||||
Subject: [PATCH 40/48] Code cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/classfile/classFileParser.cpp | 4 +++-
|
||||
src/hotspot/share/classfile/classFileParser.hpp | 2 +-
|
||||
src/hotspot/share/classfile/classLoaderData.cpp | 2 ++
|
||||
src/hotspot/share/classfile/dictionary.cpp | 4 ++++
|
||||
src/hotspot/share/classfile/dictionary.hpp | 1 +
|
||||
src/hotspot/share/classfile/loaderConstraints.cpp | 3 ++-
|
||||
src/hotspot/share/classfile/systemDictionary.cpp | 8 +++++---
|
||||
src/hotspot/share/interpreter/linkResolver.cpp | 1 +
|
||||
src/hotspot/share/memory/universe.cpp | 4 ++--
|
||||
src/hotspot/share/oops/instanceKlass.cpp | 13 ++++++++-----
|
||||
10 files changed, 29 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
|
||||
index ea150df9104..c2cd35da4e6 100644
|
||||
--- a/src/hotspot/share/classfile/classFileParser.cpp
|
||||
+++ b/src/hotspot/share/classfile/classFileParser.cpp
|
||||
@@ -954,6 +954,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
CHECK);
|
||||
}
|
||||
|
||||
+ // (DCEVM) pick newest
|
||||
interf = (Klass *) maybe_newest(interf);
|
||||
|
||||
if (!interf->is_interface()) {
|
||||
@@ -3749,6 +3750,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp,
|
||||
// However, make sure it is not an array type.
|
||||
bool is_array = false;
|
||||
if (cp->tag_at(super_class_index).is_klass()) {
|
||||
+ // (DCEVM) pick newest
|
||||
super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index)));
|
||||
if (need_verify)
|
||||
is_array = super_klass->is_array_klass();
|
||||
@@ -4417,7 +4419,7 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
|
||||
if (!_has_empty_finalizer) {
|
||||
if (_has_finalizer ||
|
||||
(super != NULL && super->has_finalizer())) {
|
||||
- // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active
|
||||
+ // FIXME - (DCEVM) this is condition from previous DCEVM version, however after reload a new finalize() method is not active
|
||||
if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) {
|
||||
ik->set_has_finalizer();
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
index 3db14b678f3..93ed54d8f70 100644
|
||||
--- a/src/hotspot/share/classfile/classFileParser.hpp
|
||||
+++ b/src/hotspot/share/classfile/classFileParser.hpp
|
||||
@@ -499,7 +499,7 @@ class ClassFileParser {
|
||||
FieldLayoutInfo* info,
|
||||
TRAPS);
|
||||
|
||||
- // Enhanced class redefinition
|
||||
+ // (DCEVM) Enhanced class redefinition
|
||||
inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; }
|
||||
|
||||
public:
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index f5b877b432b..ab2615da0ed 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -1242,6 +1242,7 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) - iterate over dict classes
|
||||
void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->classes_do(klass_closure);
|
||||
@@ -1257,6 +1258,7 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS),
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) rollback redefined classes
|
||||
void ClassLoaderDataGraph::rollback_redefinition() {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->rollback_redefinition();
|
||||
diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp
|
||||
index 118730f1b83..dda5188c370 100644
|
||||
--- a/src/hotspot/share/classfile/dictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/dictionary.cpp
|
||||
@@ -245,6 +245,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) {
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
+// (DCEVM) iterate over dict entry
|
||||
void Dictionary::classes_do(KlassClosure* closure) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
@@ -342,6 +344,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+// (DCEVM) replace old_class by new class in dictionary
|
||||
bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) {
|
||||
// There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class.
|
||||
bool found = false;
|
||||
@@ -356,6 +359,7 @@ bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData*
|
||||
return found;
|
||||
}
|
||||
|
||||
+// (DCEVM) rollback redefinition
|
||||
void Dictionary::rollback_redefinition() {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* entry = bucket(index);
|
||||
diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp
|
||||
index fd4b134d7a7..5eaa741d500 100644
|
||||
--- a/src/hotspot/share/classfile/dictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/dictionary.hpp
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
|
||||
void rollback_redefinition();
|
||||
|
||||
+ // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k"
|
||||
static InstanceKlass* old_if_redefined(InstanceKlass* k) {
|
||||
return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k;
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
index e4a23e8a27c..bca73b5e0dc 100644
|
||||
--- a/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
+++ b/src/hotspot/share/classfile/loaderConstraints.cpp
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
- * published by the Free Software Foundation.
|
||||
+ * published by the Free Software Foundation) replace old_class by new class in dictionary.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
@@ -87,6 +87,7 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
|
||||
return pp;
|
||||
}
|
||||
|
||||
+// (DCEVM) update constraint entries to new classes, called from dcevm redefinition code only
|
||||
void LoaderConstraintTable::update_after_redefinition() {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
LoaderConstraintEntry** p = bucket_addr(index);
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index 9dbd6cc9c12..e70865109dd 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -876,7 +876,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
ClassLoaderData* loader_data = k->class_loader_data();
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
Klass* kk = find_class(name, loader_data);
|
||||
- // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version())
|
||||
+ // FIXME: (DCEVM)
|
||||
+ // assert(kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version())
|
||||
assert(kk == k, "should be present in dictionary");
|
||||
}
|
||||
#endif
|
||||
@@ -1083,7 +1084,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
InstanceKlass* k = NULL;
|
||||
|
||||
#if INCLUDE_CDS
|
||||
- // FIXME: what to do during redefinition?
|
||||
+ // FIXME: (DCEVM) what to do during redefinition?
|
||||
if (!DumpSharedSpaces) {
|
||||
k = SystemDictionaryShared::lookup_from_stream(class_name,
|
||||
class_loader,
|
||||
@@ -1836,7 +1837,7 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||
CodeCache::flush_dependents_on(k);
|
||||
}
|
||||
|
||||
-// Enhanced class redefinition
|
||||
+// (DCEVM) - remove from klass hierarchy
|
||||
void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
assert(k != NULL, "just checking");
|
||||
|
||||
@@ -1844,6 +1845,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
k->remove_from_sibling_list();
|
||||
}
|
||||
|
||||
+// (DCEVM)
|
||||
void SystemDictionary::update_constraints_after_redefinition() {
|
||||
constraints()->update_after_redefinition();
|
||||
}
|
||||
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
index cb76d2ef50c..9dc184d02f5 100644
|
||||
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
||||
@@ -1384,6 +1384,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
|
||||
assert(resolved_method->can_be_statically_bound(), "cannot override this method");
|
||||
selected_method = resolved_method;
|
||||
} else {
|
||||
+ // TODO: (DCEVM) explain
|
||||
assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent");
|
||||
selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
|
||||
}
|
||||
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
|
||||
index 7ecb950b231..d0a6d665aa0 100644
|
||||
--- a/src/hotspot/share/memory/universe.cpp
|
||||
+++ b/src/hotspot/share/memory/universe.cpp
|
||||
@@ -176,7 +176,7 @@ void Universe::basic_type_classes_do(void f(Klass*)) {
|
||||
f(doubleArrayKlassObj());
|
||||
}
|
||||
|
||||
-// FIXME: This method should iterate all pointers that are not within heap objects.
|
||||
+// FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects.
|
||||
void Universe::root_oops_do(OopClosure *oopClosure) {
|
||||
|
||||
class AlwaysTrueClosure: public BoolObjectClosure {
|
||||
@@ -203,7 +203,7 @@ void Universe::root_oops_do(OopClosure *oopClosure) {
|
||||
CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations);
|
||||
CodeCache::blobs_do(&blobClosure);
|
||||
StringTable::oops_do(oopClosure);
|
||||
-
|
||||
+
|
||||
// (DCEVM) TODO: Check if this is correct?
|
||||
//CodeCache::scavenge_root_nmethods_oops_do(oopClosure);
|
||||
//Management::oops_do(oopClosure);
|
||||
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
index e14aaee21c4..c860371d2fc 100644
|
||||
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
||||
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
||||
@@ -1139,6 +1139,7 @@ void InstanceKlass::init_implementor() {
|
||||
}
|
||||
}
|
||||
|
||||
+// (DCEVM) - init_implementor() for dcevm
|
||||
void InstanceKlass::init_implementor_from_redefine() {
|
||||
assert(is_interface(), "not interface");
|
||||
Klass** addr = adr_implementor();
|
||||
@@ -1209,6 +1210,8 @@ bool InstanceKlass::implements_interface(Klass* k) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
+
|
||||
+// (DCEVM)
|
||||
bool InstanceKlass::implements_interface_any_version(Klass* k) const {
|
||||
k = k->newest_version();
|
||||
if (this->newest_version() == k) return true;
|
||||
@@ -1491,10 +1494,8 @@ void InstanceKlass::methods_do(void f(Method* method)) {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Update information contains mapping of fields from old class to the new class.
|
||||
- Info is stored on HEAP, you need to call clear_update_information to free the space.
|
||||
-*/
|
||||
+// (DCEVM) Update information contains mapping of fields from old class to the new class.
|
||||
+// Info is stored on HEAP, you need to call clear_update_information to free the space.
|
||||
void InstanceKlass::store_update_information(GrowableArray<int> &values) {
|
||||
int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass);
|
||||
for (int i = 0; i < values.length(); i++) {
|
||||
@@ -2162,6 +2163,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
|
||||
dependencies().add_dependent_nmethod(nm);
|
||||
}
|
||||
|
||||
+// DCEVM - update jmethod ids
|
||||
bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) {
|
||||
size_t idnum = (size_t)method->method_idnum();
|
||||
jmethodID* jmeths = methods_jmethod_ids_acquire();
|
||||
@@ -2177,7 +2179,7 @@ bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) {
|
||||
|
||||
void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
|
||||
dependencies().remove_dependent_nmethod(nm, delete_immediately);
|
||||
- // (DCEVM) Hack as dependencies get wrong version of Klass*
|
||||
+ // FIXME: (DCEVM) Hack as dependencies get wrong version of Klass*
|
||||
// if (this->old_version() != NULL) {
|
||||
// InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true);
|
||||
// return;
|
||||
@@ -3594,6 +3596,7 @@ void InstanceKlass::verify_on(outputStream* st) {
|
||||
}
|
||||
|
||||
guarantee(sib->is_klass(), "should be klass");
|
||||
+ // TODO: (DCEVM) explain
|
||||
guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass");
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From ab8888737eaed76776b41b28af93a0c47826b8d6 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 10:31:15 +0200
|
||||
Subject: [PATCH 41/48] Activate cpCache definition asserts for !dcevm
|
||||
|
||||
---
|
||||
src/hotspot/share/oops/cpCache.cpp | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
|
||||
index 47040d51f0c..4318df227d1 100644
|
||||
--- a/src/hotspot/share/oops/cpCache.cpp
|
||||
+++ b/src/hotspot/share/oops/cpCache.cpp
|
||||
@@ -436,8 +436,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
|
||||
if (has_appendix) {
|
||||
const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
|
||||
assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
|
||||
- // FIXME (DCEVM) relaxing for now...
|
||||
- //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
|
||||
+ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(appendix_index) == NULL, "init just once");
|
||||
resolved_references->obj_at_put(appendix_index, appendix());
|
||||
}
|
||||
|
||||
@@ -445,8 +444,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
|
||||
if (has_method_type) {
|
||||
const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset;
|
||||
assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob");
|
||||
- // FIXME (DCEVM) relaxing for now...
|
||||
- //assert(resolved_references->obj_at(method_type_index) == NULL, "init just once");
|
||||
+ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(method_type_index) == NULL, "init just once");
|
||||
resolved_references->obj_at_put(method_type_index, method_type());
|
||||
}
|
||||
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 8596cf8b677eadcd18b527dd61c891475758bbaa Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Tue, 19 May 2020 10:54:38 +0200
|
||||
Subject: [PATCH 42/48] iterate old method version only in dcevm
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiImpl.cpp | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
index 2a92ece916e..d2044541d38 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp
|
||||
@@ -294,8 +294,10 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
|
||||
Symbol* m_signature = _method->signature();
|
||||
|
||||
// (DCEVM) Go through old versions of method
|
||||
- for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) {
|
||||
- (m->*meth_act)(_bci);
|
||||
+ if (AllowEnhancedClassRedefinition) {
|
||||
+ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) {
|
||||
+ (m->*meth_act)(_bci);
|
||||
+ }
|
||||
}
|
||||
|
||||
// search previous versions if they exist
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
From f3c1667fc04abdd9aa556b2c00a23239eba14287 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 22 May 2020 21:23:01 +0200
|
||||
Subject: [PATCH 43/48] Support for Lambda class redefinition
|
||||
|
||||
---
|
||||
.../share/classfile/classLoaderData.cpp | 9 +++
|
||||
.../share/classfile/classLoaderData.hpp | 1 +
|
||||
.../share/classfile/systemDictionary.cpp | 12 +++-
|
||||
.../share/classfile/systemDictionary.hpp | 2 +
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 65 +++++++++++++++++--
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 1 +
|
||||
.../share/prims/resolvedMethodTable.cpp | 4 +-
|
||||
src/hotspot/share/prims/unsafe.cpp | 1 +
|
||||
8 files changed, 85 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
index ab2615da0ed..1bc67adf5a7 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
||||
@@ -663,6 +663,15 @@ Dictionary* ClassLoaderData::create_dictionary() {
|
||||
return new Dictionary(this, size, resizable);
|
||||
}
|
||||
|
||||
+void ClassLoaderData::exchange_holders(ClassLoaderData* cld) {
|
||||
+ oop holder_oop = _holder.peek();
|
||||
+ _holder.replace(cld->_holder.peek());
|
||||
+ cld->_holder.replace(holder_oop);
|
||||
+ WeakHandle<vm_class_loader_data> exchange = _holder;
|
||||
+ _holder = cld->_holder;
|
||||
+ cld->_holder = exchange;
|
||||
+}
|
||||
+
|
||||
// Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph
|
||||
oop ClassLoaderData::holder_phantom() const {
|
||||
// A klass that was previously considered dead can be looked up in the
|
||||
diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
index 7e357929971..00a84610b43 100644
|
||||
--- a/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
+++ b/src/hotspot/share/classfile/classLoaderData.hpp
|
||||
@@ -292,6 +292,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = true; }
|
||||
void clear_accumulated_modified_oops() { _accumulated_modified_oops = false; }
|
||||
bool has_accumulated_modified_oops() { return _accumulated_modified_oops; }
|
||||
+ void exchange_holders(ClassLoaderData* cld);
|
||||
private:
|
||||
|
||||
void unload();
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
index e70865109dd..cc9f1fa7831 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
||||
@@ -971,12 +971,16 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const InstanceKlass* host_klass,
|
||||
+ InstanceKlass* old_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS) {
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
|
||||
ClassLoaderData* loader_data;
|
||||
+
|
||||
+ bool is_redefining = (old_klass != NULL);
|
||||
+
|
||||
if (host_klass != NULL) {
|
||||
// Create a new CLD for anonymous class, that uses the same class loader
|
||||
// as the host_klass
|
||||
@@ -1000,8 +1004,12 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
protection_domain,
|
||||
host_klass,
|
||||
cp_patches,
|
||||
- false, // pick_newest
|
||||
+ is_redefining, // pick_newest
|
||||
CHECK_NULL);
|
||||
+ if (is_redefining && k != NULL) {
|
||||
+ k->set_redefining(true);
|
||||
+ k->set_old_version(old_klass);
|
||||
+ }
|
||||
|
||||
if (host_klass != NULL && k != NULL) {
|
||||
// Anonymous classes must update ClassLoaderData holder (was host_klass loader)
|
||||
@@ -1845,7 +1853,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
|
||||
k->remove_from_sibling_list();
|
||||
}
|
||||
|
||||
-// (DCEVM)
|
||||
+// (DCEVM)
|
||||
void SystemDictionary::update_constraints_after_redefinition() {
|
||||
constraints()->update_after_redefinition();
|
||||
}
|
||||
diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
index 717f34ce9a0..dc111846c12 100644
|
||||
--- a/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
|
||||
@@ -301,6 +301,7 @@ public:
|
||||
protection_domain,
|
||||
st,
|
||||
NULL, // host klass
|
||||
+ NULL, // old class
|
||||
NULL, // cp_patches
|
||||
THREAD);
|
||||
}
|
||||
@@ -309,6 +310,7 @@ public:
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const InstanceKlass* host_klass,
|
||||
+ InstanceKlass* old_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS);
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 0ca675e8ee6..08fe42d5c28 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -503,6 +503,8 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
||||
|
||||
|
||||
+ // SystemDictionary::methods_do(fix_invoke_method);
|
||||
+
|
||||
// JSR-292 support
|
||||
if (_any_class_has_resolved_methods) {
|
||||
bool trace_name_printed = false;
|
||||
@@ -774,12 +776,34 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
// load hook event.
|
||||
state->set_class_being_redefined(the_class, _class_load_kind);
|
||||
|
||||
- InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym,
|
||||
- the_class_loader,
|
||||
- protection_domain,
|
||||
- &st,
|
||||
- the_class,
|
||||
- THREAD);
|
||||
+ InstanceKlass* k;
|
||||
+
|
||||
+ if (InstanceKlass::cast(the_class)->is_anonymous()) {
|
||||
+ const InstanceKlass* host_class = the_class->host_klass();
|
||||
+
|
||||
+ // Make sure it's the real host class, not another anonymous class.
|
||||
+ while (host_class != NULL && host_class->is_anonymous()) {
|
||||
+ host_class = host_class->host_klass();
|
||||
+ }
|
||||
+
|
||||
+ k = SystemDictionary::parse_stream(the_class_sym,
|
||||
+ the_class_loader,
|
||||
+ protection_domain,
|
||||
+ &st,
|
||||
+ host_class,
|
||||
+ the_class,
|
||||
+ NULL,
|
||||
+ THREAD);
|
||||
+ k->class_loader_data()->exchange_holders(the_class->class_loader_data());
|
||||
+ the_class->class_loader_data()->inc_keep_alive();
|
||||
+ } else {
|
||||
+ k = SystemDictionary::resolve_from_stream(the_class_sym,
|
||||
+ the_class_loader,
|
||||
+ protection_domain,
|
||||
+ &st,
|
||||
+ the_class,
|
||||
+ THREAD);
|
||||
+ }
|
||||
// Clear class_being_redefined just to be sure.
|
||||
state->clear_class_being_redefined();
|
||||
|
||||
@@ -1469,6 +1493,30 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
|
||||
}
|
||||
}
|
||||
|
||||
+void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) {
|
||||
+
|
||||
+ constantPoolHandle other_cp = constantPoolHandle(method->constants());
|
||||
+
|
||||
+ for (int i = 0; i < other_cp->length(); i++) {
|
||||
+ if (other_cp->tag_at(i).is_klass()) {
|
||||
+ Klass* klass = other_cp->resolved_klass_at(i);
|
||||
+ if (klass->new_version() != NULL) {
|
||||
+ // Constant pool entry points to redefined class -- update to the new version
|
||||
+ other_cp->klass_at_put(i, klass->newest_version());
|
||||
+ }
|
||||
+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ConstantPoolCache* cp_cache = other_cp->cache();
|
||||
+ if (cp_cache != NULL) {
|
||||
+ cp_cache->clear_entries();
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
||||
for (int j = 0; j < _matching_methods_length; ++j) {
|
||||
Method* old_method = _matching_old_methods[j];
|
||||
@@ -2018,7 +2066,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
// Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined)
|
||||
AffectedKlassClosure closure(_affected_klasses);
|
||||
// Updated in j10, from original SystemDictionary::classes_do
|
||||
- ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
+
|
||||
+ ClassLoaderDataGraph::classes_do(&closure);
|
||||
+ //ClassLoaderDataGraph::dictionary_classes_do(&closure);
|
||||
+
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
// Sort the affected klasses such that a supertype is always on a smaller array index than its subtype.
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index ed44f0e27ce..7e2afd49650 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -119,6 +119,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
void rollback();
|
||||
static void mark_as_scavengable(nmethod* nm);
|
||||
static void unpatch_bytecode(Method* method);
|
||||
+ static void fix_invoke_method(Method* method);
|
||||
|
||||
// Figure out which new methods match old methods in name and signature,
|
||||
// which methods have been added, and which are no longer present
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index af2ec48c2e1..7741328979f 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -200,7 +200,7 @@ void ResolvedMethodTable::print() {
|
||||
|
||||
void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
- // For each entry in RMT, change to new method
|
||||
+ // For each entry in RMT, change to new methodadjust_method_entries_dcevm
|
||||
for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
for (ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
entry != NULL;
|
||||
@@ -271,6 +271,8 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
+
|
||||
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != newer_method, "sanity check");
|
||||
diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp
|
||||
index 2f14e01ce0d..d0e0367d8eb 100644
|
||||
--- a/src/hotspot/share/prims/unsafe.cpp
|
||||
+++ b/src/hotspot/share/prims/unsafe.cpp
|
||||
@@ -818,6 +818,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
|
||||
host_domain,
|
||||
&st,
|
||||
InstanceKlass::cast(host_klass),
|
||||
+ NULL,
|
||||
cp_patches,
|
||||
CHECK_NULL);
|
||||
if (anonk == NULL) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From b8a3d4249eb97613f796edc709e414900c9a0828 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Fri, 22 May 2020 21:43:22 +0200
|
||||
Subject: [PATCH 44/48] Skip GC runs for redefinitions without instance size
|
||||
change
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 08fe42d5c28..a785a43d352 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -578,14 +578,14 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
}
|
||||
|
||||
-// if (objectClosure.needs_instance_update()) {
|
||||
+ if (objectClosure.needs_instance_update()) {
|
||||
// Do a full garbage collection to update the instance sizes accordingly
|
||||
Universe::set_redefining_gc_run(true);
|
||||
notify_gc_begin(true);
|
||||
Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection);
|
||||
notify_gc_end();
|
||||
Universe::set_redefining_gc_run(false);
|
||||
-// }
|
||||
+ }
|
||||
|
||||
// Unmark Klass*s as "redefining"
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
From 77bdf6253c457ed88436fb4da6a53c7c0c361a1c Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 23 May 2020 10:02:15 +0200
|
||||
Subject: [PATCH 45/48] Fix "no original bytecode found" error if method with
|
||||
bkp is missing
|
||||
|
||||
Sometimes IDE can deploy class with erroneous method, such method has
|
||||
no bytecode, but breakpoint position can still exist.
|
||||
---
|
||||
src/hotspot/share/interpreter/bytecodes.cpp | 2 +-
|
||||
.../share/interpreter/interpreterRuntime.cpp | 2 +-
|
||||
src/hotspot/share/oops/method.cpp | 8 ++++----
|
||||
src/hotspot/share/oops/method.hpp | 4 ++--
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++--------
|
||||
5 files changed, 18 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/interpreter/bytecodes.cpp b/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
index e377e36b88c..262ecc021b2 100644
|
||||
--- a/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
+++ b/src/hotspot/share/interpreter/bytecodes.cpp
|
||||
@@ -84,7 +84,7 @@ Bytecodes::Code Bytecodes::code_at(Method* method, int bci) {
|
||||
Bytecodes::Code Bytecodes::non_breakpoint_code_at(const Method* method, address bcp) {
|
||||
assert(method != NULL, "must have the method for breakpoint conversion");
|
||||
assert(method->contains(bcp), "must be valid bcp in method");
|
||||
- return method->orig_bytecode_at(method->bci_from(bcp));
|
||||
+ return method->orig_bytecode_at(method->bci_from(bcp), false);
|
||||
}
|
||||
|
||||
int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) {
|
||||
diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
index f367e658879..71bbd15a4f5 100644
|
||||
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp
|
||||
@@ -834,7 +834,7 @@ IRT_END
|
||||
// Invokes
|
||||
|
||||
IRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp))
|
||||
- return method->orig_bytecode_at(method->bci_from(bcp));
|
||||
+ return method->orig_bytecode_at(method->bci_from(bcp), false);
|
||||
IRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code))
|
||||
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
|
||||
index bee69f9cec6..f1e22db70d6 100644
|
||||
--- a/src/hotspot/share/oops/method.cpp
|
||||
+++ b/src/hotspot/share/oops/method.cpp
|
||||
@@ -1747,14 +1747,14 @@ bool CompressedLineNumberReadStream::read_pair() {
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
|
||||
-Bytecodes::Code Method::orig_bytecode_at(int bci) const {
|
||||
+Bytecodes::Code Method::orig_bytecode_at(int bci, bool no_fatal) const {
|
||||
BreakpointInfo* bp = method_holder()->breakpoints();
|
||||
for (; bp != NULL; bp = bp->next()) {
|
||||
if (bp->match(this, bci)) {
|
||||
return bp->orig_bytecode();
|
||||
}
|
||||
}
|
||||
- {
|
||||
+ if (!no_fatal) {
|
||||
ResourceMark rm;
|
||||
fatal("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci);
|
||||
}
|
||||
@@ -1900,7 +1900,7 @@ BreakpointInfo::BreakpointInfo(Method* m, int bci) {
|
||||
_signature_index = m->signature_index();
|
||||
_orig_bytecode = (Bytecodes::Code) *m->bcp_from(_bci);
|
||||
if (_orig_bytecode == Bytecodes::_breakpoint)
|
||||
- _orig_bytecode = m->orig_bytecode_at(_bci);
|
||||
+ _orig_bytecode = m->orig_bytecode_at(_bci, false);
|
||||
_next = NULL;
|
||||
}
|
||||
|
||||
@@ -1909,7 +1909,7 @@ void BreakpointInfo::set(Method* method) {
|
||||
{
|
||||
Bytecodes::Code code = (Bytecodes::Code) *method->bcp_from(_bci);
|
||||
if (code == Bytecodes::_breakpoint)
|
||||
- code = method->orig_bytecode_at(_bci);
|
||||
+ code = method->orig_bytecode_at(_bci, false);
|
||||
assert(orig_bytecode() == code, "original bytecode must be the same");
|
||||
}
|
||||
#endif
|
||||
diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp
|
||||
index 4533476ff8f..193e1845b23 100644
|
||||
--- a/src/hotspot/share/oops/method.hpp
|
||||
+++ b/src/hotspot/share/oops/method.hpp
|
||||
@@ -230,7 +230,7 @@ class Method : public Metadata {
|
||||
|
||||
// JVMTI breakpoints
|
||||
#if !INCLUDE_JVMTI
|
||||
- Bytecodes::Code orig_bytecode_at(int bci) const {
|
||||
+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const {
|
||||
ShouldNotReachHere();
|
||||
return Bytecodes::_shouldnotreachhere;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class Method : public Metadata {
|
||||
};
|
||||
u2 number_of_breakpoints() const {return 0;}
|
||||
#else // !INCLUDE_JVMTI
|
||||
- Bytecodes::Code orig_bytecode_at(int bci) const;
|
||||
+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const;
|
||||
void set_orig_bytecode_at(int bci, Bytecodes::Code code);
|
||||
void set_breakpoint(int bci);
|
||||
void clear_breakpoint(int bci);
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index a785a43d352..2321483dcbd 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -1389,14 +1389,16 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
||||
|
||||
if (code == Bytecodes::_breakpoint) {
|
||||
int bci = method->bci_from(bcp);
|
||||
- code = method->orig_bytecode_at(bci);
|
||||
- java_code = Bytecodes::java_code(code);
|
||||
- if (code != java_code &&
|
||||
- (java_code == Bytecodes::_getfield ||
|
||||
- java_code == Bytecodes::_putfield ||
|
||||
- java_code == Bytecodes::_aload_0)) {
|
||||
- // Let breakpoint table handling unpatch bytecode
|
||||
- method->set_orig_bytecode_at(bci, java_code);
|
||||
+ code = method->orig_bytecode_at(bci, true);
|
||||
+ if (code != Bytecodes::_shouldnotreachhere) {
|
||||
+ java_code = Bytecodes::java_code(code);
|
||||
+ if (code != java_code &&
|
||||
+ (java_code == Bytecodes::_getfield ||
|
||||
+ java_code == Bytecodes::_putfield ||
|
||||
+ java_code == Bytecodes::_aload_0)) {
|
||||
+ // Let breakpoint table handling unpatch bytecode
|
||||
+ method->set_orig_bytecode_at(bci, java_code);
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
java_code = Bytecodes::java_code(code);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
From d3371d7d52bd4dc66efd4f6a946d5045b8bc8b2b Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sat, 23 May 2020 10:17:56 +0200
|
||||
Subject: [PATCH 46/48] Fix comments according hotspot formatting conventions
|
||||
|
||||
---
|
||||
.../prims/jvmtiEnhancedRedefineClasses.cpp | 191 +++++++-----------
|
||||
.../prims/jvmtiEnhancedRedefineClasses.hpp | 41 ++--
|
||||
2 files changed, 90 insertions(+), 142 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 2321483dcbd..8d00203fd9a 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -67,21 +67,19 @@ int VM_EnhancedRedefineClasses::_deleted_methods_length = 0;
|
||||
int VM_EnhancedRedefineClasses::_added_methods_length = 0;
|
||||
Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL;
|
||||
|
||||
-/**
|
||||
- * Create new instance of enhanced class redefiner.
|
||||
- *
|
||||
- * This class implements VM_GC_Operation - the usual usage should be:
|
||||
- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
- * VMThread::execute(&op);
|
||||
- * Which
|
||||
- *
|
||||
- * @param class_count size of class_defs
|
||||
- * @param class_defs class definition - either new class or redefined class
|
||||
- * note that this is not the final array of classes to be redefined
|
||||
- * we need to scan for all affected classes (e.g. subclasses) and
|
||||
- * caculcate redefinition for them as well.
|
||||
- * @param class_load_kind always jvmti_class_load_kind_redefine
|
||||
- */
|
||||
+//
|
||||
+// Create new instance of enhanced class redefiner.
|
||||
+//
|
||||
+// This class implements VM_GC_Operation - the usual usage should be:
|
||||
+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
+// VMThread::execute(&op);
|
||||
+// Which
|
||||
+// - class_count size of class_defs
|
||||
+// - class_defs class definition - either new class or redefined class
|
||||
+// note that this is not the final array of classes to be redefined
|
||||
+// we need to scan for all affected classes (e.g. subclasses) and
|
||||
+// caculcate redefinition for them as well.
|
||||
+// @param class_load_kind always jvmti_class_load_kind_redefine
|
||||
VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) :
|
||||
VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) {
|
||||
_affected_klasses = NULL;
|
||||
@@ -97,12 +95,10 @@ static inline InstanceKlass* get_ik(jclass def) {
|
||||
return InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Start the redefinition:
|
||||
- * - Load new class definitions - @see load_new_class_versions
|
||||
- * - Start mark&sweep GC.
|
||||
- * @return true if success, otherwise all chnages are rollbacked.
|
||||
- */
|
||||
+// Start the redefinition:
|
||||
+// - Load new class definitions - @see load_new_class_versions
|
||||
+// - Start mark&sweep GC.
|
||||
+// - true if success, otherwise all chnages are rollbacked.
|
||||
bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
|
||||
if (_class_count == 0) {
|
||||
@@ -175,9 +171,7 @@ bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Closer for static fields - copy value from old class to the new class.
|
||||
- */
|
||||
+// Closer for static fields - copy value from old class to the new class.
|
||||
class FieldCopier : public FieldClosure {
|
||||
public:
|
||||
void do_field(fieldDescriptor* fd) {
|
||||
@@ -236,9 +230,7 @@ struct StoreNoBarrier {
|
||||
template <class T> static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); }
|
||||
};
|
||||
|
||||
-/**
|
||||
- Closure to scan all heap objects and update method handles
|
||||
-*/
|
||||
+// Closure to scan all heap objects and update method handles
|
||||
template <class S>
|
||||
class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// import java_lang_invoke_MemberName.*
|
||||
@@ -247,7 +239,6 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
|
||||
};
|
||||
|
||||
-
|
||||
bool update_member_name(oop obj) {
|
||||
int flags = java_lang_invoke_MemberName::flags(obj);
|
||||
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
|
||||
@@ -382,14 +373,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
}
|
||||
};
|
||||
|
||||
-/**
|
||||
- * Closure to scan all objects on heap for objects of changed classes
|
||||
- * - if the fields are compatible, only update class definition reference
|
||||
- * - otherwise if the new object size is smaller then old size, reshufle
|
||||
- * the fields and fill the gap with "dead_space"
|
||||
- * - otherwise set the _needs_instance_update flag, we need to do full GC
|
||||
- * and reshuffle object positions durring mark&sweep
|
||||
- */
|
||||
+// Closure to scan all objects on heap for objects of changed classes
|
||||
+// - if the fields are compatible, only update class definition reference
|
||||
+// - otherwise if the new object size is smaller then old size, reshufle
|
||||
+// the fields and fill the gap with "dead_space"
|
||||
+// - otherwise set the _needs_instance_update flag, we need to do full GC
|
||||
+// and reshuffle object positions durring mark&sweep
|
||||
class ChangePointersObjectClosure : public ObjectClosure {
|
||||
private:
|
||||
|
||||
@@ -451,19 +440,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
-/**
|
||||
- Main transformation method - runs in VM thread.
|
||||
-
|
||||
- - UseSharedSpaces - TODO what does it mean?
|
||||
- - for each sratch class call redefine_single_class
|
||||
- - clear code cache (flush_dependent_code)
|
||||
- - iterate the heap and update object defintions, check it old/new class fields
|
||||
- are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
- - iterate the heap and update method handles to new version
|
||||
- - Swap marks to have same hashcodes
|
||||
- - copy static fields
|
||||
- - notify JVM of the modification
|
||||
-*/
|
||||
+// Main transformation method - runs in VM thread.
|
||||
+// - UseSharedSpaces - TODO what does it mean?
|
||||
+// - for each sratch class call redefine_single_class
|
||||
+// - clear code cache (flush_dependent_code)
|
||||
+// - iterate the heap and update object defintions, check it old/new class fields
|
||||
+// are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
+// - iterate the heap and update method handles to new version
|
||||
+// - Swap marks to have same hashcodes
|
||||
+// - copy static fields
|
||||
+// - notify JVM of the modification
|
||||
void VM_EnhancedRedefineClasses::doit() {
|
||||
Thread *thread = Thread::current();
|
||||
|
||||
@@ -634,11 +620,9 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Cleanup - runs in JVM thread
|
||||
- * - free used memory
|
||||
- * - end GC
|
||||
- */
|
||||
+// Cleanup - runs in JVM thread
|
||||
+// - free used memory
|
||||
+// - end GC
|
||||
void VM_EnhancedRedefineClasses::doit_epilogue() {
|
||||
VM_GC_Operation::doit_epilogue();
|
||||
|
||||
@@ -670,11 +654,9 @@ void VM_EnhancedRedefineClasses::doit_epilogue() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Exclude java primitives and arrays from redefinition
|
||||
- * @param klass_mirror pointer to the klass
|
||||
- * @return true if is modifiable
|
||||
- */
|
||||
+// Exclude java primitives and arrays from redefinition
|
||||
+// - klass_mirror pointer to the klass
|
||||
+// - true if is modifiable
|
||||
bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
// classes for primitives cannot be redefined
|
||||
if (java_lang_Class::is_primitive(klass_mirror)) {
|
||||
@@ -693,17 +675,12 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
-
|
||||
- - find sorted affected classes
|
||||
- - resolve new class
|
||||
- - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
- - calculate modified fields and mapping to old fields
|
||||
- - link new classes
|
||||
-
|
||||
- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
-*/
|
||||
+// Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
+// - find sorted affected classes
|
||||
+// - resolve new class
|
||||
+// - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
+// - calculate modified fields and mapping to old fields
|
||||
+// - link new classes
|
||||
jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
|
||||
_affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(_class_count, true);
|
||||
@@ -898,9 +875,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Calculated the difference between new and old class (field change, method change, supertype change, ...).
|
||||
-*/
|
||||
+ // Calculated the difference between new and old class (field change, method change, supertype change, ...).
|
||||
int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) {
|
||||
int result = Klass::NoRedefinition;
|
||||
log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string());
|
||||
@@ -1183,14 +1158,11 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
}
|
||||
|
||||
|
||||
-/**
|
||||
- Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
-
|
||||
- @param the_class definition of a class, either existing class or new_class
|
||||
- @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
- @param class_byte_count - size of class_bytes
|
||||
- @param not_changed - new_class not available or same as current class
|
||||
-*/
|
||||
+// Searches for the class bytecode of the given class and returns it as a byte array.
|
||||
+// - the_class definition of a class, either existing class or new_class
|
||||
+// - class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode.
|
||||
+// - class_byte_count - size of class_bytes
|
||||
+// - not_changed - new_class not available or same as current class
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) {
|
||||
|
||||
*not_changed = false;
|
||||
@@ -1233,11 +1205,9 @@ jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Calculate difference between non static fields of old and new class and store the info into new class:
|
||||
- instanceKlass->store_update_information
|
||||
- instanceKlass->copy_backwards
|
||||
-*/
|
||||
+// Calculate difference between non static fields of old and new class and store the info into new class:
|
||||
+// instanceKlass->store_update_information
|
||||
+// instanceKlass->copy_backwards
|
||||
void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) {
|
||||
|
||||
class CalculateFieldUpdates : public FieldClosure {
|
||||
@@ -1348,9 +1318,7 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory.
|
||||
-*/
|
||||
+// Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory.
|
||||
void VM_EnhancedRedefineClasses::rollback() {
|
||||
log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res);
|
||||
ClassLoaderDataGraph::rollback_redefinition();
|
||||
@@ -1547,9 +1515,7 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Set method as obsolete / old / deleted.
|
||||
-*/
|
||||
+// Set method as obsolete / old / deleted.
|
||||
void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() {
|
||||
for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) {
|
||||
Method* old_method = _matching_old_methods[j];
|
||||
@@ -1771,12 +1737,9 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS)
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Compare _old_methods and _new_methods arrays and store the result into
|
||||
- _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
-
|
||||
- Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
-*/
|
||||
+// Compare _old_methods and _new_methods arrays and store the result into
|
||||
+// _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods
|
||||
+// Setup _old_methods and _new_methods before the call - it should be called for one class only!
|
||||
void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() {
|
||||
Method* old_method;
|
||||
Method* new_method;
|
||||
@@ -1900,7 +1863,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
||||
}
|
||||
*/
|
||||
|
||||
-
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
// increment the classRedefinedCount field in the_class and in any
|
||||
@@ -1940,9 +1902,7 @@ void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Logging of all methods (old, new, changed, ...)
|
||||
- */
|
||||
+// Logging of all methods (old, new, changed, ...)
|
||||
void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
int j;
|
||||
log_trace(redefine, class, dump)("_old_methods --");
|
||||
@@ -2002,9 +1962,7 @@ void VM_EnhancedRedefineClasses::dump_methods() {
|
||||
}
|
||||
}
|
||||
|
||||
-/**
|
||||
- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
-*/
|
||||
+// Helper class to traverse all loaded classes and figure out if the class is affected by redefinition.
|
||||
class AffectedKlassClosure : public KlassClosure {
|
||||
private:
|
||||
GrowableArray<Klass*>* _affected_klasses;
|
||||
@@ -2052,10 +2010,8 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
}
|
||||
};
|
||||
|
||||
-/**
|
||||
- Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
- Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
-*/
|
||||
+// Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
+// Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
for (int i = 0; i < _class_count; i++) {
|
||||
InstanceKlass* klass_handle = get_ik(_class_defs[i].klass);
|
||||
@@ -2086,9 +2042,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
-/**
|
||||
- Pairs of class dependencies (for topological sort)
|
||||
-*/
|
||||
+// Pairs of class dependencies (for topological sort)
|
||||
struct KlassPair {
|
||||
const Klass* _left;
|
||||
const Klass* _right;
|
||||
@@ -2101,14 +2055,11 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
return elem._right == value;
|
||||
}
|
||||
|
||||
-/**
|
||||
- For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
- First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
- Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
- For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
-
|
||||
- TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
-*/
|
||||
+// For each class to be redefined parse the bytecode and figure out the superclass and all interfaces.
|
||||
+// First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses).
|
||||
+// Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
+// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
+// TODO - the class file is potentionally parsed multiple times - introduce a cache?
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
ResourceMark mark(THREAD);
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
index 7e2afd49650..d8a11b51fe9 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
||||
@@ -35,17 +35,16 @@
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
|
||||
-/**
|
||||
- * Enhanced class redefiner.
|
||||
- *
|
||||
- * This class implements VM_GC_Operation - the usual usage should be:
|
||||
- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
- * VMThread::execute(&op);
|
||||
- * Which in turn runs:
|
||||
- * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions
|
||||
- * - doit() - main redefition, adjust existing objects on the heap, clear caches
|
||||
- * - doit_epilogue() - cleanup
|
||||
-*/
|
||||
+//
|
||||
+// Enhanced class redefiner.
|
||||
+//
|
||||
+// This class implements VM_GC_Operation - the usual usage should be:
|
||||
+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
||||
+// VMThread::execute(&op);
|
||||
+// Which in turn runs:
|
||||
+// - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions
|
||||
+// - doit() - main redefition, adjust existing objects on the heap, clear caches
|
||||
+// - doit_epilogue() - cleanup
|
||||
class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
private:
|
||||
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
||||
@@ -93,17 +92,15 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
// These routines are roughly in call order unless otherwise noted.
|
||||
|
||||
- /**
|
||||
- Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
-
|
||||
- - find sorted affected classes
|
||||
- - resolve new class
|
||||
- - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
- - calculate modified fields and mapping to old fields
|
||||
- - link new classes
|
||||
-
|
||||
- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
- */
|
||||
+ // Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
||||
+ //
|
||||
+ // - find sorted affected classes
|
||||
+ // - resolve new class
|
||||
+ // - calculate redefine flags (field change, method change, supertype change, ...)
|
||||
+ // - calculate modified fields and mapping to old fields
|
||||
+ // - link new classes
|
||||
+ //
|
||||
+ // The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
jvmtiError load_new_class_versions(TRAPS);
|
||||
|
||||
// Searches for all affected classes and performs a sorting such tha
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 2ad306a4cce06cfccf95a1193daf5b968ec1fa87 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 24 May 2020 12:07:09 +0200
|
||||
Subject: [PATCH 47/48] Review threads, cleanup
|
||||
|
||||
---
|
||||
src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
index 8d00203fd9a..1fbba406087 100644
|
||||
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
||||
@@ -253,7 +253,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// Note: we might set NULL at this point, which should force AbstractMethodError at runtime
|
||||
Thread *thread = Thread::current();
|
||||
CallInfo info(new_method, newest, thread);
|
||||
- Handle objHandle(thread, obj); // TODO : review thread
|
||||
+ Handle objHandle(thread, obj);
|
||||
MethodHandles::init_method_MemberName(objHandle, info);
|
||||
} else {
|
||||
java_lang_invoke_MemberName::set_method(obj, NULL);
|
||||
@@ -280,7 +280,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version());
|
||||
fieldDescriptor fd_new;
|
||||
if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) {
|
||||
- Handle objHandle(Thread::current(), obj); // TODO : review thread
|
||||
+ Handle objHandle(Thread::current(), obj);
|
||||
MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind));
|
||||
} else {
|
||||
// Matching field is not found in new version, not much we can do here.
|
||||
@@ -441,10 +441,9 @@ public:
|
||||
|
||||
|
||||
// Main transformation method - runs in VM thread.
|
||||
-// - UseSharedSpaces - TODO what does it mean?
|
||||
-// - for each sratch class call redefine_single_class
|
||||
+// - for each scratch class call redefine_single_class
|
||||
// - clear code cache (flush_dependent_code)
|
||||
-// - iterate the heap and update object defintions, check it old/new class fields
|
||||
+// - iterate the heap and update object definitions, check it old/new class fields
|
||||
// are compatible. If new class size is smaller then old, it can be solved directly here.
|
||||
// - iterate the heap and update method handles to new version
|
||||
// - Swap marks to have same hashcodes
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From a5586aff03fde654102e2c2e1fc19fdea406b31e Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Dvorak <lada.dvorak7@gmail.com>
|
||||
Date: Sun, 24 May 2020 12:07:42 +0200
|
||||
Subject: [PATCH 48/48] Replace deleted method with
|
||||
Universe::throw_no_such_method_error
|
||||
|
||||
---
|
||||
.../share/prims/resolvedMethodTable.cpp | 28 +++++++++----------
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
index 7741328979f..06581643c3b 100644
|
||||
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
|
||||
@@ -261,25 +261,25 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed)
|
||||
|
||||
if (old_method->is_old()) {
|
||||
|
||||
+ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
+ Method* newer_method;
|
||||
+
|
||||
// Method* new_method;
|
||||
if (old_method->is_deleted()) {
|
||||
- // FIXME:(DCEVM) - check if exception can be thrown
|
||||
- // new_method = Universe::throw_no_such_method_error();
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
|
||||
- Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
+ newer_method = Universe::throw_no_such_method_error();
|
||||
+ } else {
|
||||
+ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
|
||||
|
||||
- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
- assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
- assert(old_method != newer_method, "sanity check");
|
||||
+ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
|
||||
+ assert(newer_method != NULL, "method_with_idnum() should not be NULL");
|
||||
+ assert(old_method != newer_method, "sanity check");
|
||||
|
||||
- if (_the_table->lookup(newer_method) != NULL) {
|
||||
- // old method was already adjusted if new method exists in _the_table
|
||||
- continue;
|
||||
+ if (_the_table->lookup(newer_method) != NULL) {
|
||||
+ // old method was already adjusted if new method exists in _the_table
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
|
||||
--
|
||||
2.24.3 (Apple Git-128)
|
||||
|
||||
107
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
107
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/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 $?
|
||||
}
|
||||
|
||||
WITH_DEBUG_LEVEL="--with-debug-level=release"
|
||||
RELEASE_NAME=windows-x86_64-server-release
|
||||
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
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" == "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" == "fd" ]; then
|
||||
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
do_exit 0
|
||||
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" == "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
|
||||
@@ -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
|
||||
|
||||
@@ -272,12 +272,14 @@ XEvent.xclient 0
|
||||
XEvent.xcolormap 0
|
||||
XEvent.xconfigure 0
|
||||
XEvent.xconfigurerequest 0
|
||||
XEvent.xcookie 0
|
||||
XEvent.xcreatewindow 0
|
||||
XEvent.xcrossing 0
|
||||
XEvent.xdestroywindow 0
|
||||
XEvent.xerror 0
|
||||
XEvent.xexpose 0
|
||||
XEvent.xfocus 0
|
||||
XEvent.xgeneric 0
|
||||
XEvent.xgraphicsexpose 0
|
||||
XEvent.xgravity 0
|
||||
XEvent.xkey 0
|
||||
@@ -370,6 +372,22 @@ XGCValues.subwindow_mode 64
|
||||
XGCValues.tile 44
|
||||
XGCValues.ts_x_origin 52
|
||||
XGCValues.ts_y_origin 56
|
||||
XGenericEvent 24
|
||||
XGenericEventCookie 32
|
||||
XGenericEventCookie.cookie 24
|
||||
XGenericEventCookie.data 28
|
||||
XGenericEventCookie.display 12
|
||||
XGenericEventCookie.evtype 20
|
||||
XGenericEventCookie.extension 16
|
||||
XGenericEventCookie.send_event 8
|
||||
XGenericEventCookie.serial 4
|
||||
XGenericEventCookie.type 0
|
||||
XGenericEvent.display 12
|
||||
XGenericEvent.evtype 20
|
||||
XGenericEvent.extension 16
|
||||
XGenericEvent.send_event 8
|
||||
XGenericEvent.serial 4
|
||||
XGenericEvent.type 0
|
||||
XGraphicsExposeEvent 48
|
||||
XGraphicsExposeEvent.count 36
|
||||
XGraphicsExposeEvent.display 12
|
||||
@@ -396,6 +414,9 @@ XHostAddress 12
|
||||
XHostAddress.address 8
|
||||
XHostAddress.family 0
|
||||
XHostAddress.length 4
|
||||
XIButtonState 8
|
||||
XIButtonState.mask 4
|
||||
XIButtonState.mask_len 0
|
||||
XIconSize 24
|
||||
XIconSize.height_inc 20
|
||||
XIconSize.max_height 12
|
||||
@@ -403,6 +424,29 @@ XIconSize.max_width 8
|
||||
XIconSize.min_height 4
|
||||
XIconSize.min_width 0
|
||||
XIconSize.width_inc 16
|
||||
XIDeviceEvent 140
|
||||
XIDeviceEvent.buttons 88
|
||||
XIDeviceEvent.child 48
|
||||
XIDeviceEvent.detail 36
|
||||
XIDeviceEvent.deviceid 28
|
||||
XIDeviceEvent.display 12
|
||||
XIDeviceEvent.event 44
|
||||
XIDeviceEvent.event_x 68
|
||||
XIDeviceEvent.event_y 76
|
||||
XIDeviceEvent.evtype 20
|
||||
XIDeviceEvent.extension 16
|
||||
XIDeviceEvent.flags 84
|
||||
XIDeviceEvent.group 124
|
||||
XIDeviceEvent.mods 108
|
||||
XIDeviceEvent.root 40
|
||||
XIDeviceEvent.root_x 52
|
||||
XIDeviceEvent.root_y 60
|
||||
XIDeviceEvent.send_event 8
|
||||
XIDeviceEvent.serial 4
|
||||
XIDeviceEvent.sourceid 32
|
||||
XIDeviceEvent.time 24
|
||||
XIDeviceEvent.type 0
|
||||
XIDeviceEvent.valuators 96
|
||||
XImage 88
|
||||
XImage.bitmap_bit_order 28
|
||||
XImage.bitmap_pad 32
|
||||
@@ -436,6 +480,11 @@ XIMHotKeyTrigger.modifier_mask 8
|
||||
XIMHotKeyTriggers 8
|
||||
XIMHotKeyTriggers.key 4
|
||||
XIMHotKeyTriggers.num_hot_key 0
|
||||
XIModifierState 16
|
||||
XIModifierState.base 0
|
||||
XIModifierState.effective 12
|
||||
XIModifierState.latched 4
|
||||
XIModifierState.locked 8
|
||||
XIMPreeditCaretCallbackStruct 12
|
||||
XIMPreeditCaretCallbackStruct.direction 4
|
||||
XIMPreeditCaretCallbackStruct.position 0
|
||||
@@ -472,6 +521,10 @@ XIMText.string 12
|
||||
XIMValuesList 8
|
||||
XIMValuesList.count_values 0
|
||||
XIMValuesList.supported_values 4
|
||||
XIValuatorState 12
|
||||
XIValuatorState.mask 4
|
||||
XIValuatorState.mask_len 0
|
||||
XIValuatorState.values 8
|
||||
XkbAccessXNotifyEvent 44
|
||||
XkbAccessXNotifyEvent.debounce_delay 40
|
||||
XkbAccessXNotifyEvent.detail 28
|
||||
|
||||
@@ -272,12 +272,14 @@ XEvent.xclient 0
|
||||
XEvent.xcolormap 0
|
||||
XEvent.xconfigure 0
|
||||
XEvent.xconfigurerequest 0
|
||||
XEvent.xcookie 0
|
||||
XEvent.xcreatewindow 0
|
||||
XEvent.xcrossing 0
|
||||
XEvent.xdestroywindow 0
|
||||
XEvent.xerror 0
|
||||
XEvent.xexpose 0
|
||||
XEvent.xfocus 0
|
||||
XEvent.xgeneric 0
|
||||
XEvent.xgraphicsexpose 0
|
||||
XEvent.xgravity 0
|
||||
XEvent.xkey 0
|
||||
@@ -370,6 +372,22 @@ XGCValues.subwindow_mode 96
|
||||
XGCValues.tile 64
|
||||
XGCValues.ts_x_origin 80
|
||||
XGCValues.ts_y_origin 84
|
||||
XGenericEvent 40
|
||||
XGenericEventCookie 56
|
||||
XGenericEventCookie.cookie 40
|
||||
XGenericEventCookie.data 48
|
||||
XGenericEventCookie.display 24
|
||||
XGenericEventCookie.evtype 36
|
||||
XGenericEventCookie.extension 32
|
||||
XGenericEventCookie.send_event 16
|
||||
XGenericEventCookie.serial 8
|
||||
XGenericEventCookie.type 0
|
||||
XGenericEvent.display 24
|
||||
XGenericEvent.evtype 36
|
||||
XGenericEvent.extension 32
|
||||
XGenericEvent.send_event 16
|
||||
XGenericEvent.serial 8
|
||||
XGenericEvent.type 0
|
||||
XGraphicsExposeEvent 72
|
||||
XGraphicsExposeEvent.count 56
|
||||
XGraphicsExposeEvent.display 24
|
||||
@@ -396,6 +414,9 @@ XHostAddress 16
|
||||
XHostAddress.address 8
|
||||
XHostAddress.family 0
|
||||
XHostAddress.length 4
|
||||
XIButtonState 16
|
||||
XIButtonState.mask 8
|
||||
XIButtonState.mask_len 0
|
||||
XIconSize 24
|
||||
XIconSize.height_inc 20
|
||||
XIconSize.max_height 12
|
||||
@@ -403,6 +424,29 @@ XIconSize.max_width 8
|
||||
XIconSize.min_height 4
|
||||
XIconSize.min_width 0
|
||||
XIconSize.width_inc 16
|
||||
XIDeviceEvent 200
|
||||
XIDeviceEvent.buttons 128
|
||||
XIDeviceEvent.child 80
|
||||
XIDeviceEvent.detail 56
|
||||
XIDeviceEvent.deviceid 48
|
||||
XIDeviceEvent.display 24
|
||||
XIDeviceEvent.event 72
|
||||
XIDeviceEvent.event_x 104
|
||||
XIDeviceEvent.event_y 112
|
||||
XIDeviceEvent.evtype 36
|
||||
XIDeviceEvent.extension 32
|
||||
XIDeviceEvent.flags 120
|
||||
XIDeviceEvent.group 184
|
||||
XIDeviceEvent.mods 168
|
||||
XIDeviceEvent.root 64
|
||||
XIDeviceEvent.root_x 88
|
||||
XIDeviceEvent.root_y 96
|
||||
XIDeviceEvent.send_event 16
|
||||
XIDeviceEvent.serial 8
|
||||
XIDeviceEvent.sourceid 52
|
||||
XIDeviceEvent.time 40
|
||||
XIDeviceEvent.type 0
|
||||
XIDeviceEvent.valuators 144
|
||||
XImage 136
|
||||
XImage.bitmap_bit_order 32
|
||||
XImage.bitmap_pad 36
|
||||
@@ -436,6 +480,11 @@ XIMHotKeyTrigger.modifier_mask 12
|
||||
XIMHotKeyTriggers 16
|
||||
XIMHotKeyTriggers.key 8
|
||||
XIMHotKeyTriggers.num_hot_key 0
|
||||
XIModifierState 16
|
||||
XIModifierState.base 0
|
||||
XIModifierState.effective 12
|
||||
XIModifierState.latched 4
|
||||
XIModifierState.locked 8
|
||||
XIMPreeditCaretCallbackStruct 12
|
||||
XIMPreeditCaretCallbackStruct.direction 4
|
||||
XIMPreeditCaretCallbackStruct.position 0
|
||||
@@ -472,6 +521,10 @@ XIMText.string 24
|
||||
XIMValuesList 16
|
||||
XIMValuesList.count_values 0
|
||||
XIMValuesList.supported_values 8
|
||||
XIValuatorState 24
|
||||
XIValuatorState.mask 8
|
||||
XIValuatorState.mask_len 0
|
||||
XIValuatorState.values 16
|
||||
XkbAccessXNotifyEvent 64
|
||||
XkbAccessXNotifyEvent.debounce_delay 60
|
||||
XkbAccessXNotifyEvent.detail 48
|
||||
|
||||
@@ -127,6 +127,22 @@ XKeymapEvent
|
||||
display long
|
||||
window long
|
||||
key_vector array byte 32
|
||||
XGenericEvent
|
||||
type int
|
||||
serial long
|
||||
send_event Bool
|
||||
display long
|
||||
extension int
|
||||
evtype int
|
||||
XGenericEventCookie
|
||||
type int
|
||||
serial long
|
||||
send_event Bool
|
||||
display long
|
||||
extension int
|
||||
evtype int
|
||||
cookie int
|
||||
data pointer
|
||||
XDestroyWindowEvent
|
||||
type int
|
||||
serial long
|
||||
@@ -814,6 +830,8 @@ XEvent
|
||||
xmapping struct XMappingEvent
|
||||
xerror struct XErrorEvent
|
||||
xkeymap struct XKeymapEvent
|
||||
xgeneric struct XGenericEvent
|
||||
xcookie struct XGenericEventCookie
|
||||
pad array long 24
|
||||
|
||||
XkbAnyEvent
|
||||
@@ -1039,3 +1057,42 @@ XkbEvent
|
||||
accessx struct XkbAccessXNotifyEvent
|
||||
device struct XkbExtensionDeviceNotifyEvent
|
||||
core struct XEvent
|
||||
|
||||
XIButtonState
|
||||
mask_len int
|
||||
mask pointer byte
|
||||
|
||||
XIValuatorState
|
||||
mask_len int
|
||||
mask pointer byte
|
||||
values pointer double
|
||||
|
||||
XIModifierState
|
||||
base int
|
||||
latched int
|
||||
locked int
|
||||
effective int
|
||||
|
||||
XIDeviceEvent
|
||||
type int
|
||||
serial long
|
||||
send_event Bool
|
||||
display long
|
||||
extension int
|
||||
evtype int
|
||||
time ulong
|
||||
deviceid int
|
||||
sourceid int
|
||||
detail int
|
||||
root long
|
||||
event long
|
||||
child long
|
||||
root_x double
|
||||
root_y double
|
||||
event_x double
|
||||
event_y double
|
||||
flags int
|
||||
buttons struct XIButtonState
|
||||
valuators struct XIValuatorState
|
||||
mods struct XIModifierState
|
||||
group struct XIModifierState
|
||||
|
||||
@@ -1142,6 +1142,8 @@ public class WrapperGenerator {
|
||||
pw.println("/* This file is an automatically generated file, please do not edit this file, modify the XlibParser.java file instead !*/\n" );
|
||||
pw.println("#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xos.h>\n#include <X11/Xatom.h>\n#include <stdio.h>\n");
|
||||
pw.println("#include <X11/extensions/Xdbe.h>");
|
||||
pw.println("#include <X11/extensions/XI2.h>");
|
||||
pw.println("#include <X11/extensions/XInput2.h>");
|
||||
pw.println("#include <X11/XKBlib.h>");
|
||||
pw.println("#include \"awt_p.h\"");
|
||||
pw.println("#include \"color.h\"");
|
||||
|
||||
@@ -78,3 +78,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_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)
|
||||
|
||||
@@ -483,10 +483,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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,4 +308,9 @@ public final class CFontManager extends SunFontManager {
|
||||
@Override
|
||||
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
|
||||
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
|
||||
|
||||
@Override
|
||||
public boolean areColorGlyphsSupported() {
|
||||
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
|
||||
@@ -1516,4 +1517,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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#import "CDataTransferer.h"
|
||||
#include "sun_lwawt_macosx_CDataTransferer.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import "jni_util.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@@ -259,13 +260,22 @@ JNF_COCOA_ENTER(env);
|
||||
}
|
||||
|
||||
NSUInteger dataSize = [clipData length];
|
||||
const void *dataBuffer = [clipData bytes];
|
||||
if (format == sun_lwawt_macosx_CDataTransferer_CF_STRING && dataSize >= 3) {
|
||||
const unsigned char *bytesPtr = (const unsigned char *)dataBuffer;
|
||||
if (bytesPtr[0] == 0xEF && bytesPtr[1] == 0xBB && bytesPtr[2] == 0xBF) {
|
||||
// strip BOM from string content, like native applications do
|
||||
dataSize -= 3;
|
||||
dataBuffer = (const void *)(bytesPtr + 3);
|
||||
}
|
||||
}
|
||||
|
||||
returnValue = (*env)->NewByteArray(env, dataSize);
|
||||
if (returnValue == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dataSize != 0) {
|
||||
const void *dataBuffer = [clipData bytes];
|
||||
(*env)->SetByteArrayRegion(env, returnValue, 0, dataSize, (jbyte *)dataBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -601,42 +601,3 @@ Java_sun_awt_FontDescriptor_initIDs
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Class: sun_awt_FontDescriptor
|
||||
* Method: initIDs
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_font_CFont_getCascadeList
|
||||
(JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)
|
||||
{
|
||||
jclass alc = (*env)->FindClass(env, "java/util/ArrayList");
|
||||
if (alc == NULL) return;
|
||||
jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");
|
||||
if (addMID == NULL) return;
|
||||
|
||||
CFIndex i;
|
||||
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||
NSFont* nsFont = awtFont->fFont;
|
||||
CTFontRef font = (CTFontRef)nsFont;
|
||||
CFStringRef base = CTFontCopyFullName(font);
|
||||
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"BaseFont is : %@", (NSString*)base);
|
||||
#endif
|
||||
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
|
||||
CFIndex cnt = CFArrayGetCount(fds);
|
||||
for (i=0; i<cnt; i++) {
|
||||
CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
|
||||
CFStringRef fontname =
|
||||
CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);
|
||||
#ifdef DEBUG
|
||||
NSLog(@"Font is : %@", (NSString*)fontname);
|
||||
#endif
|
||||
jstring jFontName = (jstring)JNFNSToJavaString(env, fontname);
|
||||
(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
|
||||
(*env)->DeleteLocalRef(env, jFontName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
CGFloat fSize;
|
||||
JRSFontRenderingStyle fStyle;
|
||||
jint fAAStyle;
|
||||
jint fFmHint;
|
||||
|
||||
CGAffineTransform fTx;
|
||||
CGAffineTransform fDevTx;
|
||||
@@ -41,6 +42,6 @@
|
||||
CGAffineTransform fFontTx;
|
||||
}
|
||||
|
||||
+ (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont tx:(CGAffineTransform)tx invDevTx:(CGAffineTransform)invDevTx style:(JRSFontRenderingStyle)style aaStyle:(jint)aaStyle;
|
||||
+ (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont tx:(CGAffineTransform)tx invDevTx:(CGAffineTransform)invDevTx style:(JRSFontRenderingStyle)style aaStyle:(jint)aaStyle fmHint:(jint)fmHint;
|
||||
|
||||
@end
|
||||
|
||||
@@ -40,13 +40,15 @@ static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
|
||||
tx:(CGAffineTransform)tx
|
||||
invDevTx:(CGAffineTransform)invDevTx
|
||||
style:(JRSFontRenderingStyle)style
|
||||
aaStyle:(jint)aaStyle {
|
||||
aaStyle:(jint)aaStyle
|
||||
fmHint:(jint)fmHint {
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
fAWTFont = [awtFont retain];
|
||||
fStyle = style;
|
||||
fAAStyle = aaStyle;
|
||||
fFmHint = fmHint;
|
||||
|
||||
fTx = tx; // composited glyph and device transform
|
||||
|
||||
@@ -76,12 +78,14 @@ static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
|
||||
tx:(CGAffineTransform)tx
|
||||
invDevTx:(CGAffineTransform)invDevTx
|
||||
style:(JRSFontRenderingStyle)style
|
||||
aaStyle:(jint)aaStyle {
|
||||
aaStyle:(jint)aaStyle
|
||||
fmHint:(jint)fmHint {
|
||||
|
||||
return [[[AWTStrike alloc] initWithFont:awtFont
|
||||
tx:tx invDevTx:invDevTx
|
||||
style:style
|
||||
aaStyle:aaStyle] autorelease];
|
||||
aaStyle:aaStyle
|
||||
fmHint:fmHint] autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -151,7 +155,19 @@ JNF_COCOA_ENTER(env);
|
||||
// to indicate we should use CoreText to substitute the character
|
||||
CGGlyph glyph;
|
||||
const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
|
||||
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
|
||||
if (CGGI_IsColorFont(cgFallback)) {
|
||||
CGAffineTransform matrix = awtStrike->fAltTx;
|
||||
CGFloat fontSize = sqrt(fabs(matrix.a * matrix.d - matrix.b * matrix.c));
|
||||
CTFontRef font = CTFontCreateWithGraphicsFont(cgFallback, fontSize, NULL, NULL);
|
||||
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
CFRelease(font);
|
||||
advance.width /= fontSize;
|
||||
advance.height /= fontSize;
|
||||
} else {
|
||||
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
}
|
||||
CFRelease(cgFallback);
|
||||
CFRelease(fallback);
|
||||
advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
|
||||
if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
|
||||
@@ -348,7 +364,7 @@ JNF_COCOA_ENTER(env);
|
||||
CGAffineTransform glyphTx = GetTxFromDoubles(env, glyphTxArray);
|
||||
CGAffineTransform invDevTx = GetTxFromDoubles(env, invDevTxArray);
|
||||
|
||||
awtStrike = [AWTStrike awtStrikeForFont:awtFont tx:glyphTx invDevTx:invDevTx style:style aaStyle:aaStyle]; // autoreleased
|
||||
awtStrike = [AWTStrike awtStrikeForFont:awtFont tx:glyphTx invDevTx:invDevTx style:style aaStyle:aaStyle fmHint:fmHint]; // autoreleased
|
||||
|
||||
if (awtStrike)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#import "CoreTextSupport.h"
|
||||
|
||||
#import "sun_font_CCharToGlyphMapper.h"
|
||||
#import "sun_font_CCompositeGlyphMapper.h"
|
||||
|
||||
/*
|
||||
* Class: sun_font_CCharToGlyphMapper
|
||||
@@ -113,3 +114,28 @@ JNF_COCOA_ENTER(env);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_font_CCompositeGlyphMapper
|
||||
* Method: nativeCodePointToGlyph
|
||||
* Signature: (JI[Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_font_CCompositeGlyphMapper_nativeCodePointToGlyph
|
||||
(JNIEnv *env, jclass clazz, jlong awtFontPtr, jint codePoint, jobjectArray resultArray)
|
||||
{
|
||||
JNF_COCOA_ENTER(env);
|
||||
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||
CFStringRef fontNames[] = {NULL, NULL};
|
||||
CGGlyph glyph = CTS_CopyGlyphAndFontNamesForCodePoint(awtFont, (UnicodeScalarValue)codePoint, fontNames);
|
||||
if (glyph > 0) {
|
||||
jstring fontName = (jstring)JNFNSToJavaString(env, (NSString *)fontNames[0]);
|
||||
(*env)->SetObjectArrayElement(env, resultArray, 0, fontName);
|
||||
jstring fontFamilyName = (jstring)JNFNSToJavaString(env, (NSString *)fontNames[1]);
|
||||
(*env)->SetObjectArrayElement(env, resultArray, 1, fontFamilyName);
|
||||
}
|
||||
if (fontNames[0]) CFRelease(fontNames[0]);
|
||||
if (fontNames[1]) CFRelease(fontNames[1]);
|
||||
return glyph;
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
@@ -34,4 +34,6 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
|
||||
const AWTStrike *strike,
|
||||
jint rawGlyphCodes[], const CFIndex len);
|
||||
|
||||
bool CGGI_IsColorFont(CGFontRef font);
|
||||
|
||||
#endif /* __CGGLYPHIMAGES_H */
|
||||
|
||||
@@ -309,6 +309,40 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CGGI_CopyImageFromCanvasToARGBInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info)
|
||||
{
|
||||
CGBitmapInfo bitmapInfo = CGBitmapContextGetBitmapInfo(canvas->context);
|
||||
bool littleEndian = (bitmapInfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little;
|
||||
|
||||
UInt32 *src = (UInt32 *)canvas->image->data;
|
||||
size_t srcRowWidth = canvas->image->width;
|
||||
|
||||
UInt8 *dest = (UInt8 *)info->image;
|
||||
size_t destRowWidth = info->width;
|
||||
|
||||
size_t height = info->height;
|
||||
|
||||
size_t y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
size_t srcRow = y * srcRowWidth;
|
||||
if (littleEndian) {
|
||||
UInt16 destRowBytes = info->rowBytes;
|
||||
memcpy(dest, src + srcRow, destRowBytes);
|
||||
dest += destRowBytes;
|
||||
} else {
|
||||
size_t x;
|
||||
for (x = 0; x < destRowWidth; x++) {
|
||||
UInt32 p = src[srcRow + x];
|
||||
*dest++ = (p >> 24 & 0xFF); // blue (alpha-premultiplied)
|
||||
*dest++ = (p >> 16 & 0xFF); // green (alpha-premultiplied)
|
||||
*dest++ = (p >> 8 & 0xFF); // red (alpha-premultiplied)
|
||||
*dest++ = (p & 0xFF); // alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark --- Pixel Size, Modes, and Canvas Shaping Helper Functions ---
|
||||
|
||||
@@ -326,6 +360,26 @@ static CGGI_GlyphInfoDescriptor grey =
|
||||
{ 1, &CGGI_CopyImageFromCanvasToAlphaInfo };
|
||||
static CGGI_GlyphInfoDescriptor rgb =
|
||||
{ 3, &CGGI_CopyImageFromCanvasToRGBInfo };
|
||||
static CGGI_GlyphInfoDescriptor argb =
|
||||
{ 4, &CGGI_CopyImageFromCanvasToARGBInfo };
|
||||
|
||||
static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");
|
||||
|
||||
bool CGGI_IsColorFont(CGFontRef font)
|
||||
{
|
||||
CFStringRef name = CGFontCopyFullName(font);
|
||||
if (name == NULL) return false;
|
||||
bool isFixedColor = CFStringCompare(name, EMOJI_FONT_NAME, 0) == kCFCompareEqualTo;
|
||||
CFRelease(name);
|
||||
return isFixedColor;
|
||||
}
|
||||
|
||||
static inline CGGI_GlyphInfoDescriptor*
|
||||
CGGI_GetGlyphInfoDescriptor(const CGGI_RenderingMode *mode, CGFontRef font)
|
||||
{
|
||||
bool isFixedColor = CGGI_IsColorFont(font);
|
||||
return isFixedColor ? &argb : mode->glyphDescriptor;
|
||||
}
|
||||
|
||||
static inline CGGI_RenderingMode
|
||||
CGGI_GetRenderingMode(const AWTStrike *strike)
|
||||
@@ -459,11 +513,11 @@ CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width,
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the canvas by blitting white only into the region of interest
|
||||
* Clear the canvas by blitting white (or transparent background for color glyphs) only into the region of interest
|
||||
* (the rect which we will copy out of once the glyph is struck).
|
||||
*/
|
||||
static inline void
|
||||
CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info)
|
||||
CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info, bool transparent)
|
||||
{
|
||||
vImage_Buffer canvasRectToClear;
|
||||
canvasRectToClear.data = canvas->image->data;
|
||||
@@ -474,18 +528,31 @@ CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info)
|
||||
|
||||
// clean the canvas
|
||||
#ifdef CGGI_DEBUG
|
||||
Pixel_8888 opaqueWhite = { 0xE0, 0xE0, 0xE0, 0xE0 };
|
||||
Pixel_8888 background = { 0xE0, 0xE0, 0xE0, 0xE0 };
|
||||
#else
|
||||
Pixel_8888 opaqueWhite = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
Pixel_8888 background = { transparent ? 0 : 0xFF,
|
||||
transparent ? 0 : 0xFF,
|
||||
transparent ? 0 : 0xFF,
|
||||
transparent ? 0 : 0xFF };
|
||||
#endif
|
||||
|
||||
// clear canvas background and set foreground color
|
||||
vImageBufferFill_ARGB8888(&canvasRectToClear, opaqueWhite, kvImageNoFlags);
|
||||
// clear canvas background
|
||||
vImageBufferFill_ARGB8888(&canvasRectToClear, background, kvImageNoFlags);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark --- GlyphInfo Creation & Copy Functions ---
|
||||
|
||||
static inline CGSize CGGI_ScaleAdvance(CGSize advance, const AWTStrike *strike) {
|
||||
advance = CGSizeApplyAffineTransform(advance, strike->fFontTx);
|
||||
if (!JRSFontStyleUsesFractionalMetrics(strike->fStyle)) {
|
||||
advance.width = round(advance.width);
|
||||
advance.height = round(advance.height);
|
||||
}
|
||||
advance = CGSizeApplyAffineTransform(advance, strike->fDevTx);
|
||||
return advance;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a GlyphInfo with exactly the correct size image and measurements.
|
||||
*/
|
||||
@@ -493,9 +560,9 @@ CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info)
|
||||
static inline GlyphInfo *
|
||||
CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode)
|
||||
const CGGI_GlyphInfoDescriptor *glyphDescriptor)
|
||||
{
|
||||
size_t pixelSize = mode->glyphDescriptor->pixelSize;
|
||||
size_t pixelSize = glyphDescriptor->pixelSize;
|
||||
|
||||
// adjust the bounding box to be 1px bigger on each side than what
|
||||
// CGFont-whatever suggests - because it gives a bounding box that
|
||||
@@ -515,21 +582,19 @@ CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
|
||||
width = 1;
|
||||
height = 1;
|
||||
}
|
||||
advance = CGSizeApplyAffineTransform(advance, strike->fFontTx);
|
||||
if (!JRSFontStyleUsesFractionalMetrics(strike->fStyle)) {
|
||||
advance.width = round(advance.width);
|
||||
advance.height = round(advance.height);
|
||||
}
|
||||
advance = CGSizeApplyAffineTransform(advance, strike->fDevTx);
|
||||
advance = CGGI_ScaleAdvance(advance, strike);
|
||||
|
||||
int imageBytes = height * width * pixelSize;
|
||||
int extraPixelStorage = (strike->fAAStyle == sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_LCD_HRGB &&
|
||||
strike->fFmHint == sun_awt_SunHints_INTVAL_FRACTIONALMETRICS_ON) ? 3 : 0;
|
||||
|
||||
#ifdef USE_IMAGE_ALIGNED_MEMORY
|
||||
// create separate memory
|
||||
GlyphInfo *glyphInfo = (GlyphInfo *)malloc(sizeof(GlyphInfo));
|
||||
void *image = (void *)malloc(height * width * pixelSize);
|
||||
void *image = (void *)malloc(imageBytes + extraPixelStorage);
|
||||
#else
|
||||
// create a GlyphInfo struct fused to the image it points to
|
||||
GlyphInfo *glyphInfo = (GlyphInfo *)malloc(sizeof(GlyphInfo) +
|
||||
height * width * pixelSize);
|
||||
GlyphInfo *glyphInfo = (GlyphInfo *)malloc(sizeof(GlyphInfo) + imageBytes + extraPixelStorage);
|
||||
#endif
|
||||
|
||||
glyphInfo->advanceX = advance.width;
|
||||
@@ -547,6 +612,9 @@ CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
|
||||
glyphInfo->image = ((void *)glyphInfo) + sizeof(GlyphInfo);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for (i = 0; i < extraPixelStorage; i++) (glyphInfo->image)[imageBytes + i] = 0;
|
||||
|
||||
return glyphInfo;
|
||||
}
|
||||
|
||||
@@ -559,8 +627,8 @@ CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
|
||||
*/
|
||||
static inline void
|
||||
CGGI_CreateImageForGlyph
|
||||
(CGGI_GlyphCanvas *canvas, const CGGlyph glyph,
|
||||
GlyphInfo *info, const CGGI_RenderingMode *mode)
|
||||
(CGFontRef cgFont, CGGI_GlyphCanvas *canvas, const CGGlyph glyph,
|
||||
GlyphInfo *info, const CGGI_GlyphInfoDescriptor *glyphDescriptor, const AWTStrike *strike)
|
||||
{
|
||||
if (isnan(info->topLeftX) || isnan(info->topLeftY)) {
|
||||
// Explicitly set glyphInfo width/height to be 0 to ensure
|
||||
@@ -569,20 +637,53 @@ CGGI_CreateImageForGlyph
|
||||
info->height = 0;
|
||||
|
||||
// copy the "empty" glyph from the canvas into the info
|
||||
(*mode->glyphDescriptor->copyFxnPtr)(canvas, info);
|
||||
(*glyphDescriptor->copyFxnPtr)(canvas, info);
|
||||
return;
|
||||
}
|
||||
|
||||
// clean the canvas
|
||||
CGGI_ClearCanvas(canvas, info);
|
||||
CGGI_ClearCanvas(canvas, info, glyphDescriptor == &argb);
|
||||
|
||||
// strike the glyph in the upper right corner
|
||||
CGContextShowGlyphsAtPoint(canvas->context,
|
||||
-info->topLeftX,
|
||||
canvas->image->height + info->topLeftY,
|
||||
&glyph, 1);
|
||||
CGFloat x = -info->topLeftX;
|
||||
CGFloat y = canvas->image->height + info->topLeftY;
|
||||
|
||||
if (glyphDescriptor == &argb) {
|
||||
CGAffineTransform matrix = CGContextGetTextMatrix(canvas->context);
|
||||
CGFloat fontSize = sqrt(fabs(matrix.a * matrix.d - matrix.b * matrix.c));
|
||||
CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, fontSize, NULL, NULL);
|
||||
|
||||
CGFloat normFactor = 1.0 / fontSize;
|
||||
CGAffineTransform normMatrix = CGAffineTransformScale(matrix, normFactor, normFactor);
|
||||
CGContextSetTextMatrix(canvas->context, normMatrix);
|
||||
|
||||
CGPoint userPoint = CGPointMake(x, y);
|
||||
CGAffineTransform invNormMatrix = CGAffineTransformInvert(normMatrix);
|
||||
CGPoint textPoint = CGPointApplyAffineTransform(userPoint, invNormMatrix);
|
||||
|
||||
CTFontDrawGlyphs(font, &glyph, &textPoint, 1, canvas->context);
|
||||
|
||||
// CTFontGetAdvancesForGlyphs returns rounded advance for emoji font, so it can be calculated only here
|
||||
// where CTFont instance with actual size is available
|
||||
CGSize advance;
|
||||
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
advance.width /= fontSize;
|
||||
advance.height /= fontSize;
|
||||
advance = CGGI_ScaleAdvance(advance, strike);
|
||||
info->advanceX = advance.width;
|
||||
info->advanceY = advance.height;
|
||||
|
||||
CFRelease(font);
|
||||
// restore context's original state
|
||||
CGContextSetTextMatrix(canvas->context, matrix);
|
||||
CGContextSetFontSize(canvas->context, 1);
|
||||
} else {
|
||||
// old procedure is faster, so we use it by default
|
||||
CGContextShowGlyphsAtPoint(canvas->context, x, y, &glyph, 1);
|
||||
}
|
||||
|
||||
// copy the glyph from the canvas into the info
|
||||
(*mode->glyphDescriptor->copyFxnPtr)(canvas, info);
|
||||
(*glyphDescriptor->copyFxnPtr)(canvas, info);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -620,8 +721,11 @@ CGGI_CreateImageForUnicode
|
||||
CGSize advance;
|
||||
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
|
||||
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
|
||||
CGGI_GlyphInfoDescriptor *glyphDescriptor = CGGI_GetGlyphInfoDescriptor(mode, cgFallback);
|
||||
|
||||
// create the Sun2D GlyphInfo we are going to strike into
|
||||
GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode);
|
||||
GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, glyphDescriptor);
|
||||
|
||||
// fix the context size, just in case the substituted character is unexpectedly large
|
||||
CGGI_SizeCanvas(canvas, info->width, info->height, mode);
|
||||
@@ -629,12 +733,11 @@ CGGI_CreateImageForUnicode
|
||||
// align the transform for the real CoreText strike
|
||||
CGContextSetTextMatrix(canvas->context, strike->fAltTx);
|
||||
|
||||
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
|
||||
CGContextSetFont(canvas->context, cgFallback);
|
||||
CFRelease(cgFallback);
|
||||
|
||||
// clean the canvas - align, strike, and copy the glyph from the canvas into the info
|
||||
CGGI_CreateImageForGlyph(canvas, glyph, info, mode);
|
||||
CGGI_CreateImageForGlyph(cgFallback, canvas, glyph, info, glyphDescriptor, strike);
|
||||
|
||||
// restore the state of the world
|
||||
CGContextRestoreGState(canvas->context);
|
||||
@@ -677,11 +780,14 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
|
||||
CGContextSetFont(canvas->context, strike->fAWTFont->fNativeCGFont);
|
||||
JRSFontSetRenderingStyleOnContext(canvas->context, strike->fStyle);
|
||||
|
||||
CGGI_GlyphInfoDescriptor* mainFontDescriptor = CGGI_GetGlyphInfoDescriptor(mode, strike->fAWTFont->fNativeCGFont);
|
||||
|
||||
CFIndex i;
|
||||
for (i = 0; i < len; i++) {
|
||||
GlyphInfo *info = (GlyphInfo *)jlong_to_ptr(glyphInfos[i]);
|
||||
if (info != NULL) {
|
||||
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode);
|
||||
CGGI_CreateImageForGlyph(strike->fAWTFont->fNativeCGFont,
|
||||
canvas, glyphs[i], info, mainFontDescriptor, strike);
|
||||
} else {
|
||||
info = CGGI_CreateImageForUnicode(canvas, strike, mode, uniChars[i]);
|
||||
glyphInfos[i] = ptr_to_jlong(info);
|
||||
@@ -742,7 +848,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
|
||||
NSString* theKey = (mode->glyphDescriptor == &rgb) ?
|
||||
threadLocalLCDCanvasKey : threadLocalAACanvasKey;
|
||||
|
||||
|
||||
CGGI_GlyphCanvas *canvas = [threadDict objectForKey:theKey];
|
||||
if (canvas == nil) {
|
||||
canvas = [[CGGI_GlyphCanvas alloc] init];
|
||||
@@ -780,6 +886,8 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
|
||||
size_t maxWidth = 1;
|
||||
size_t maxHeight = 1;
|
||||
|
||||
CGGI_GlyphInfoDescriptor* mainFontDescriptor = CGGI_GetGlyphInfoDescriptor(mode, strike->fAWTFont->fNativeCGFont);
|
||||
|
||||
CFIndex i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@@ -792,7 +900,7 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
|
||||
CGSize advance = advances[i];
|
||||
CGRect bbox = bboxes[i];
|
||||
|
||||
GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode);
|
||||
GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mainFontDescriptor);
|
||||
|
||||
if (maxWidth < glyphInfo->width) maxWidth = glyphInfo->width;
|
||||
if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height;
|
||||
|
||||
@@ -54,6 +54,11 @@ CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(const AWTFont *font, co
|
||||
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
|
||||
CTFontRef CTS_CopyCTFallbackFontAndGlyphForUnicode(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count);
|
||||
|
||||
// Transform a single Unicode character code into glyph code.
|
||||
// Names of the relevant font are also returned, if the substitution is used.
|
||||
// Non-null components of fontNames array should always be released by the calling code, regardless of the returned value.
|
||||
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[]);
|
||||
|
||||
// Breakup a 32 bit unicode value into the component surrogate pairs
|
||||
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]);
|
||||
|
||||
|
||||
@@ -88,18 +88,10 @@ ReleaseCTStateDictionary(CFDictionaryRef ctStateDict)
|
||||
CFRelease(ctStateDict); // GC
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform Unicode characters into glyphs.
|
||||
*
|
||||
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
|
||||
* or the negative unicode value if we know the character can be hot-substituted.
|
||||
*
|
||||
* This is the heart of "Universal Font Substitution" in Java.
|
||||
*/
|
||||
void CTS_GetGlyphsAsIntsForCharacters
|
||||
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
|
||||
void GetFontsAndGlyphsForCharacters(CTFontRef font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[],
|
||||
CTFontRef actualFonts[], const size_t count)
|
||||
{
|
||||
CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count);
|
||||
CTFontGetGlyphsForCharacters(font, unicodes, glyphs, count);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
@@ -115,12 +107,15 @@ void CTS_GetGlyphsAsIntsForCharacters
|
||||
continue;
|
||||
}
|
||||
|
||||
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicodes[i],
|
||||
surrogatePair ? 2 : 1);
|
||||
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(font, &unicodes[i], surrogatePair ? 2 : 1);
|
||||
if (fallback) {
|
||||
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
|
||||
glyph = glyphs[i];
|
||||
CFRelease(fallback);
|
||||
if (actualFonts && glyph > 0) {
|
||||
actualFonts[i] = fallback;
|
||||
} else {
|
||||
CFRelease(fallback);
|
||||
}
|
||||
}
|
||||
|
||||
if (glyph > 0) {
|
||||
@@ -134,6 +129,53 @@ void CTS_GetGlyphsAsIntsForCharacters
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform Unicode characters into glyphs.
|
||||
*
|
||||
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
|
||||
* or the negative unicode value if we know the character can be hot-substituted.
|
||||
*
|
||||
* This is the heart of "Universal Font Substitution" in Java.
|
||||
*/
|
||||
void CTS_GetGlyphsAsIntsForCharacters
|
||||
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
|
||||
{
|
||||
GetFontsAndGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, glyphsAsInts, NULL, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns glyph code for a given Unicode character.
|
||||
* Names of the corresponding substituted font are also returned if substitution is performed.
|
||||
*/
|
||||
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint
|
||||
(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[])
|
||||
{
|
||||
CTFontRef fontRef = (CTFontRef)font->fFont;
|
||||
int count = codePoint >= 0x10000 ? 2 : 1;
|
||||
UTF16Char unicodes[count];
|
||||
if (count == 1) {
|
||||
unicodes[0] = (UTF16Char)codePoint;
|
||||
} else {
|
||||
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, unicodes);
|
||||
}
|
||||
CGGlyph glyphs[count];
|
||||
jint glyphsAsInts[count];
|
||||
CTFontRef actualFonts[count];
|
||||
GetFontsAndGlyphsForCharacters(fontRef, unicodes, glyphs, glyphsAsInts, actualFonts, count);
|
||||
CGGlyph glyph = glyphs[0];
|
||||
bool substitutionHappened = glyphsAsInts[0] < 0;
|
||||
if (glyph > 0 && substitutionHappened) {
|
||||
CTFontRef actualFont = actualFonts[0];
|
||||
CFStringRef fontName = CTFontCopyPostScriptName(actualFont);
|
||||
CFStringRef familyName = CTFontCopyFamilyName(actualFont);
|
||||
CFRelease(actualFont);
|
||||
fontNames[0] = fontName;
|
||||
fontNames[1] = familyName;
|
||||
if (!fontName || !familyName) glyph = 0;
|
||||
}
|
||||
return glyph;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translates a Unicode into a CGGlyph/CTFontRef pair
|
||||
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
|
||||
|
||||
import sun.awt.image.SunWritableRaster;
|
||||
import sun.swing.ImageCache;
|
||||
import sun.awt.X11GraphicsDevice;
|
||||
|
||||
/**
|
||||
* GTKEngine delegates all painting job to native GTK libraries.
|
||||
@@ -94,6 +95,7 @@ class GTKEngine {
|
||||
static enum Settings {
|
||||
GTK_FONT_NAME,
|
||||
GTK_ICON_SIZES,
|
||||
GTK_XFT_DPI,
|
||||
GTK_CURSOR_BLINK,
|
||||
GTK_CURSOR_BLINK_TIME
|
||||
}
|
||||
@@ -270,6 +272,18 @@ class GTKEngine {
|
||||
regionToWidgetTypeMap.put(Region.TREE, WidgetType.TREE);
|
||||
regionToWidgetTypeMap.put(Region.TREE_CELL, WidgetType.TREE_CELL);
|
||||
regionToWidgetTypeMap.put(Region.VIEWPORT, WidgetType.VIEWPORT);
|
||||
|
||||
Object value = INSTANCE.getSetting(Settings.GTK_XFT_DPI);
|
||||
if (value instanceof Integer) {
|
||||
int dpi = ((Integer)value).intValue() / 1024;
|
||||
if (dpi == -1) {
|
||||
dpi = 96;
|
||||
}
|
||||
if (dpi < 50) {
|
||||
dpi = 50;
|
||||
}
|
||||
X11GraphicsDevice.setGlobalScale(Math.round(dpi / 96f));
|
||||
}
|
||||
}
|
||||
|
||||
/** Translate Region and JComponent into WidgetType ordinals */
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.Map;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.UNIXToolkit;
|
||||
import sun.awt.OSInfo;
|
||||
import sun.awt.X11GraphicsDevice;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.swing.DefaultLayoutStyle;
|
||||
import sun.swing.SwingAccessor;
|
||||
@@ -1447,6 +1448,18 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
|
||||
gtkAAFontSettingsCond = SwingUtilities2.isLocalDisplay();
|
||||
aaTextInfo = new HashMap<>(2);
|
||||
SwingUtilities2.putAATextInfo(gtkAAFontSettingsCond, aaTextInfo);
|
||||
|
||||
Object value = GTKEngine.INSTANCE.getSetting(GTKEngine.Settings.GTK_XFT_DPI);
|
||||
if (value instanceof Integer) {
|
||||
int dpi = ((Integer)value).intValue() / 1024;
|
||||
if (dpi == -1) {
|
||||
dpi = 96;
|
||||
}
|
||||
if (dpi < 50) {
|
||||
dpi = 50;
|
||||
}
|
||||
X11GraphicsDevice.setGlobalScale(Math.round(dpi / 96f));
|
||||
}
|
||||
}
|
||||
|
||||
static ReferenceQueue<GTKLookAndFeel> queue = new ReferenceQueue<GTKLookAndFeel>();
|
||||
|
||||
@@ -30,8 +30,10 @@ import java.awt.geom.AffineTransform;
|
||||
import javax.swing.plaf.FontUIResource;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.font.FontConfigManager;
|
||||
import sun.font.FontUtilities;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
|
||||
/**
|
||||
* @author Shannon Hickey
|
||||
@@ -161,11 +163,15 @@ class PangoFonts {
|
||||
*/
|
||||
double dsize = size;
|
||||
int dpi = 96;
|
||||
Object value =
|
||||
Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI");
|
||||
Object xftDPI = Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI");
|
||||
Object value = xftDPI;
|
||||
|
||||
if (!(value instanceof Integer)) {
|
||||
value = GTKEngine.INSTANCE.getSetting(GTKEngine.Settings.GTK_XFT_DPI);
|
||||
}
|
||||
if (value instanceof Integer) {
|
||||
dpi = ((Integer)value).intValue() / 1024;
|
||||
if (dpi == -1) {
|
||||
if (dpi == -1 || SunGraphicsEnvironment.isUIScaleEnabled()) {
|
||||
dpi = 96;
|
||||
}
|
||||
if (dpi < 50) { /* 50 dpi is the minimum value gnome allows */
|
||||
@@ -175,6 +181,12 @@ class PangoFonts {
|
||||
* 72 dpi, so we need to adjust for that.
|
||||
*/
|
||||
dsize = ((double)(dpi * size)/ 72.0);
|
||||
|
||||
if (xftDPI == null) {
|
||||
// [tav] used to indicate the 96/72 scale correction to the client app
|
||||
AWTAccessor.getToolkitAccessor().setDesktopProperty(
|
||||
Toolkit.getDefaultToolkit(), "gnome.Xft/DPI", value);
|
||||
}
|
||||
} else {
|
||||
/* If there's no property, GTK scales for the resolution
|
||||
* reported by the Xserver using the formula listed above.
|
||||
|
||||
@@ -1820,6 +1820,7 @@ public class Font implements java.io.Serializable
|
||||
nonIdentityTx == font.nonIdentityTx &&
|
||||
hasLayoutAttributes == font.hasLayoutAttributes &&
|
||||
pointSize == font.pointSize &&
|
||||
createdFont == font.createdFont &&
|
||||
name.equals(font.name)) {
|
||||
|
||||
/* 'values' is usually initialized lazily, except when
|
||||
@@ -2847,6 +2848,11 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
|
||||
|
||||
/**
|
||||
* A flag to layoutGlyphVector requesting to disable detection of paired characters
|
||||
* when splitting text into scripts.
|
||||
*/
|
||||
public static final int LAYOUT_NO_PAIRED_CHARS_AT_SCRIPT_SPLIT = 8;
|
||||
|
||||
private static void applyTransform(AffineTransform trans, AttributeValues values) {
|
||||
if (trans == null) {
|
||||
|
||||
@@ -1392,6 +1392,11 @@ public abstract class Toolkit {
|
||||
public void setPlatformResources(ResourceBundle bundle) {
|
||||
Toolkit.setPlatformResources(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDesktopProperty(Toolkit tk, String prop, Object value) {
|
||||
tk.setDesktopProperty(prop, value);
|
||||
}
|
||||
});
|
||||
|
||||
java.security.AccessController.doPrivileged(
|
||||
|
||||
@@ -568,7 +568,8 @@ public class Window extends Container implements Accessible {
|
||||
*/
|
||||
public Window(Frame owner) {
|
||||
this(owner == null ? (GraphicsConfiguration)null :
|
||||
owner.getGraphicsConfiguration());
|
||||
// until peer is not created, the device should match default to correctly handle bounds settings
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration());
|
||||
ownedInit(owner);
|
||||
}
|
||||
|
||||
@@ -598,7 +599,8 @@ public class Window extends Container implements Accessible {
|
||||
*/
|
||||
public Window(Window owner) {
|
||||
this(owner == null ? (GraphicsConfiguration)null :
|
||||
owner.getGraphicsConfiguration());
|
||||
// until peer is not created, the device should match default to correctly handle bounds settings
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration());
|
||||
ownedInit(owner);
|
||||
}
|
||||
|
||||
|
||||
@@ -118,4 +118,13 @@ public interface WindowPeer extends ContainerPeer {
|
||||
* Instructs the peer to update the position of the security warning.
|
||||
*/
|
||||
void repositionSecurityWarning();
|
||||
|
||||
/**
|
||||
* Returns platform window handle.
|
||||
*
|
||||
* @return platform window handle
|
||||
*/
|
||||
default long getWindowHandle() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,12 @@ import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Point;
|
||||
import java.awt.Window;
|
||||
|
||||
import sun.awt.ModalExclude;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.swing.SwingUtilities2;
|
||||
|
||||
/**
|
||||
* Popups are used to display a <code>Component</code> to the user, typically
|
||||
@@ -161,8 +164,11 @@ public class Popup {
|
||||
|
||||
if (c instanceof JWindow) {
|
||||
JWindow component = (JWindow)getComponent();
|
||||
|
||||
Point ownerPt = SwingUtilities2.scalePoint(owner, new Point(ownerX, ownerY), component);
|
||||
|
||||
// Sets the proper location, and resets internal state of the window
|
||||
component.setBounds(ownerX, ownerY, 1, 1);
|
||||
component.setBounds(ownerPt.x, ownerPt.y, 1, 1);
|
||||
component.getContentPane().add(contents, BorderLayout.CENTER);
|
||||
component.invalidate();
|
||||
component.validate();
|
||||
|
||||
@@ -1211,8 +1211,15 @@ public class RepaintManager
|
||||
GraphicsConfiguration gc = gd.getDefaultConfiguration();
|
||||
virtualBounds = virtualBounds.union(gc.getBounds());
|
||||
}
|
||||
doubleBufferMaxSize = new Dimension(virtualBounds.width,
|
||||
virtualBounds.height);
|
||||
doubleBufferMaxSize =
|
||||
// Sometimes underlying desktop environment reports
|
||||
// incorrect gc bounds (w=0,h=0). Replace them with
|
||||
// maximum values (as we do for headless mode)
|
||||
new Dimension(
|
||||
virtualBounds.width == 0 ?
|
||||
Integer.MAX_VALUE : virtualBounds.width,
|
||||
virtualBounds.height == 0 ?
|
||||
Integer.MAX_VALUE : virtualBounds.height);
|
||||
} catch (HeadlessException e) {
|
||||
doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@@ -1584,7 +1584,12 @@ public abstract class AbstractDocument implements Document, Serializable {
|
||||
/**
|
||||
* Document property that indicates if a character has been inserted
|
||||
* into the document that is more than one byte long. GlyphView uses
|
||||
* this to determine if it should use BreakIterator.
|
||||
* this to determine if it should use BreakIterator. This property should
|
||||
* not be publicly exposed, since it is used for implementation convenience
|
||||
* only. As a side effect, copies of this property may be in its subclasses
|
||||
* that live in different packages (e.g. HTMLDocument as of now), so those
|
||||
* copies should also be taken care of when this property needs to be
|
||||
* modified.
|
||||
*/
|
||||
static final Object MultiByteProperty = "multiByte";
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ public abstract class FlowView extends BoxView {
|
||||
float min = layoutPool.getMinimumSpan(axis);
|
||||
// Don't include insets, Box.getXXXSpan will include them.
|
||||
r.minimum = (int)min;
|
||||
r.preferred = Math.max(r.minimum, (int) pref);
|
||||
r.preferred = Math.max(r.minimum, (int) Math.ceil(pref));
|
||||
r.maximum = Integer.MAX_VALUE;
|
||||
r.alignment = 0.5f;
|
||||
return r;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user