Merge
This commit is contained in:
commit
e0f6f70d3f
233
bin/idea.sh
233
bin/idea.sh
@ -25,21 +25,7 @@
|
||||
# Shell script for generating an IDEA project from a given list of modules
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [-h|--help] [-q|--quiet] [-a|--absolute-paths] [-o|--output <path>] [modules...]"
|
||||
echo " -h | --help"
|
||||
echo " -q | --quiet
|
||||
No stdout output"
|
||||
echo " -a | --absolute-paths
|
||||
Use absolute paths to this jdk, so that generated .idea
|
||||
project files can be moved independently of jdk sources"
|
||||
echo " -o | --output <path>
|
||||
Where .idea directory with project files will be generated
|
||||
(e.g. using '-o .' will place project files in './.idea')
|
||||
Default: $TOPLEVEL_DIR"
|
||||
echo " [modules...]
|
||||
Generate project modules for specific java modules
|
||||
(e.g. 'java.base java.desktop')
|
||||
Default: all existing modules (java.* and jdk.*)"
|
||||
echo "usage: $0 [-h|--help] [-v|--verbose] [-o|--output <path>] [modules]+"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -47,12 +33,10 @@ SCRIPT_DIR=`dirname $0`
|
||||
#assume TOP is the dir from which the script has been called
|
||||
TOP=`pwd`
|
||||
cd $SCRIPT_DIR; SCRIPT_DIR=`pwd`
|
||||
cd .. ; TOPLEVEL_DIR=`pwd`
|
||||
cd $TOP;
|
||||
|
||||
IDEA_OUTPUT=$TOPLEVEL_DIR/.idea
|
||||
VERBOSE=true
|
||||
ABSOLUTE_PATHS=false
|
||||
IDEA_OUTPUT=$TOP/.idea
|
||||
VERBOSE="false"
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case $1 in
|
||||
@ -60,12 +44,8 @@ do
|
||||
usage
|
||||
;;
|
||||
|
||||
-q | --quiet )
|
||||
VERBOSE=false
|
||||
;;
|
||||
|
||||
-a | --absolute-paths )
|
||||
ABSOLUTE_PATHS=true
|
||||
-v | --vebose )
|
||||
VERBOSE="true"
|
||||
;;
|
||||
|
||||
-o | --output )
|
||||
@ -86,13 +66,18 @@ done
|
||||
|
||||
mkdir -p $IDEA_OUTPUT || exit 1
|
||||
cd $IDEA_OUTPUT; IDEA_OUTPUT=`pwd`
|
||||
cd ..; IDEA_OUTPUT_PARENT=`pwd`
|
||||
|
||||
MAKE_DIR="$TOPLEVEL_DIR/make"
|
||||
if [ "x$TOPLEVEL_DIR" = "x" ] ; then
|
||||
cd $SCRIPT_DIR/..
|
||||
TOPLEVEL_DIR=`pwd`
|
||||
cd $IDEA_OUTPUT
|
||||
fi
|
||||
|
||||
MAKE_DIR="$SCRIPT_DIR/../make"
|
||||
IDEA_MAKE="$MAKE_DIR/ide/idea/jdk"
|
||||
IDEA_TEMPLATE="$IDEA_MAKE/template"
|
||||
|
||||
cp -rn "$IDEA_TEMPLATE"/* "$IDEA_OUTPUT"
|
||||
cp -r "$IDEA_TEMPLATE"/* "$IDEA_OUTPUT"
|
||||
|
||||
#override template
|
||||
if [ -d "$TEMPLATES_OVERRIDE" ] ; then
|
||||
@ -101,31 +86,31 @@ if [ -d "$TEMPLATES_OVERRIDE" ] ; then
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$VERBOSE" = true ] ; then
|
||||
echo "Will generate IDEA project files in \"$IDEA_OUTPUT\" for project \"$TOPLEVEL_DIR\""
|
||||
if [ "$VERBOSE" = "true" ] ; then
|
||||
echo "output dir: $IDEA_OUTPUT"
|
||||
echo "idea template dir: $IDEA_TEMPLATE"
|
||||
fi
|
||||
|
||||
cd $TOP ; make -f "$IDEA_MAKE/idea.gmk" -I "$TOPLEVEL_DIR" idea \
|
||||
MAKEOVERRIDES= IDEA_OUTPUT_PARENT="$IDEA_OUTPUT_PARENT" OUT="$IDEA_OUTPUT/env.cfg" MODULES="$*" || exit 1
|
||||
cd $TOP ; make -f "$IDEA_MAKE/idea.gmk" -I $MAKE_DIR/.. idea MAKEOVERRIDES= OUT=$IDEA_OUTPUT/env.cfg MODULES="$*" || exit 1
|
||||
cd $SCRIPT_DIR
|
||||
|
||||
. $IDEA_OUTPUT/env.cfg
|
||||
|
||||
# Expect MODULES, MODULE_NAMES, RELATIVE_PROJECT_DIR, RELATIVE_BUILD_DIR to be set
|
||||
if [ "xMODULES" = "x" ] ; then
|
||||
echo "FATAL: MODULES is empty" >&2; exit 1
|
||||
# Expect MODULE_ROOTS, MODULE_NAMES, BOOT_JDK & SPEC to be set
|
||||
if [ "x$MODULE_ROOTS" = "x" ] ; then
|
||||
echo "FATAL: MODULE_ROOTS is empty" >&2; exit 1
|
||||
fi
|
||||
|
||||
if [ "x$MODULE_NAMES" = "x" ] ; then
|
||||
echo "FATAL: MODULE_NAMES is empty" >&2; exit 1
|
||||
fi
|
||||
|
||||
if [ "x$RELATIVE_PROJECT_DIR" = "x" ] ; then
|
||||
echo "FATAL: RELATIVE_PROJECT_DIR is empty" >&2; exit 1
|
||||
if [ "x$BOOT_JDK" = "x" ] ; then
|
||||
echo "FATAL: BOOT_JDK is empty" >&2; exit 1
|
||||
fi
|
||||
|
||||
if [ "x$RELATIVE_BUILD_DIR" = "x" ] ; then
|
||||
echo "FATAL: RELATIVE_BUILD_DIR is empty" >&2; exit 1
|
||||
if [ "x$SPEC" = "x" ] ; then
|
||||
echo "FATAL: SPEC is empty" >&2; exit 1
|
||||
fi
|
||||
|
||||
if [ -d "$TOPLEVEL_DIR/.hg" ] ; then
|
||||
@ -136,29 +121,6 @@ if [ -d "$TOPLEVEL_DIR/.git" ] ; then
|
||||
VCS_TYPE="Git"
|
||||
fi
|
||||
|
||||
if [ "$ABSOLUTE_PATHS" = true ] ; then
|
||||
if [ "x$PATHTOOL" != "x" ]; then
|
||||
PROJECT_DIR="`$PATHTOOL -am $TOPLEVEL_DIR`"
|
||||
else
|
||||
PROJECT_DIR="$TOPLEVEL_DIR"
|
||||
fi
|
||||
MODULE_DIR="$PROJECT_DIR"
|
||||
cd "$TOPLEVEL_DIR" && cd "$RELATIVE_BUILD_DIR" && BUILD_DIR="`pwd`"
|
||||
else
|
||||
if [ "$RELATIVE_PROJECT_DIR" = "." ] ; then
|
||||
PROJECT_DIR=""
|
||||
else
|
||||
PROJECT_DIR="/$RELATIVE_PROJECT_DIR"
|
||||
fi
|
||||
MODULE_DIR="\$MODULE_DIR\$$PROJECT_DIR"
|
||||
PROJECT_DIR="\$PROJECT_DIR\$$PROJECT_DIR"
|
||||
BUILD_DIR="\$PROJECT_DIR\$/$RELATIVE_BUILD_DIR"
|
||||
fi
|
||||
if [ "$VERBOSE" = true ] ; then
|
||||
echo "Project root: $PROJECT_DIR"
|
||||
echo "Generating IDEA project files..."
|
||||
fi
|
||||
|
||||
### Replace template variables
|
||||
|
||||
NUM_REPLACEMENTS=0
|
||||
@ -182,82 +144,105 @@ add_replacement() {
|
||||
eval TO$NUM_REPLACEMENTS='$2'
|
||||
}
|
||||
|
||||
add_replacement "###PROJECT_DIR###" "$PROJECT_DIR"
|
||||
add_replacement "###MODULE_DIR###" "$MODULE_DIR"
|
||||
add_replacement "###MODULE_NAMES###" "$MODULE_NAMES"
|
||||
add_replacement "###VCS_TYPE###" "$VCS_TYPE"
|
||||
add_replacement "###BUILD_DIR###" "$BUILD_DIR"
|
||||
if [ "x$PATHTOOL" != "x" ]; then
|
||||
add_replacement "###BASH_RUNNER_PREFIX###" "\$PROJECT_DIR\$/.idea/bash.bat"
|
||||
else
|
||||
add_replacement "###BASH_RUNNER_PREFIX###" ""
|
||||
fi
|
||||
if [ "x$PATHTOOL" != "x" ]; then
|
||||
SPEC_DIR=`dirname $SPEC`
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
add_replacement "###BUILD_DIR###" "`cygpath -am $SPEC_DIR`"
|
||||
add_replacement "###IMAGES_DIR###" "`cygpath -am $SPEC_DIR`/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "`cygpath -am $TOPLEVEL_DIR`"
|
||||
add_replacement "###IDEA_DIR###" "`cygpath -am $IDEA_OUTPUT`"
|
||||
if [ "x$JT_HOME" = "x" ]; then
|
||||
add_replacement "###JTREG_HOME###" ""
|
||||
else
|
||||
add_replacement "###JTREG_HOME###" "`$PATHTOOL -am $JT_HOME`"
|
||||
add_replacement "###JTREG_HOME###" "`cygpath -am $JT_HOME`"
|
||||
fi
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
add_replacement "###BUILD_DIR###" "`wslpath -am $SPEC_DIR`"
|
||||
add_replacement "###IMAGES_DIR###" "`wslpath -am $SPEC_DIR`/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "`wslpath -am $TOPLEVEL_DIR`"
|
||||
add_replacement "###IDEA_DIR###" "`wslpath -am $IDEA_OUTPUT`"
|
||||
if [ "x$JT_HOME" = "x" ]; then
|
||||
add_replacement "###JTREG_HOME###" ""
|
||||
else
|
||||
add_replacement "###JTREG_HOME###" "`wslpath -am $JT_HOME`"
|
||||
fi
|
||||
else
|
||||
add_replacement "###BUILD_DIR###" "$SPEC_DIR"
|
||||
add_replacement "###JTREG_HOME###" "$JT_HOME"
|
||||
add_replacement "###IMAGES_DIR###" "$SPEC_DIR/images/jdk"
|
||||
add_replacement "###ROOT_DIR###" "$TOPLEVEL_DIR"
|
||||
add_replacement "###IDEA_DIR###" "$IDEA_OUTPUT"
|
||||
fi
|
||||
|
||||
MODULE_IMLS=""
|
||||
TEST_MODULE_DEPENDENCIES=""
|
||||
for module in $MODULE_NAMES; do
|
||||
MODULE_IMLS="$MODULE_IMLS<module fileurl=\"file://\$PROJECT_DIR$/.idea/$module.iml\" filepath=\"\$PROJECT_DIR$/.idea/$module.iml\" /> "
|
||||
TEST_MODULE_DEPENDENCIES="$TEST_MODULE_DEPENDENCIES<orderEntry type=\"module\" module-name=\"$module\" scope=\"TEST\" /> "
|
||||
SOURCE_PREFIX="<sourceFolder url=\"file://"
|
||||
SOURCE_POSTFIX="\" isTestSource=\"false\" />"
|
||||
|
||||
for root in $MODULE_ROOTS; do
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
root=`cygpath -am $root`
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
root=`wslpath -am $root`
|
||||
fi
|
||||
|
||||
VM_CI="jdk.internal.vm.ci/share/classes"
|
||||
VM_COMPILER="src/jdk.internal.vm.compiler/share/classes"
|
||||
if test "${root#*$VM_CI}" != "$root" || test "${root#*$VM_COMPILER}" != "$root"; then
|
||||
for subdir in "$root"/*; do
|
||||
if [ -d "$subdir" ]; then
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$subdir"/src"$SOURCE_POSTFIX"
|
||||
fi
|
||||
done
|
||||
else
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
fi
|
||||
done
|
||||
add_replacement "###MODULE_IMLS###" "$MODULE_IMLS"
|
||||
add_replacement "###TEST_MODULE_DEPENDENCIES###" "$TEST_MODULE_DEPENDENCIES"
|
||||
|
||||
add_replacement "###SOURCE_ROOTS###" "$SOURCES"
|
||||
|
||||
replace_template_dir "$IDEA_OUTPUT"
|
||||
|
||||
### Generate module project files
|
||||
### Compile the custom Logger
|
||||
|
||||
if [ "$VERBOSE" = true ] ; then
|
||||
echo "Generating project modules:"
|
||||
fi
|
||||
(
|
||||
DEFAULT_IFS="$IFS"
|
||||
IFS='#'
|
||||
for value in $MODULES; do
|
||||
(
|
||||
eval "$value"
|
||||
if [ "$VERBOSE" = true ] ; then
|
||||
echo " $module"
|
||||
fi
|
||||
add_replacement "###MODULE_CONTENT###" "src/$module"
|
||||
SOURCE_DIRS=""
|
||||
IFS=' '
|
||||
for dir in $moduleSrcDirs; do
|
||||
case $dir in # Exclude generated sources to avoid module-info conflicts, see https://youtrack.jetbrains.com/issue/IDEA-185108
|
||||
"src/"*) SOURCE_DIRS="$SOURCE_DIRS<sourceFolder url=\"file://$MODULE_DIR/$dir\" isTestSource=\"false\" /> "
|
||||
esac
|
||||
done
|
||||
add_replacement "###SOURCE_DIRS###" "$SOURCE_DIRS"
|
||||
DEPENDENCIES=""
|
||||
for dep in $moduleDependencies; do
|
||||
case $MODULE_NAMES in # Exclude skipped modules from dependencies
|
||||
*"$dep"*) DEPENDENCIES="$DEPENDENCIES<orderEntry type=\"module\" module-name=\"$dep\" /> "
|
||||
esac
|
||||
done
|
||||
add_replacement "###DEPENDENCIES###" "$DEPENDENCIES"
|
||||
cp "$IDEA_OUTPUT/module.iml" "$IDEA_OUTPUT/$module.iml"
|
||||
IFS="$DEFAULT_IFS"
|
||||
replace_template_file "$IDEA_OUTPUT/$module.iml"
|
||||
)
|
||||
done
|
||||
)
|
||||
rm "$IDEA_OUTPUT/module.iml"
|
||||
CLASSES=$IDEA_OUTPUT/classes
|
||||
|
||||
### Create shell script runner for Windows
|
||||
|
||||
if [ "x$PATHTOOL" != "x" ]; then
|
||||
echo "@echo off" > "$IDEA_OUTPUT/bash.bat"
|
||||
if [ "x$WSL_DISTRO_NAME" != "x" ] ; then
|
||||
echo "wsl -d $WSL_DISTRO_NAME --cd \"%cd%\" -e %*" >> "$IDEA_OUTPUT/bash.bat"
|
||||
else
|
||||
echo "$WINENV_ROOT\bin\bash.exe -l -c \"cd %CD:\=/%/ && %*\"" >> "$IDEA_OUTPUT/bash.bat"
|
||||
fi
|
||||
if [ "x$ANT_HOME" = "x" ] ; then
|
||||
# try some common locations, before giving up
|
||||
if [ -f "/usr/share/ant/lib/ant.jar" ] ; then
|
||||
ANT_HOME="/usr/share/ant"
|
||||
elif [ -f "/usr/local/Cellar/ant/1.9.4/libexec/lib/ant.jar" ] ; then
|
||||
ANT_HOME="/usr/local/Cellar/ant/1.9.4/libexec"
|
||||
else
|
||||
echo "FATAL: cannot find ant. Try setting ANT_HOME." >&2; exit 1
|
||||
fi
|
||||
fi
|
||||
CP=$ANT_HOME/lib/ant.jar
|
||||
rm -rf $CLASSES; mkdir $CLASSES
|
||||
|
||||
if [ "x$CYGPATH" != "x" ] ; then ## CYGPATH may be set in env.cfg
|
||||
JAVAC_SOURCE_FILE=`cygpath -am $IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java`
|
||||
JAVAC_SOURCE_PATH=`cygpath -am $IDEA_OUTPUT/src`
|
||||
JAVAC_CLASSES=`cygpath -am $CLASSES`
|
||||
JAVAC_CP=`cygpath -am $CP`
|
||||
JAVAC=javac
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
JAVAC_SOURCE_FILE=`realpath --relative-to=./ $IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java`
|
||||
JAVAC_SOURCE_PATH=`realpath --relative-to=./ $IDEA_OUTPUT/src`
|
||||
JAVAC_CLASSES=`realpath --relative-to=./ $CLASSES`
|
||||
ANT_TEMP=`mktemp -d -p ./`
|
||||
cp $ANT_HOME/lib/ant.jar $ANT_TEMP/ant.jar
|
||||
JAVAC_CP=$ANT_TEMP/ant.jar
|
||||
JAVAC=javac.exe
|
||||
else
|
||||
JAVAC_SOURCE_FILE=$IDEA_OUTPUT/src/idea/IdeaLoggerWrapper.java
|
||||
JAVAC_SOURCE_PATH=$IDEA_OUTPUT/src
|
||||
JAVAC_CLASSES=$CLASSES
|
||||
JAVAC_CP=$CP
|
||||
JAVAC=javac
|
||||
fi
|
||||
|
||||
$BOOT_JDK/bin/$JAVAC -d $JAVAC_CLASSES -sourcepath $JAVAC_SOURCE_PATH -cp $JAVAC_CP $JAVAC_SOURCE_FILE
|
||||
|
||||
if [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
rm -rf $ANT_TEMP
|
||||
fi
|
@ -542,6 +542,9 @@ AC_DEFUN([JVM_FEATURES_VERIFY],
|
||||
if ! JVM_FEATURES_IS_ACTIVE(jvmci); then
|
||||
INCLUDE_JVMCI="false"
|
||||
fi
|
||||
if JVM_FEATURES_IS_ACTIVE(compiler2); then
|
||||
INCLUDE_COMPILER2="true"
|
||||
fi
|
||||
|
||||
# Verify that we have at least one gc selected (i.e., feature named "*gc").
|
||||
if ! JVM_FEATURES_IS_ACTIVE(.*gc); then
|
||||
@ -565,6 +568,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_SETUP],
|
||||
# missing any of them.
|
||||
ENABLE_CDS="true"
|
||||
INCLUDE_JVMCI="true"
|
||||
INCLUDE_COMPILER2="false"
|
||||
|
||||
for variant in $JVM_VARIANTS; do
|
||||
# Figure out if any features are unavailable, or should be filtered out
|
||||
@ -601,5 +605,6 @@ AC_DEFUN_ONCE([JVM_FEATURES_SETUP],
|
||||
AC_SUBST(JVM_FEATURES_custom)
|
||||
|
||||
AC_SUBST(INCLUDE_JVMCI)
|
||||
AC_SUBST(INCLUDE_COMPILER2)
|
||||
|
||||
])
|
||||
|
@ -853,6 +853,7 @@ PNG_CFLAGS:=@PNG_CFLAGS@
|
||||
|
||||
INCLUDE_SA=@INCLUDE_SA@
|
||||
INCLUDE_JVMCI=@INCLUDE_JVMCI@
|
||||
INCLUDE_COMPILER2=@INCLUDE_COMPILER2@
|
||||
|
||||
OS_VERSION_MAJOR:=@OS_VERSION_MAJOR@
|
||||
OS_VERSION_MINOR:=@OS_VERSION_MINOR@
|
||||
|
42
make/ide/idea/jdk/build.xml
Normal file
42
make/ide/idea/jdk/build.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- importing.xml -->
|
||||
<project name="jdk">
|
||||
|
||||
<taskdef name="wrapLogger" classname="idea.IdeaLoggerWrapper" classpath="${idea.dir}/classes"/>
|
||||
|
||||
<wrapLogger/>
|
||||
|
||||
<macrodef name="call-make">
|
||||
<attribute name="dir"/>
|
||||
<attribute name="args"/>
|
||||
<sequential>
|
||||
<exec executable="make" dir="@{dir}" failonerror="true">
|
||||
<arg line="@{args}"/>
|
||||
<env key="CLASSPATH" value = ""/>
|
||||
</exec>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<target name="cond-clean" unless="${intellij.ismake}">
|
||||
<antcall target="clean"/>
|
||||
</target>
|
||||
|
||||
<target name="post-make" depends="cond-clean, build-module"/>
|
||||
|
||||
<!--
|
||||
**** Global JDK Build Targets
|
||||
-->
|
||||
|
||||
<target name="clean">
|
||||
<echo message="base = ${basedir}"/>
|
||||
<call-make dir = "${build.target.dir}" args = "reconfigure"/>
|
||||
<call-make dir = "${build.target.dir}" args = "clean"/>
|
||||
</target>
|
||||
|
||||
<target name="images">
|
||||
<call-make dir = "${build.target.dir}" args = "images"/>
|
||||
</target>
|
||||
|
||||
<target name="build-module">
|
||||
<call-make dir = "${build.target.dir}" args = "${module.name}"/>
|
||||
</target>
|
||||
</project>
|
@ -46,16 +46,13 @@ else #with SPEC
|
||||
endif
|
||||
|
||||
idea:
|
||||
$(ECHO) "MODULES=\"$(foreach mod, $(SEL_MODULES), \
|
||||
module='$(mod)' \
|
||||
moduleSrcDirs='$(foreach m,$(call FindModuleSrcDirs,$(mod)),$(call RelativePath,$m,$(topdir)))' \
|
||||
moduleDependencies='$(call FindTransitiveDepsForModule,$(mod))' \
|
||||
#)\"" > $(OUT)
|
||||
$(ECHO) "SUPPORT=$(SUPPORT_OUTPUTDIR)" >> $(OUT)
|
||||
$(ECHO) "MODULE_ROOTS=\"$(foreach mod, $(SEL_MODULES), $(call FindModuleSrcDirs,$(mod)))\"" >> $(OUT)
|
||||
$(ECHO) "MODULE_NAMES=\"$(strip $(foreach mod, $(SEL_MODULES), $(mod)))\"" >> $(OUT)
|
||||
$(ECHO) "RELATIVE_PROJECT_DIR=\"$(call RelativePath,$(topdir),$(IDEA_OUTPUT_PARENT))\"" >> $(OUT)
|
||||
$(ECHO) "RELATIVE_BUILD_DIR=\"$(call RelativePath,$(OUTPUTDIR),$(IDEA_OUTPUT_PARENT))\"" >> $(OUT)
|
||||
$(ECHO) "PATHTOOL=\"$(PATHTOOL)\"" >> $(OUT)
|
||||
$(ECHO) "SEL_MODULES=\"$(SEL_MODULES)\"" >> $(OUT)
|
||||
$(ECHO) "BOOT_JDK=\"$(BOOT_JDK)\"" >> $(OUT)
|
||||
$(ECHO) "CYGPATH=\"$(PATHTOOL)\"" >> $(OUT)
|
||||
$(ECHO) "SPEC=\"$(SPEC)\"" >> $(OUT)
|
||||
$(ECHO) "JT_HOME=\"$(JT_HOME)\"" >> $(OUT)
|
||||
$(ECHO) "WINENV_ROOT=\"$(WINENV_ROOT)\"" >> $(OUT)
|
||||
|
||||
endif
|
||||
|
14
make/ide/idea/jdk/template/ant.xml
Normal file
14
make/ide/idea/jdk/template/ant.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://###ROOT_DIR###/make/ide/idea/jdk/build.xml">
|
||||
<properties>
|
||||
<property name="intellij.ismake" value="$IsMake$" />
|
||||
<property name="build.target.dir" value="###BUILD_DIR###" />
|
||||
<property name="module.name" value="###MODULE_NAMES###" />
|
||||
<property name="idea.dir" value="###IDEA_DIR###" />
|
||||
</properties>
|
||||
<executeOn event="afterCompilation" target="post-make" />
|
||||
</buildFile>
|
||||
</component>
|
||||
</project>
|
@ -3,10 +3,10 @@
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<excludeFromCompile>
|
||||
<directory url="file://###PROJECT_DIR###/src" includeSubdirectories="true" />
|
||||
<directory url="file://###PROJECT_DIR###/build" includeSubdirectories="true" />
|
||||
<directory url="file://###PROJECT_DIR###/make" includeSubdirectories="true" />
|
||||
<directory url="file://###PROJECT_DIR###/test" includeSubdirectories="false" />
|
||||
<directory url="file://###ROOT_DIR###/src" includeSubdirectories="true" />
|
||||
<directory url="file://###ROOT_DIR###/build" includeSubdirectories="true" />
|
||||
<directory url="file://###ROOT_DIR###/make" includeSubdirectories="true" />
|
||||
<directory url="file://###ROOT_DIR###/test" includeSubdirectories="true" />
|
||||
</excludeFromCompile>
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
|
@ -2,9 +2,10 @@
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://###MODULE_DIR###">
|
||||
<excludeFolder url="file://###MODULE_DIR###/build" />
|
||||
<excludeFolder url="file://###MODULE_DIR###/make" />
|
||||
<content url="file://###ROOT_DIR###">
|
||||
###SOURCE_ROOTS###
|
||||
<excludeFolder url="file://###ROOT_DIR###/build" />
|
||||
<excludeFolder url="file://###ROOT_DIR###/make" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
@ -6,8 +6,11 @@
|
||||
<component name="JTRegService">
|
||||
<path>###JTREG_HOME###</path>
|
||||
<workDir>###BUILD_DIR###</workDir>
|
||||
<jre alt="true" value="###BUILD_DIR###/images/jdk" />
|
||||
<jre alt="true" value="###IMAGES_DIR###" />
|
||||
<options></options>
|
||||
<ant>
|
||||
<target file="file://###ROOT_DIR###/make/ide/idea/jdk/build.xml" name="images" />
|
||||
</ant>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" assert-keyword="true" jdk-15="true">
|
||||
<output url="file://###BUILD_DIR###/idea" />
|
||||
|
@ -3,8 +3,6 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/jdk.iml" filepath="$PROJECT_DIR$/.idea/jdk.iml" />
|
||||
###MODULE_IMLS###
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/test.iml" filepath="$PROJECT_DIR$/.idea/test.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
13
make/ide/idea/jdk/template/src/idea/IdeaLoggerWrapper.java
Normal file
13
make/ide/idea/jdk/template/src/idea/IdeaLoggerWrapper.java
Normal file
@ -0,0 +1,13 @@
|
||||
package idea;
|
||||
|
||||
import org.apache.tools.ant.Task;
|
||||
|
||||
/**
|
||||
* This class implements a custom Ant task which replaces the standard Intellij IDEA Ant logger
|
||||
* with a custom one which generates tighter output.
|
||||
*/
|
||||
public class IdeaLoggerWrapper extends Task {
|
||||
public void execute() {
|
||||
new JdkIdeaAntLogger(getProject());
|
||||
}
|
||||
}
|
375
make/ide/idea/jdk/template/src/idea/JdkIdeaAntLogger.java
Normal file
375
make/ide/idea/jdk/template/src/idea/JdkIdeaAntLogger.java
Normal file
@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 idea;
|
||||
|
||||
import org.apache.tools.ant.BuildEvent;
|
||||
import org.apache.tools.ant.BuildListener;
|
||||
import org.apache.tools.ant.DefaultLogger;
|
||||
import org.apache.tools.ant.Project;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Stack;
|
||||
|
||||
import static org.apache.tools.ant.Project.*;
|
||||
|
||||
/**
|
||||
* This class is used to wrap the IntelliJ ant logger in order to provide more meaningful
|
||||
* output when building langtools. The basic ant output in IntelliJ can be quite cumbersome to
|
||||
* work with, as it provides two separate views: (i) a tree view, which is good to display build task
|
||||
* in a hierarchical fashion as they are processed; and a (ii) plain text view, which gives you
|
||||
* the full ant output. The main problem is that javac-related messages are buried into the
|
||||
* ant output (which is made very verbose by IntelliJ in order to support the tree view). It is
|
||||
* not easy to figure out which node to expand in order to see the error message; switching
|
||||
* to plain text doesn't help either, as now the output is totally flat.
|
||||
*
|
||||
* This logger class removes a lot of verbosity from the IntelliJ ant logger by not propagating
|
||||
* all the events to the IntelliJ's logger. In addition, certain events are handled in a custom
|
||||
* fashion, to generate better output during the build.
|
||||
*/
|
||||
public final class JdkIdeaAntLogger extends DefaultLogger {
|
||||
|
||||
/**
|
||||
* This is just a way to pass in customized binary string predicates;
|
||||
*
|
||||
* TODO: replace with @code{BiPredicate<String, String>} and method reference when moving to 8
|
||||
*/
|
||||
enum StringBinaryPredicate {
|
||||
CONTAINS() {
|
||||
@Override
|
||||
boolean apply(String s1, String s2) {
|
||||
return s1.contains(s2);
|
||||
}
|
||||
},
|
||||
STARTS_WITH {
|
||||
@Override
|
||||
boolean apply(String s1, String s2) {
|
||||
return s1.startsWith(s2);
|
||||
}
|
||||
},
|
||||
MATCHES {
|
||||
@Override
|
||||
boolean apply(String s1, String s2) {
|
||||
return s1.matches(s2);
|
||||
}
|
||||
};
|
||||
|
||||
abstract boolean apply(String s1, String s2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Various kinds of ant messages that we shall intercept
|
||||
*/
|
||||
enum MessageKind {
|
||||
|
||||
/** a make error */
|
||||
MAKE_ERROR(StringBinaryPredicate.CONTAINS, MSG_ERR, "error:", "compiler.err"),
|
||||
/** a make warning */
|
||||
MAKE_WARNING(StringBinaryPredicate.CONTAINS, MSG_WARN, "warning:", "compiler.warn"),
|
||||
/** a make note */
|
||||
MAKE_NOTE(StringBinaryPredicate.CONTAINS, MSG_INFO, "note:", "compiler.note"),
|
||||
/** std make output */
|
||||
MAKE_OTHER(StringBinaryPredicate.MATCHES, MSG_INFO, ".*"),
|
||||
/** a javac crash */
|
||||
JAVAC_CRASH(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "An exception has occurred in the compiler"),
|
||||
/** jtreg test success */
|
||||
JTREG_TEST_PASSED(StringBinaryPredicate.STARTS_WITH, MSG_INFO, "Passed: "),
|
||||
/** jtreg test failure */
|
||||
JTREG_TEST_FAILED(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "FAILED: "),
|
||||
/** jtreg test error */
|
||||
JTREG_TEST_ERROR(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "Error: "),
|
||||
/** jtreg report */
|
||||
JTREG_TEST_REPORT(StringBinaryPredicate.STARTS_WITH, MSG_INFO, "Report written");
|
||||
|
||||
StringBinaryPredicate sbp;
|
||||
int priority;
|
||||
String[] keys;
|
||||
|
||||
MessageKind(StringBinaryPredicate sbp, int priority, String... keys) {
|
||||
this.sbp = sbp;
|
||||
this.priority = priority;
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a given message string matches this kind?
|
||||
*/
|
||||
boolean matches(String s) {
|
||||
for (String key : keys) {
|
||||
if (sbp.apply(s, key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum is used to represent the list of tasks we need to keep track of during logging.
|
||||
*/
|
||||
enum Task {
|
||||
/** javac task - invoked during compilation */
|
||||
MAKE("exec", MessageKind.MAKE_ERROR, MessageKind.MAKE_WARNING, MessageKind.MAKE_NOTE,
|
||||
MessageKind.MAKE_OTHER, MessageKind.JAVAC_CRASH),
|
||||
/** jtreg task - invoked during test execution */
|
||||
JTREG("jtreg", MessageKind.JTREG_TEST_PASSED, MessageKind.JTREG_TEST_FAILED, MessageKind.JTREG_TEST_ERROR, MessageKind.JTREG_TEST_REPORT),
|
||||
/** initial synthetic task when the logger is created */
|
||||
ROOT("") {
|
||||
@Override
|
||||
boolean matches(String s) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
/** synthetic task catching any other tasks not in this list */
|
||||
ANY("") {
|
||||
@Override
|
||||
boolean matches(String s) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
String taskName;
|
||||
MessageKind[] msgs;
|
||||
|
||||
Task(String taskName, MessageKind... msgs) {
|
||||
this.taskName = taskName;
|
||||
this.msgs = msgs;
|
||||
}
|
||||
|
||||
boolean matches(String s) {
|
||||
return s.equals(taskName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum is used to represent the list of targets we need to keep track of during logging.
|
||||
* A regular expression is used to match a given target name.
|
||||
*/
|
||||
enum Target {
|
||||
/** jtreg target - executed when launching tests */
|
||||
JTREG("jtreg") {
|
||||
@Override
|
||||
String getDisplayMessage(BuildEvent e) {
|
||||
return "Running jtreg tests: " + e.getProject().getProperty("jtreg.tests");
|
||||
}
|
||||
},
|
||||
/** build selected modules */
|
||||
BUILD_MODULE("build-module") {
|
||||
@Override
|
||||
String getDisplayMessage(BuildEvent e) {
|
||||
return "Building modules: " + e.getProject().getProperty("module.name") + "...";
|
||||
}
|
||||
},
|
||||
/** build images */
|
||||
BUILD_IMAGES("images") {
|
||||
@Override
|
||||
String getDisplayMessage(BuildEvent e) {
|
||||
return "Building images...";
|
||||
}
|
||||
},
|
||||
/** build images */
|
||||
CONFIGURE("-do-configure") {
|
||||
@Override
|
||||
String getDisplayMessage(BuildEvent e) {
|
||||
return "Configuring build...";
|
||||
}
|
||||
},
|
||||
/** synthetic target catching any other target not in this list */
|
||||
ANY("") {
|
||||
@Override
|
||||
String getDisplayMessage(BuildEvent e) {
|
||||
return "Executing Ant target(s): " + e.getProject().getProperty("ant.project.invoked-targets");
|
||||
}
|
||||
@Override
|
||||
boolean matches(String msg) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
String targetRegex;
|
||||
|
||||
Target(String targetRegex) {
|
||||
this.targetRegex = targetRegex;
|
||||
}
|
||||
|
||||
boolean matches(String msg) {
|
||||
return msg.matches(targetRegex);
|
||||
}
|
||||
|
||||
abstract String getDisplayMessage(BuildEvent e);
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom build event used to represent status changes which should be notified inside
|
||||
* Intellij
|
||||
*/
|
||||
static class StatusEvent extends BuildEvent {
|
||||
|
||||
/** the target to which the status update refers */
|
||||
Target target;
|
||||
|
||||
StatusEvent(BuildEvent e, Target target) {
|
||||
super(new StatusTask(e, target.getDisplayMessage(e)));
|
||||
this.target = target;
|
||||
setMessage(getTask().getTaskName(), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom task used to channel info regarding a status change
|
||||
*/
|
||||
static class StatusTask extends org.apache.tools.ant.Task {
|
||||
StatusTask(BuildEvent event, String msg) {
|
||||
setProject(event.getProject());
|
||||
setOwningTarget(event.getTarget());
|
||||
setTaskName(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** wrapped ant logger (IntelliJ's own logger) */
|
||||
DefaultLogger logger;
|
||||
|
||||
/** flag - is this the first target we encounter? */
|
||||
boolean firstTarget = true;
|
||||
|
||||
/** flag - should subsequenet failures be suppressed ? */
|
||||
boolean suppressTaskFailures = false;
|
||||
|
||||
/** flag - have we ran into a javac crash ? */
|
||||
boolean crashFound = false;
|
||||
|
||||
/** stack of status changes associated with pending targets */
|
||||
Stack<StatusEvent> statusEvents = new Stack<>();
|
||||
|
||||
/** stack of pending tasks */
|
||||
Stack<Task> tasks = new Stack<>();
|
||||
|
||||
public JdkIdeaAntLogger(Project project) {
|
||||
for (Object o : project.getBuildListeners()) {
|
||||
if (o instanceof DefaultLogger) {
|
||||
this.logger = (DefaultLogger)o;
|
||||
project.removeBuildListener((BuildListener)o);
|
||||
project.addBuildListener(this);
|
||||
}
|
||||
}
|
||||
tasks.push(Task.ROOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildStarted(BuildEvent event) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildFinished(BuildEvent event) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetStarted(BuildEvent event) {
|
||||
EnumSet<Target> statusKinds = firstTarget ?
|
||||
EnumSet.allOf(Target.class) :
|
||||
EnumSet.complementOf(EnumSet.of(Target.ANY));
|
||||
|
||||
String targetName = event.getTarget().getName();
|
||||
|
||||
for (Target statusKind : statusKinds) {
|
||||
if (statusKind.matches(targetName)) {
|
||||
StatusEvent statusEvent = new StatusEvent(event, statusKind);
|
||||
statusEvents.push(statusEvent);
|
||||
logger.taskStarted(statusEvent);
|
||||
firstTarget = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetFinished(BuildEvent event) {
|
||||
if (!statusEvents.isEmpty()) {
|
||||
StatusEvent lastEvent = statusEvents.pop();
|
||||
if (lastEvent.target.matches(event.getTarget().getName())) {
|
||||
logger.taskFinished(lastEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void taskStarted(BuildEvent event) {
|
||||
String taskName = event.getTask().getTaskName();
|
||||
System.err.println("task started " + taskName);
|
||||
for (Task task : Task.values()) {
|
||||
if (task.matches(taskName)) {
|
||||
tasks.push(task);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void taskFinished(BuildEvent event) {
|
||||
if (tasks.peek() == Task.ROOT) {
|
||||
//we need to 'close' the root task to get nicer output
|
||||
logger.taskFinished(event);
|
||||
} else if (!suppressTaskFailures && event.getException() != null) {
|
||||
//the first (innermost) task failure should always be logged
|
||||
event.setMessage(event.getException().toString(), 0);
|
||||
event.setException(null);
|
||||
//note: we turn this into a plain message to avoid stack trace being logged by Idea
|
||||
logger.messageLogged(event);
|
||||
suppressTaskFailures = true;
|
||||
}
|
||||
tasks.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageLogged(BuildEvent event) {
|
||||
String msg = event.getMessage();
|
||||
|
||||
boolean processed = false;
|
||||
|
||||
if (!tasks.isEmpty()) {
|
||||
Task task = tasks.peek();
|
||||
for (MessageKind messageKind : task.msgs) {
|
||||
if (messageKind.matches(msg)) {
|
||||
event.setMessage(msg, messageKind.priority);
|
||||
processed = true;
|
||||
if (messageKind == MessageKind.JAVAC_CRASH) {
|
||||
crashFound = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPriority() == MSG_ERR || crashFound) {
|
||||
//we log errors regardless of owning task
|
||||
logger.messageLogged(event);
|
||||
suppressTaskFailures = true;
|
||||
} else if (processed) {
|
||||
logger.messageLogged(event);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="###PROJECT_DIR###" vcs="###VCS_TYPE###" />
|
||||
<mapping directory="###ROOT_DIR###" vcs="###VCS_TYPE###" />
|
||||
</component>
|
||||
</project>
|
||||
|
@ -2,62 +2,63 @@
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<ignored path="jdk.iws" />
|
||||
<ignored path="###PROJECT_DIR###/build/idea/out/" />
|
||||
<ignored path="###ROOT_DIR###/build/idea/out/" />
|
||||
<ignored path=".idea/" />
|
||||
</component>
|
||||
<component name="StructureViewFactory">
|
||||
<option name="ACTIVE_ACTIONS" value=",ALPHA_COMPARATOR" />
|
||||
</component>
|
||||
<component name="RunManager" selected="Shell Script.images">
|
||||
<configuration name="clean" type="ShConfigurationType" folderName="make">
|
||||
<option name="SCRIPT_TEXT" value="###BASH_RUNNER_PREFIX### make clean" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="###PROJECT_DIR###" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="images" type="ShConfigurationType" folderName="make">
|
||||
<option name="SCRIPT_TEXT" value="###BASH_RUNNER_PREFIX### make images" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="###PROJECT_DIR###" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="reconfigure" type="ShConfigurationType" folderName="make">
|
||||
<option name="SCRIPT_TEXT" value="###BASH_RUNNER_PREFIX### make reconfigure" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="###PROJECT_DIR###" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue="Shell Script.images" />
|
||||
<item itemvalue="Shell Script.clean" />
|
||||
<item itemvalue="Shell Script.reconfigure" />
|
||||
</list>
|
||||
<component name="antWorkspaceConfiguration">
|
||||
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="FILTER_TARGETS" value="false" />
|
||||
<buildFile url="file://###ROOT_DIR###/make/ide/idea/jdk/build.xml">
|
||||
<runInBackground value="false" />
|
||||
<targetFilters>
|
||||
<filter targetName="clean" isVisible="true" />
|
||||
<filter targetName="images" isVisible="true" />
|
||||
</targetFilters>
|
||||
<treeView value="false" />
|
||||
<expanded value="true" />
|
||||
</buildFile>
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<autoscrollToSource />
|
||||
<autoscrollFromSource />
|
||||
<sortByType />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="jdk" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="PackagesPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="jdk" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="jdk" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
</project>
|
||||
|
@ -27,7 +27,7 @@ include LibCommon.gmk
|
||||
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, linux windows)+$(call isTargetCpu, x86_64), true+true)
|
||||
ifeq ($(call isTargetOs, linux windows)+$(call isTargetCpu, x86_64)+$(INCLUDE_COMPILER2), true+true+true)
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBSVML, \
|
||||
NAME := svml, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB), \
|
||||
|
@ -643,7 +643,8 @@ void LinearScan::compute_local_live_sets() {
|
||||
CodeEmitInfo* info = visitor.info_at(k);
|
||||
ValueStack* stack = info->stack();
|
||||
for_each_state_value(stack, value,
|
||||
set_live_gen_kill(value, op, live_gen, live_kill)
|
||||
set_live_gen_kill(value, op, live_gen, live_kill);
|
||||
local_has_fpu_registers = local_has_fpu_registers || value->type()->is_float_kind();
|
||||
);
|
||||
}
|
||||
|
||||
@ -1659,22 +1660,33 @@ void LinearScan::allocate_registers() {
|
||||
Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
|
||||
Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
|
||||
|
||||
// allocate cpu registers
|
||||
// collect cpu intervals
|
||||
create_unhandled_lists(&precolored_cpu_intervals, ¬_precolored_cpu_intervals,
|
||||
is_precolored_cpu_interval, is_virtual_cpu_interval);
|
||||
|
||||
// allocate fpu registers
|
||||
// collect fpu intervals
|
||||
create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals,
|
||||
is_precolored_fpu_interval, is_virtual_fpu_interval);
|
||||
|
||||
// the fpu interval allocation cannot be moved down below with the fpu section as
|
||||
// this fpu interval collection cannot be moved down below with the allocation section as
|
||||
// the cpu_lsw.walk() changes interval positions.
|
||||
|
||||
if (!has_fpu_registers()) {
|
||||
#ifdef ASSERT
|
||||
assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
|
||||
#else
|
||||
if (not_precolored_fpu_intervals != Interval::end()) {
|
||||
BAILOUT("missed an uncolored fpu interval");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// allocate cpu registers
|
||||
LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
|
||||
cpu_lsw.walk();
|
||||
cpu_lsw.finish_allocation();
|
||||
|
||||
if (has_fpu_registers()) {
|
||||
// allocate fpu registers
|
||||
LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
|
||||
fpu_lsw.walk();
|
||||
fpu_lsw.finish_allocation();
|
||||
|
@ -390,7 +390,7 @@ static void rewrite_nofast_bytecode(const methodHandle& method) {
|
||||
void MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread* thread, InstanceKlass* ik) {
|
||||
for (int i = 0; i < ik->methods()->length(); i++) {
|
||||
methodHandle m(thread, ik->methods()->at(i));
|
||||
if (!ik->can_be_verified_at_dumptime()) {
|
||||
if (ik->can_be_verified_at_dumptime()) {
|
||||
rewrite_nofast_bytecode(m);
|
||||
}
|
||||
Fingerprinter fp(m);
|
||||
@ -574,7 +574,7 @@ public:
|
||||
bool MetaspaceShared::linking_required(InstanceKlass* ik) {
|
||||
// For static CDS dump, do not link old classes.
|
||||
// For dynamic CDS dump, only link classes loaded by the builtin class loaders.
|
||||
return DumpSharedSpaces ? !ik->can_be_verified_at_dumptime() : !ik->is_shared_unregistered_class();
|
||||
return DumpSharedSpaces ? ik->can_be_verified_at_dumptime() : !ik->is_shared_unregistered_class();
|
||||
}
|
||||
|
||||
bool MetaspaceShared::link_class_for_cds(InstanceKlass* ik, TRAPS) {
|
||||
@ -750,7 +750,7 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) {
|
||||
ExceptionMark em(current);
|
||||
JavaThread* THREAD = current; // For exception macros.
|
||||
Arguments::assert_is_dumping_archive();
|
||||
if (ik->is_loaded() && !ik->is_linked() && !ik->can_be_verified_at_dumptime() &&
|
||||
if (ik->is_loaded() && !ik->is_linked() && ik->can_be_verified_at_dumptime() &&
|
||||
!SystemDictionaryShared::has_class_failed_verification(ik)) {
|
||||
bool saved = BytecodeVerificationLocal;
|
||||
if (ik->is_shared_unregistered_class() && ik->class_loader() == NULL) {
|
||||
|
@ -1411,7 +1411,7 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) {
|
||||
if (has_class_failed_verification(k)) {
|
||||
return warn_excluded(k, "Failed verification");
|
||||
} else {
|
||||
if (!k->can_be_verified_at_dumptime()) {
|
||||
if (k->can_be_verified_at_dumptime()) {
|
||||
return warn_excluded(k, "Not linked");
|
||||
}
|
||||
}
|
||||
@ -1425,7 +1425,7 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (k->can_be_verified_at_dumptime() && k->is_linked()) {
|
||||
if (!k->can_be_verified_at_dumptime() && k->is_linked()) {
|
||||
return warn_excluded(k, "Old class has been linked");
|
||||
}
|
||||
|
||||
|
@ -571,7 +571,7 @@ void Rewriter::rewrite(InstanceKlass* klass, TRAPS) {
|
||||
#if INCLUDE_CDS
|
||||
if (klass->is_shared()) {
|
||||
assert(!klass->is_rewritten(), "rewritten shared classes cannot be rewritten again");
|
||||
assert(klass->can_be_verified_at_dumptime(), "only shared old classes aren't rewritten");
|
||||
assert(!klass->can_be_verified_at_dumptime(), "only shared old classes aren't rewritten");
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
ResourceMark rm(THREAD);
|
||||
|
@ -370,7 +370,7 @@ void ConstantPool::restore_unshareable_info(TRAPS) {
|
||||
}
|
||||
|
||||
void ConstantPool::remove_unshareable_info() {
|
||||
if (!_pool_holder->is_linked() && _pool_holder->is_shared_old_klass()) {
|
||||
if (!_pool_holder->is_linked() && !_pool_holder->verified_at_dump_time()) {
|
||||
return;
|
||||
}
|
||||
// Resolved references are not in the shared archive.
|
||||
|
@ -2403,8 +2403,8 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
void InstanceKlass::remove_unshareable_info() {
|
||||
|
||||
if (can_be_verified_at_dumptime()) {
|
||||
// Set the old class bit.
|
||||
set_is_shared_old_klass();
|
||||
// Remember this so we can avoid walking the hierarchy at runtime.
|
||||
set_verified_at_dump_time();
|
||||
}
|
||||
|
||||
Klass::remove_unshareable_info();
|
||||
@ -2549,19 +2549,19 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
|
||||
// Verification of archived old classes will be performed during run time.
|
||||
bool InstanceKlass::can_be_verified_at_dumptime() const {
|
||||
if (major_version() < 50 /*JAVA_6_VERSION*/) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (java_super() != NULL && java_super()->can_be_verified_at_dumptime()) {
|
||||
return true;
|
||||
if (java_super() != NULL && !java_super()->can_be_verified_at_dumptime()) {
|
||||
return false;
|
||||
}
|
||||
Array<InstanceKlass*>* interfaces = local_interfaces();
|
||||
int len = interfaces->length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (interfaces->at(i)->can_be_verified_at_dumptime()) {
|
||||
return true;
|
||||
if (!interfaces->at(i)->can_be_verified_at_dumptime()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void InstanceKlass::set_shared_class_loader_type(s2 loader_type) {
|
||||
|
@ -178,7 +178,7 @@ private:
|
||||
enum {
|
||||
_archived_lambda_proxy_is_available = 2,
|
||||
_has_value_based_class_annotation = 4,
|
||||
_is_shared_old_klass = 8
|
||||
_verified_at_dump_time = 8
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -334,11 +334,11 @@ protected:
|
||||
NOT_CDS(return false;)
|
||||
}
|
||||
|
||||
void set_is_shared_old_klass() {
|
||||
CDS_ONLY(_shared_class_flags |= _is_shared_old_klass;)
|
||||
void set_verified_at_dump_time() {
|
||||
CDS_ONLY(_shared_class_flags |= _verified_at_dump_time;)
|
||||
}
|
||||
bool is_shared_old_klass() const {
|
||||
CDS_ONLY(return (_shared_class_flags & _is_shared_old_klass) != 0;)
|
||||
bool verified_at_dump_time() const {
|
||||
CDS_ONLY(return (_shared_class_flags & _verified_at_dump_time) != 0;)
|
||||
NOT_CDS(return false;)
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ inline InstanceKlass* klassVtable::ik() const {
|
||||
}
|
||||
|
||||
bool klassVtable::is_preinitialized_vtable() {
|
||||
return _klass->is_shared() && !MetaspaceShared::remapped_readwrite() && !_klass->is_shared_old_klass();
|
||||
return _klass->is_shared() && !MetaspaceShared::remapped_readwrite() && _klass->verified_at_dump_time();
|
||||
}
|
||||
|
||||
|
||||
@ -1094,8 +1094,8 @@ void itableMethodEntry::initialize(InstanceKlass* klass, Method* m) {
|
||||
#ifdef ASSERT
|
||||
if (MetaspaceShared::is_in_shared_metaspace((void*)&_method) &&
|
||||
!MetaspaceShared::remapped_readwrite() &&
|
||||
!m->method_holder()->can_be_verified_at_dumptime() &&
|
||||
!klass->can_be_verified_at_dumptime()) {
|
||||
m->method_holder()->verified_at_dump_time() &&
|
||||
klass->verified_at_dump_time()) {
|
||||
// At runtime initialize_itable is rerun as part of link_class_impl()
|
||||
// for a shared class loaded by the non-boot loader.
|
||||
// The dumptime itable method entry should be the same as the runtime entry.
|
||||
|
@ -409,7 +409,7 @@ void Method::remove_unshareable_info() {
|
||||
}
|
||||
|
||||
void Method::set_vtable_index(int index) {
|
||||
if (is_shared() && !MetaspaceShared::remapped_readwrite() && !method_holder()->is_shared_old_klass()) {
|
||||
if (is_shared() && !MetaspaceShared::remapped_readwrite() && method_holder()->verified_at_dump_time()) {
|
||||
// At runtime initialize_vtable is rerun as part of link_class_impl()
|
||||
// for a shared class loaded by the non-boot loader to obtain the loader
|
||||
// constraints based on the runtime classloaders' context.
|
||||
@ -420,7 +420,7 @@ void Method::set_vtable_index(int index) {
|
||||
}
|
||||
|
||||
void Method::set_itable_index(int index) {
|
||||
if (is_shared() && !MetaspaceShared::remapped_readwrite() && !method_holder()->is_shared_old_klass()) {
|
||||
if (is_shared() && !MetaspaceShared::remapped_readwrite() && method_holder()->verified_at_dump_time()) {
|
||||
// At runtime initialize_itable is rerun as part of link_class_impl()
|
||||
// for a shared class loaded by the non-boot loader to obtain the loader
|
||||
// constraints based on the runtime classloaders' context. The dumptime
|
||||
|
@ -45,6 +45,9 @@ const char* C2Compiler::retry_no_subsuming_loads() {
|
||||
const char* C2Compiler::retry_no_escape_analysis() {
|
||||
return "retry without escape analysis";
|
||||
}
|
||||
const char* C2Compiler::retry_no_locks_coarsening() {
|
||||
return "retry without locks coarsening";
|
||||
}
|
||||
const char* C2Compiler::retry_class_loading_during_parsing() {
|
||||
return "retry class loading during parsing";
|
||||
}
|
||||
@ -97,10 +100,11 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo
|
||||
bool subsume_loads = SubsumeLoads;
|
||||
bool do_escape_analysis = DoEscapeAnalysis;
|
||||
bool eliminate_boxing = EliminateAutoBox;
|
||||
bool do_locks_coarsening = EliminateLocks;
|
||||
|
||||
while (!env->failing()) {
|
||||
// Attempt to compile while subsuming loads into machine instructions.
|
||||
Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, install_code, directive);
|
||||
Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, do_locks_coarsening, install_code, directive);
|
||||
|
||||
// Check result and retry if appropriate.
|
||||
if (C.failure_reason() != NULL) {
|
||||
@ -120,6 +124,12 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo
|
||||
env->report_failure(C.failure_reason());
|
||||
continue; // retry
|
||||
}
|
||||
if (C.failure_reason_is(retry_no_locks_coarsening())) {
|
||||
assert(do_locks_coarsening, "must make progress");
|
||||
do_locks_coarsening = false;
|
||||
env->report_failure(C.failure_reason());
|
||||
continue; // retry
|
||||
}
|
||||
if (C.has_boxed_value()) {
|
||||
// Recompile without boxing elimination regardless failure reason.
|
||||
assert(eliminate_boxing, "must make progress");
|
||||
@ -141,6 +151,10 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo
|
||||
do_escape_analysis = false;
|
||||
continue; // retry
|
||||
}
|
||||
if (do_locks_coarsening) {
|
||||
do_locks_coarsening = false;
|
||||
continue; // retry
|
||||
}
|
||||
}
|
||||
// print inlining for last compilation only
|
||||
C.dump_print_inlining();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -49,6 +49,7 @@ public:
|
||||
// sentinel value used to trigger backtracking in compile_method().
|
||||
static const char* retry_no_subsuming_loads();
|
||||
static const char* retry_no_escape_analysis();
|
||||
static const char* retry_no_locks_coarsening();
|
||||
static const char* retry_class_loading_during_parsing();
|
||||
|
||||
// Print compilation timers and statistics
|
||||
|
@ -2054,6 +2054,12 @@ bool AbstractLockNode::find_unlocks_for_region(const RegionNode* region, LockNod
|
||||
|
||||
}
|
||||
|
||||
const char* AbstractLockNode::_kind_names[] = {"Regular", "NonEscObj", "Coarsened", "Nested"};
|
||||
|
||||
const char * AbstractLockNode::kind_as_string() const {
|
||||
return _kind_names[_kind];
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
//
|
||||
// Create a counter which counts the number of times this lock is acquired
|
||||
@ -2071,8 +2077,6 @@ void AbstractLockNode::set_eliminated_lock_counter() {
|
||||
}
|
||||
}
|
||||
|
||||
const char* AbstractLockNode::_kind_names[] = {"Regular", "NonEscObj", "Coarsened", "Nested"};
|
||||
|
||||
void AbstractLockNode::dump_spec(outputStream* st) const {
|
||||
st->print("%s ", _kind_names[_kind]);
|
||||
CallNode::dump_spec(st);
|
||||
@ -2124,6 +2128,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!phase->C->do_locks_coarsening()) {
|
||||
return result; // Compiling without locks coarsening
|
||||
}
|
||||
//
|
||||
// Try lock coarsening
|
||||
//
|
||||
@ -2161,6 +2168,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if (PrintEliminateLocks) {
|
||||
int locks = 0;
|
||||
int unlocks = 0;
|
||||
if (Verbose) {
|
||||
tty->print_cr("=== Locks coarsening ===");
|
||||
}
|
||||
for (int i = 0; i < lock_ops.length(); i++) {
|
||||
AbstractLockNode* lock = lock_ops.at(i);
|
||||
if (lock->Opcode() == Op_Lock)
|
||||
@ -2168,10 +2178,11 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
else
|
||||
unlocks++;
|
||||
if (Verbose) {
|
||||
lock->dump(1);
|
||||
tty->print(" %d: ", i);
|
||||
lock->dump();
|
||||
}
|
||||
}
|
||||
tty->print_cr("***Eliminated %d unlocks and %d locks", unlocks, locks);
|
||||
tty->print_cr("=== Coarsened %d unlocks and %d locks", unlocks, locks);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2186,6 +2197,8 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
#endif
|
||||
lock->set_coarsened();
|
||||
}
|
||||
// Record this coarsened group.
|
||||
phase->C->add_coarsened_locks(lock_ops);
|
||||
} else if (ctrl->is_Region() &&
|
||||
iter->_worklist.member(ctrl)) {
|
||||
// We weren't able to find any opportunities but the region this
|
||||
@ -2219,15 +2232,34 @@ bool LockNode::is_nested_lock_region(Compile * c) {
|
||||
// Ignore complex cases: merged locks or multiple locks.
|
||||
Node* obj = obj_node();
|
||||
LockNode* unique_lock = NULL;
|
||||
if (!box->is_simple_lock_region(&unique_lock, obj)) {
|
||||
Node* bad_lock = NULL;
|
||||
if (!box->is_simple_lock_region(&unique_lock, obj, &bad_lock)) {
|
||||
#ifdef ASSERT
|
||||
this->log_lock_optimization(c, "eliminate_lock_INLR_2a");
|
||||
this->log_lock_optimization(c, "eliminate_lock_INLR_2a", bad_lock);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (unique_lock != this) {
|
||||
#ifdef ASSERT
|
||||
this->log_lock_optimization(c, "eliminate_lock_INLR_2b");
|
||||
this->log_lock_optimization(c, "eliminate_lock_INLR_2b", (unique_lock != NULL ? unique_lock : bad_lock));
|
||||
if (PrintEliminateLocks && Verbose) {
|
||||
tty->print_cr("=============== unique_lock != this ============");
|
||||
tty->print(" this: ");
|
||||
this->dump();
|
||||
tty->print(" box: ");
|
||||
box->dump();
|
||||
tty->print(" obj: ");
|
||||
obj->dump();
|
||||
if (unique_lock != NULL) {
|
||||
tty->print(" unique_lock: ");
|
||||
unique_lock->dump();
|
||||
}
|
||||
if (bad_lock != NULL) {
|
||||
tty->print(" bad_lock: ");
|
||||
bad_lock->dump();
|
||||
}
|
||||
tty->print_cr("===============");
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@ -2294,23 +2326,21 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const char * AbstractLockNode::kind_as_string() const {
|
||||
return is_coarsened() ? "coarsened" :
|
||||
is_nested() ? "nested" :
|
||||
is_non_esc_obj() ? "non_escaping" :
|
||||
"?";
|
||||
}
|
||||
|
||||
void AbstractLockNode::log_lock_optimization(Compile *C, const char * tag) const {
|
||||
void AbstractLockNode::log_lock_optimization(Compile *C, const char * tag, Node* bad_lock) const {
|
||||
if (C == NULL) {
|
||||
return;
|
||||
}
|
||||
CompileLog* log = C->log();
|
||||
if (log != NULL) {
|
||||
log->begin_head("%s lock='%d' compile_id='%d' class_id='%s' kind='%s'",
|
||||
tag, is_Lock(), C->compile_id(),
|
||||
Node* box = box_node();
|
||||
Node* obj = obj_node();
|
||||
int box_id = box != NULL ? box->_idx : -1;
|
||||
int obj_id = obj != NULL ? obj->_idx : -1;
|
||||
|
||||
log->begin_head("%s compile_id='%d' lock_id='%d' class='%s' kind='%s' box_id='%d' obj_id='%d' bad_id='%d'",
|
||||
tag, C->compile_id(), this->_idx,
|
||||
is_Unlock() ? "unlock" : is_Lock() ? "lock" : "?",
|
||||
kind_as_string());
|
||||
kind_as_string(), box_id, obj_id, (bad_lock != NULL ? bad_lock->_idx : -1));
|
||||
log->stamp();
|
||||
log->end_head();
|
||||
JVMState* p = is_Unlock() ? (as_Unlock()->dbg_jvms()) : jvms();
|
||||
|
@ -1056,9 +1056,11 @@ private:
|
||||
Coarsened, // Lock was coarsened
|
||||
Nested // Nested lock
|
||||
} _kind;
|
||||
|
||||
static const char* _kind_names[Nested+1];
|
||||
|
||||
#ifndef PRODUCT
|
||||
NamedCounter* _counter;
|
||||
static const char* _kind_names[Nested+1];
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -1101,7 +1103,7 @@ public:
|
||||
bool is_nested() const { return (_kind == Nested); }
|
||||
|
||||
const char * kind_as_string() const;
|
||||
void log_lock_optimization(Compile* c, const char * tag) const;
|
||||
void log_lock_optimization(Compile* c, const char * tag, Node* bad_lock = NULL) const;
|
||||
|
||||
void set_non_esc_obj() { _kind = NonEscObj; set_eliminated_lock_counter(); }
|
||||
void set_coarsened() { _kind = Coarsened; set_eliminated_lock_counter(); }
|
||||
|
@ -432,6 +432,7 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
remove_useless_nodes(_skeleton_predicate_opaqs, useful);
|
||||
remove_useless_nodes(_expensive_nodes, useful); // remove useless expensive nodes
|
||||
remove_useless_nodes(_for_post_loop_igvn, useful); // remove useless node recorded for post loop opts IGVN pass
|
||||
remove_useless_coarsened_locks(useful); // remove useless coarsened locks nodes
|
||||
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
bs->eliminate_useless_gc_barriers(useful, this);
|
||||
@ -501,6 +502,12 @@ void Compile::print_compile_messages() {
|
||||
tty->print_cr("** Bailout: Recompile without boxing elimination **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if ((_do_locks_coarsening != EliminateLocks) && PrintOpto) {
|
||||
// Recompiling without locks coarsening
|
||||
tty->print_cr("*********************************************************");
|
||||
tty->print_cr("** Bailout: Recompile without locks coarsening **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if (env()->break_at_compile()) {
|
||||
// Open the debugger when compiling this method.
|
||||
tty->print("### Breaking when compiling: ");
|
||||
@ -528,13 +535,15 @@ debug_only( int Compile::_debug_idx = 100000; )
|
||||
|
||||
|
||||
Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, bool install_code, DirectiveSet* directive)
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing,
|
||||
bool do_locks_coarsening, bool install_code, DirectiveSet* directive)
|
||||
: Phase(Compiler),
|
||||
_compile_id(ci_env->compile_id()),
|
||||
_subsume_loads(subsume_loads),
|
||||
_do_escape_analysis(do_escape_analysis),
|
||||
_install_code(install_code),
|
||||
_eliminate_boxing(eliminate_boxing),
|
||||
_do_locks_coarsening(do_locks_coarsening),
|
||||
_method(target),
|
||||
_entry_bci(osr_bci),
|
||||
_stub_function(NULL),
|
||||
@ -566,6 +575,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
|
||||
_skeleton_predicate_opaqs (comp_arena(), 8, 0, NULL),
|
||||
_expensive_nodes (comp_arena(), 8, 0, NULL),
|
||||
_for_post_loop_igvn(comp_arena(), 8, 0, NULL),
|
||||
_coarsened_locks (comp_arena(), 8, 0, NULL),
|
||||
_congraph(NULL),
|
||||
NOT_PRODUCT(_printer(NULL) COMMA)
|
||||
_dead_node_list(comp_arena()),
|
||||
@ -832,6 +842,7 @@ Compile::Compile( ciEnv* ci_env,
|
||||
_do_escape_analysis(false),
|
||||
_install_code(true),
|
||||
_eliminate_boxing(false),
|
||||
_do_locks_coarsening(false),
|
||||
_method(NULL),
|
||||
_entry_bci(InvocationEntryBci),
|
||||
_stub_function(stub_function),
|
||||
@ -4447,6 +4458,101 @@ void Compile::add_expensive_node(Node * n) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track coarsened Lock and Unlock nodes.
|
||||
*/
|
||||
|
||||
class Lock_List : public Node_List {
|
||||
uint _origin_cnt;
|
||||
public:
|
||||
Lock_List(Arena *a, uint cnt) : Node_List(a), _origin_cnt(cnt) {}
|
||||
uint origin_cnt() const { return _origin_cnt; }
|
||||
};
|
||||
|
||||
void Compile::add_coarsened_locks(GrowableArray<AbstractLockNode*>& locks) {
|
||||
int length = locks.length();
|
||||
if (length > 0) {
|
||||
// Have to keep this list until locks elimination during Macro nodes elimination.
|
||||
Lock_List* locks_list = new (comp_arena()) Lock_List(comp_arena(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
AbstractLockNode* lock = locks.at(i);
|
||||
assert(lock->is_coarsened(), "expecting only coarsened AbstractLock nodes, but got '%s'[%d] node", lock->Name(), lock->_idx);
|
||||
locks_list->push(lock);
|
||||
}
|
||||
_coarsened_locks.append(locks_list);
|
||||
}
|
||||
}
|
||||
|
||||
void Compile::remove_useless_coarsened_locks(Unique_Node_List& useful) {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Node_List* locks_list = _coarsened_locks.at(i);
|
||||
for (uint j = 0; j < locks_list->size(); j++) {
|
||||
Node* lock = locks_list->at(j);
|
||||
assert(lock->is_AbstractLock(), "sanity");
|
||||
if (!useful.member(lock)) {
|
||||
locks_list->yank(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compile::remove_coarsened_lock(Node* n) {
|
||||
if (n->is_AbstractLock()) {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Node_List* locks_list = _coarsened_locks.at(i);
|
||||
locks_list->yank(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Compile::coarsened_locks_consistent() {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
bool unbalanced = false;
|
||||
bool modified = false; // track locks kind modifications
|
||||
Lock_List* locks_list = (Lock_List*)_coarsened_locks.at(i);
|
||||
uint size = locks_list->size();
|
||||
if (size != locks_list->origin_cnt()) {
|
||||
unbalanced = true; // Some locks were removed from list
|
||||
} else {
|
||||
for (uint j = 0; j < size; j++) {
|
||||
Node* lock = locks_list->at(j);
|
||||
// All nodes in group should have the same state (modified or not)
|
||||
if (!lock->as_AbstractLock()->is_coarsened()) {
|
||||
if (j == 0) {
|
||||
// first on list was modified, the rest should be too for consistency
|
||||
modified = true;
|
||||
} else if (!modified) {
|
||||
// this lock was modified but previous locks on the list were not
|
||||
unbalanced = true;
|
||||
break;
|
||||
}
|
||||
} else if (modified) {
|
||||
// previous locks on list were modified but not this lock
|
||||
unbalanced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unbalanced) {
|
||||
// unbalanced monitor enter/exit - only some [un]lock nodes were removed or modified
|
||||
#ifdef ASSERT
|
||||
if (PrintEliminateLocks) {
|
||||
tty->print_cr("=== unbalanced coarsened locks ===");
|
||||
for (uint l = 0; l < size; l++) {
|
||||
locks_list->at(l)->dump();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
record_failure(C2Compiler::retry_no_locks_coarsening());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the speculative part of types and clean up the graph
|
||||
*/
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
class AbstractLockNode;
|
||||
class AddPNode;
|
||||
class Block;
|
||||
class Bundle;
|
||||
@ -63,6 +64,7 @@ class MachOper;
|
||||
class MachSafePointNode;
|
||||
class Node;
|
||||
class Node_Array;
|
||||
class Node_List;
|
||||
class Node_Notes;
|
||||
class NodeCloneInfo;
|
||||
class OptoReg;
|
||||
@ -248,6 +250,7 @@ class Compile : public Phase {
|
||||
const bool _do_escape_analysis; // Do escape analysis.
|
||||
const bool _install_code; // Install the code that was compiled
|
||||
const bool _eliminate_boxing; // Do boxing elimination.
|
||||
const bool _do_locks_coarsening; // Do locks coarsening
|
||||
ciMethod* _method; // The method being compiled.
|
||||
int _entry_bci; // entry bci for osr methods.
|
||||
const TypeFunc* _tf; // My kind of signature
|
||||
@ -317,6 +320,7 @@ class Compile : public Phase {
|
||||
GrowableArray<Node*> _skeleton_predicate_opaqs; // List of Opaque4 nodes for the loop skeleton predicates.
|
||||
GrowableArray<Node*> _expensive_nodes; // List of nodes that are expensive to compute and that we'd better not let the GVN freely common
|
||||
GrowableArray<Node*> _for_post_loop_igvn; // List of nodes for IGVN after loop opts are over
|
||||
GrowableArray<Node_List*> _coarsened_locks; // List of coarsened Lock and Unlock nodes
|
||||
ConnectionGraph* _congraph;
|
||||
#ifndef PRODUCT
|
||||
IdealGraphPrinter* _printer;
|
||||
@ -508,6 +512,8 @@ class Compile : public Phase {
|
||||
/** Do aggressive boxing elimination. */
|
||||
bool aggressive_unboxing() const { return _eliminate_boxing && AggressiveUnboxing; }
|
||||
bool should_install_code() const { return _install_code; }
|
||||
/** Do locks coarsening. */
|
||||
bool do_locks_coarsening() const { return _do_locks_coarsening; }
|
||||
|
||||
// Other fixed compilation parameters.
|
||||
ciMethod* method() const { return _method; }
|
||||
@ -656,6 +662,7 @@ class Compile : public Phase {
|
||||
int predicate_count() const { return _predicate_opaqs.length(); }
|
||||
int skeleton_predicate_count() const { return _skeleton_predicate_opaqs.length(); }
|
||||
int expensive_count() const { return _expensive_nodes.length(); }
|
||||
int coarsened_count() const { return _coarsened_locks.length(); }
|
||||
|
||||
Node* macro_node(int idx) const { return _macro_nodes.at(idx); }
|
||||
Node* predicate_opaque1_node(int idx) const { return _predicate_opaqs.at(idx); }
|
||||
@ -677,6 +684,10 @@ class Compile : public Phase {
|
||||
if (predicate_count() > 0) {
|
||||
_predicate_opaqs.remove_if_existing(n);
|
||||
}
|
||||
// Remove from coarsened locks list if present
|
||||
if (coarsened_count() > 0) {
|
||||
remove_coarsened_lock(n);
|
||||
}
|
||||
}
|
||||
void add_expensive_node(Node* n);
|
||||
void remove_expensive_node(Node* n) {
|
||||
@ -696,6 +707,10 @@ class Compile : public Phase {
|
||||
_skeleton_predicate_opaqs.remove_if_existing(n);
|
||||
}
|
||||
}
|
||||
void add_coarsened_locks(GrowableArray<AbstractLockNode*>& locks);
|
||||
void remove_coarsened_lock(Node* n);
|
||||
bool coarsened_locks_consistent();
|
||||
|
||||
bool post_loop_opts_phase() { return _post_loop_opts_phase; }
|
||||
void set_post_loop_opts_phase() { _post_loop_opts_phase = true; }
|
||||
void reset_post_loop_opts_phase() { _post_loop_opts_phase = false; }
|
||||
@ -952,6 +967,8 @@ class Compile : public Phase {
|
||||
void remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines, Unique_Node_List &useful);
|
||||
void remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines, Node* dead);
|
||||
|
||||
void remove_useless_coarsened_locks(Unique_Node_List& useful);
|
||||
|
||||
void process_print_inlining();
|
||||
void dump_print_inlining();
|
||||
|
||||
@ -1018,7 +1035,8 @@ class Compile : public Phase {
|
||||
// continuation.
|
||||
Compile(ciEnv* ci_env, ciMethod* target,
|
||||
int entry_bci, bool subsume_loads, bool do_escape_analysis,
|
||||
bool eliminate_boxing, bool install_code, DirectiveSet* directive);
|
||||
bool eliminate_boxing, bool do_locks_coarsening,
|
||||
bool install_code, DirectiveSet* directive);
|
||||
|
||||
// Second major entry point. From the TypeFunc signature, generate code
|
||||
// to pass arguments from the Java calling convention to the C calling
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -85,7 +85,7 @@ OptoReg::Name BoxLockNode::reg(Node* box) {
|
||||
}
|
||||
|
||||
// Is BoxLock node used for one simple lock region (same box and obj)?
|
||||
bool BoxLockNode::is_simple_lock_region(LockNode** unique_lock, Node* obj) {
|
||||
bool BoxLockNode::is_simple_lock_region(LockNode** unique_lock, Node* obj, Node** bad_lock) {
|
||||
LockNode* lock = NULL;
|
||||
bool has_one_lock = false;
|
||||
for (uint i = 0; i < this->outcnt(); i++) {
|
||||
@ -102,9 +102,15 @@ bool BoxLockNode::is_simple_lock_region(LockNode** unique_lock, Node* obj) {
|
||||
has_one_lock = true;
|
||||
} else if (lock != alock->as_Lock()) {
|
||||
has_one_lock = false;
|
||||
if (bad_lock != NULL) {
|
||||
*bad_lock = alock;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bad_lock != NULL) {
|
||||
*bad_lock = alock;
|
||||
}
|
||||
return false; // Different objects
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -63,7 +63,7 @@ public:
|
||||
void set_eliminated() { _is_eliminated = true; }
|
||||
|
||||
// Is BoxLock node used for one simple lock region?
|
||||
bool is_simple_lock_region(LockNode** unique_lock, Node* obj);
|
||||
bool is_simple_lock_region(LockNode** unique_lock, Node* obj, Node** bad_lock);
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void format( PhaseRegAlloc *, outputStream *st ) const;
|
||||
|
@ -1909,15 +1909,15 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
|
||||
// Mark all associated (same box and obj) lock and unlock nodes for
|
||||
// elimination if some of them marked already.
|
||||
void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) {
|
||||
if (oldbox->as_BoxLock()->is_eliminated())
|
||||
if (oldbox->as_BoxLock()->is_eliminated()) {
|
||||
return; // This BoxLock node was processed already.
|
||||
|
||||
}
|
||||
// New implementation (EliminateNestedLocks) has separate BoxLock
|
||||
// node for each locked region so mark all associated locks/unlocks as
|
||||
// eliminated even if different objects are referenced in one locked region
|
||||
// (for example, OSR compilation of nested loop inside locked scope).
|
||||
if (EliminateNestedLocks ||
|
||||
oldbox->as_BoxLock()->is_simple_lock_region(NULL, obj)) {
|
||||
oldbox->as_BoxLock()->is_simple_lock_region(NULL, obj, NULL)) {
|
||||
// Box is used only in one lock region. Mark this box as eliminated.
|
||||
_igvn.hash_delete(oldbox);
|
||||
oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value
|
||||
@ -2089,11 +2089,7 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintEliminateLocks) {
|
||||
if (alock->is_Lock()) {
|
||||
tty->print_cr("++++ Eliminated: %d Lock", alock->_idx);
|
||||
} else {
|
||||
tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx);
|
||||
}
|
||||
tty->print_cr("++++ Eliminated: %d %s '%s'", alock->_idx, (alock->is_Lock() ? "Lock" : "Unlock"), alock->kind_as_string());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2502,16 +2498,21 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
|
||||
if (C->macro_count() == 0)
|
||||
return;
|
||||
|
||||
// First, attempt to eliminate locks
|
||||
// Before elimination may re-mark (change to Nested or NonEscObj)
|
||||
// all associated (same box and obj) lock and unlock nodes.
|
||||
int cnt = C->macro_count();
|
||||
for (int i=0; i < cnt; i++) {
|
||||
Node *n = C->macro_node(i);
|
||||
if (n->is_AbstractLock()) { // Lock and Unlock nodes
|
||||
// Before elimination mark all associated (same box and obj)
|
||||
// lock and unlock nodes.
|
||||
mark_eliminated_locking_nodes(n->as_AbstractLock());
|
||||
}
|
||||
}
|
||||
// Re-marking may break consistency of Coarsened locks.
|
||||
if (!C->coarsened_locks_consistent()) {
|
||||
return; // recompile without Coarsened locks if broken
|
||||
}
|
||||
|
||||
// First, attempt to eliminate locks
|
||||
bool progress = true;
|
||||
while (progress) {
|
||||
progress = false;
|
||||
@ -2574,6 +2575,7 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
|
||||
bool PhaseMacroExpand::expand_macro_nodes() {
|
||||
// Last attempt to eliminate macro nodes.
|
||||
eliminate_macro_nodes();
|
||||
if (C->failing()) return true;
|
||||
|
||||
// Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations.
|
||||
bool progress = true;
|
||||
|
@ -41,7 +41,7 @@ import static com.sun.crypto.provider.KWUtil.*;
|
||||
class AESKeyWrap extends FeedbackCipher {
|
||||
|
||||
// default integrity check value (icv) if iv is not supplied
|
||||
private static final byte[] ICV1 = { // SEMI_BLKSIZE long
|
||||
static final byte[] ICV1 = { // SEMI_BLKSIZE long
|
||||
(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6,
|
||||
(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ import static com.sun.crypto.provider.KWUtil.*;
|
||||
class AESKeyWrapPadded extends FeedbackCipher {
|
||||
|
||||
// default integrity check value (icv) if iv is not supplied
|
||||
private static final byte[] ICV2 = { // SEMI_BLKSIZE/2 long
|
||||
static final byte[] ICV2 = { // SEMI_BLKSIZE/2 long
|
||||
(byte) 0xA6, (byte) 0x59, (byte) 0x59, (byte) 0xA6,
|
||||
};
|
||||
|
||||
|
@ -161,6 +161,7 @@ abstract class KeyWrapCipher extends CipherSpi {
|
||||
}
|
||||
|
||||
// internal cipher object which does the real work.
|
||||
// AESKeyWrap for KW, AESKeyWrapPadded for KWP
|
||||
private final FeedbackCipher cipher;
|
||||
|
||||
// internal padding object; null if NoPadding
|
||||
@ -279,13 +280,15 @@ abstract class KeyWrapCipher extends CipherSpi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialization vector (IV).
|
||||
* Returns the initialization vector (IV) in a new buffer.
|
||||
*
|
||||
* @return the user-specified iv or null if default iv is used.
|
||||
* @return the user-specified iv, or null if the underlying algorithm does
|
||||
* not use an IV, or if the IV has not yet been set.
|
||||
*/
|
||||
@Override
|
||||
protected byte[] engineGetIV() {
|
||||
return cipher.getIV().clone();
|
||||
byte[] iv = cipher.getIV();
|
||||
return (iv == null? null : iv.clone());
|
||||
}
|
||||
|
||||
// actual impl for various engineInit(...) methods
|
||||
@ -623,13 +626,18 @@ abstract class KeyWrapCipher extends CipherSpi {
|
||||
/**
|
||||
* Returns the parameters used with this cipher.
|
||||
*
|
||||
* @return AlgorithmParameters object containing IV.
|
||||
* @return AlgorithmParameters object containing IV, or null if this cipher
|
||||
* does not use any parameters.
|
||||
*/
|
||||
@Override
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
AlgorithmParameters params = null;
|
||||
|
||||
byte[] iv = cipher.getIV();
|
||||
if (iv == null) {
|
||||
iv = (cipher instanceof AESKeyWrap?
|
||||
AESKeyWrap.ICV1 : AESKeyWrapPadded.ICV2);
|
||||
}
|
||||
try {
|
||||
params = AlgorithmParameters.getInstance("AES");
|
||||
params.init(new IvParameterSpec(iv));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2021, 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
|
||||
@ -54,7 +54,8 @@ public interface AutoCloseable {
|
||||
* This method is invoked automatically on objects managed by the
|
||||
* {@code try}-with-resources statement.
|
||||
*
|
||||
* <p>While this interface method is declared to throw {@code
|
||||
* @apiNote
|
||||
* While this interface method is declared to throw {@code
|
||||
* Exception}, implementers are <em>strongly</em> encouraged to
|
||||
* declare concrete implementations of the {@code close} method to
|
||||
* throw more specific exceptions, or to throw no exception at all
|
||||
|
@ -26,6 +26,7 @@
|
||||
package sun.security.jca;
|
||||
|
||||
import java.security.Provider;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
/**
|
||||
* Collection of methods to get and set provider list. Also includes
|
||||
@ -150,7 +151,17 @@ public class Providers {
|
||||
} else {
|
||||
changeThreadProviderList(newList);
|
||||
}
|
||||
clearCachedValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cached provider-list-specific values. These values need to
|
||||
* be re-generated whenever provider list is changed. The logic for
|
||||
* generating them is in the respective classes.
|
||||
*/
|
||||
private static void clearCachedValues() {
|
||||
JCAUtil.clearDefSecureRandom();
|
||||
AlgorithmId.clearAliasOidsTable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -536,6 +536,11 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
// oid string cache index'ed by algorithm name and oid strings
|
||||
private static volatile Map<String,String> aliasOidsTable;
|
||||
|
||||
// called by sun.security.jca.Providers whenever provider list is changed
|
||||
public static void clearAliasOidsTable() {
|
||||
aliasOidsTable = null;
|
||||
}
|
||||
|
||||
// returns the aliasOidsTable, lazily initializing it on first access.
|
||||
private static Map<String,String> aliasOidsTable() {
|
||||
// Double checked locking; safe because aliasOidsTable is volatile
|
||||
|
@ -1310,7 +1310,7 @@ By default this option is disabled.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \f[CB]\-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] (or)\f[CB]\-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R]
|
||||
.B \f[CB]\-XX:FlightRecorderOptions=\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] (or)\f[CB]\-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R]
|
||||
Sets the parameters that control the behavior of JFR.
|
||||
.RS
|
||||
.PP
|
||||
@ -1636,7 +1636,7 @@ By default, this option is disabled.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \f[CB]\-XX:StartFlightRecording:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R]
|
||||
.B \f[CB]\-XX:StartFlightRecording=\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R]
|
||||
Starts a JFR recording for the Java application.
|
||||
This option is equivalent to the \f[CB]JFR.start\f[R] diagnostic command
|
||||
that starts a recording during runtime.
|
||||
@ -1757,22 +1757,6 @@ is needed.
|
||||
.PP
|
||||
You can specify values for multiple parameters by separating them with a
|
||||
comma.
|
||||
.PP
|
||||
Event settings and .jfc options can also be specified using the following
|
||||
syntax:
|
||||
.TP
|
||||
.B \f[CB]option=\f[R]\f[I]value\f[R]
|
||||
Specifies the option value to modify. To list available options, use the
|
||||
JAVA_HOME/bin/jfr tool.
|
||||
.TP
|
||||
.B \f[CB]event-setting=\f[R]\f[I]value\f[R]
|
||||
Specifies the event setting value to modify. Use the form:
|
||||
<event-name>#<setting-name>=<value>
|
||||
To add a new event setting, prefix the event name with '+'.
|
||||
.PP
|
||||
In case of a conflict between a parameter and a .jfc option, the parameter
|
||||
will take precedence. The whitespace delimiter can be omitted for timespan values, i.e. 20ms. For
|
||||
more information about the settings syntax, see Javadoc of the jdk.jfr package.
|
||||
.RE
|
||||
.TP
|
||||
.B \f[CB]\-XX:ThreadStackSize=\f[R]\f[I]size\f[R]
|
||||
@ -3888,68 +3872,6 @@ future JDK release.
|
||||
They\[aq]re still accepted and acted upon, but a warning is issued when
|
||||
they\[aq]re used.
|
||||
.TP
|
||||
.B \f[CB]\-\-illegal\-access=\f[R]\f[I]parameter\f[R]
|
||||
When present at run time, \f[CB]\-\-illegal\-access=\f[R] takes a keyword
|
||||
\f[I]parameter\f[R] to specify a mode of operation:
|
||||
.RS
|
||||
.RS
|
||||
.PP
|
||||
\f[B]Note:\f[R] This option will be removed in a future release.
|
||||
.RE
|
||||
.IP \[bu] 2
|
||||
\f[CB]permit\f[R]: This mode opens each package in each module in the
|
||||
run\-time image to code in all unnamed modules ( such as code on the
|
||||
class path), if that package existed in JDK 8.
|
||||
This enables both static access, (for example, by compiled bytecode, and
|
||||
deep reflective access) through the platform\[aq]s various reflection
|
||||
APIs.
|
||||
The first reflective\-access operation to any such package causes a
|
||||
warning to be issued.
|
||||
However, no warnings are issued after the first occurrence.
|
||||
This single warning describes how to enable further warnings.
|
||||
.IP \[bu] 2
|
||||
\f[CB]warn\f[R]: This mode is identical to \f[CB]permit\f[R] except that a
|
||||
warning message is issued for each illegal reflective\-access operation.
|
||||
.IP \[bu] 2
|
||||
\f[CB]debug\f[R]: This mode is identical to \f[CB]warn\f[R] except that both
|
||||
a warning message and a stack trace are issued for each illegal
|
||||
reflective\-access operation.
|
||||
.IP \[bu] 2
|
||||
\f[CB]deny\f[R]: This mode disables all illegal\-access operations except
|
||||
for those enabled by other command\-line options, such as
|
||||
\f[CB]\-\-add\-opens\f[R].
|
||||
This mode is the default.
|
||||
.PP
|
||||
If your application does not work with the default mode of
|
||||
\f[CB]\-\-illegal\-access=deny\f[R] then you can learn more about what is
|
||||
going on with the \f[CB]warn\f[R] and \f[CB]debug\f[R] modes.
|
||||
For each library or framework on the class path that requires illegal
|
||||
access, you have two options:
|
||||
.IP \[bu] 2
|
||||
If the component\[aq]s maintainers have already released a fixed version
|
||||
that no longer uses JDK\-internal APIs then you can consider upgrading
|
||||
to that version.
|
||||
.IP \[bu] 2
|
||||
If the component still needs to be fixed, then you can contact its
|
||||
maintainers and ask them to replace their use of JDK\-internal APIs with
|
||||
the proper exported APIs.
|
||||
.PP
|
||||
If you must continue to use a component that requires illegal access,
|
||||
then you can eliminate the warning messages by using one or more
|
||||
\f[CB]\-\-add\-opens\f[R] options to open only those internal packages to
|
||||
which access is required.
|
||||
.PP
|
||||
To verify that your application is ready for a future version of the
|
||||
JDK, run it with \f[CB]\-\-illegal\-access=deny\f[R] along with any
|
||||
necessary \f[CB]\-\-add\-opens\f[R] options.
|
||||
Any remaining illegal\-access errors will most likely be due to static
|
||||
references from compiled code to JDK\-internal APIs.
|
||||
You can identify those by running the \f[B]jdeps\f[R] tool with the
|
||||
\f[CB]\-\-jdk\-internals\f[R] option.
|
||||
For performance reasons, the current JDK does not issue warnings for
|
||||
illegal static\-access operations.
|
||||
.RE
|
||||
.TP
|
||||
.B \f[CB]\-Xfuture\f[R]
|
||||
Enables strict class\-file format checks that enforce close conformance
|
||||
to the class\-file format specification.
|
||||
@ -4032,8 +3954,16 @@ By default, this option is disabled.
|
||||
.PP
|
||||
These \f[CB]java\f[R] options are still accepted but ignored, and a
|
||||
warning is issued when they\[aq]re used.
|
||||
.PP
|
||||
None in JDK 17.
|
||||
.TP
|
||||
.B \f[CB]\-\-illegal\-access=\f[R]\f[I]parameter\f[R]
|
||||
Controlled \f[I]relaxed strong encapsulation\f[R], as defined in \f[B]JEP
|
||||
261\f[R]
|
||||
[https://openjdk.java.net/jeps/261#Relaxed\-strong\-encapsulation].
|
||||
This option was deprecated in JDK 16 by \f[B]JEP 396\f[R]
|
||||
[https://openjdk.java.net/jeps/396] and made obsolete in JDK 17 by
|
||||
\f[B]JEP 403\f[R] [https://openjdk.java.net/jeps/403].
|
||||
.RS
|
||||
.RE
|
||||
.SH REMOVED JAVA OPTIONS
|
||||
.PP
|
||||
These \f[CB]java\f[R] options have been removed in JDK 17 and using them
|
||||
@ -4374,6 +4304,8 @@ the Java Virtual Machine (JVM) unified logging framework.
|
||||
.RS
|
||||
.PP
|
||||
\f[CB]\-Xlog\f[R][\f[CB]:\f[R][\f[I]what\f[R]][\f[CB]:\f[R][\f[I]output\f[R]][\f[CB]:\f[R][\f[I]decorators\f[R]][\f[CB]:\f[R]\f[I]output\-options\f[R][\f[CB],\f[R]...]]]]]
|
||||
.PP
|
||||
\f[CB]\-Xlog:\f[R]\f[I]directive\f[R]
|
||||
.RE
|
||||
.TP
|
||||
.B \f[I]what\f[R]
|
||||
@ -4404,6 +4336,11 @@ See \f[B]Decorations\f[R].
|
||||
Sets the \f[CB]\-Xlog\f[R] logging output options.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \f[I]directive\f[R]
|
||||
A global option or subcommand: help, disable, async
|
||||
.RS
|
||||
.RE
|
||||
.SS Description
|
||||
.PP
|
||||
The Java Virtual Machine (JVM) unified logging framework provides a
|
||||
@ -4554,6 +4491,29 @@ Specifying \f[CB]filecount=0\f[R] means that the log file shouldn\[aq]t be
|
||||
rotated.
|
||||
There\[aq]s a possibility of the pre\-existing log file getting
|
||||
overwritten.
|
||||
.SS \-Xlog Output Mode
|
||||
.PP
|
||||
By default logging messages are output synchronously \- each log message
|
||||
is written to the designated output when the logging call is made.
|
||||
But you can instead use asynchronous logging mode by specifying:
|
||||
.TP
|
||||
.B \f[CB]\-Xlog:async\f[R]
|
||||
Write all logging asynchronously.
|
||||
.RS
|
||||
.RE
|
||||
.PP
|
||||
In asynchronous logging mode, log sites enqueue all logging messages to
|
||||
an intermediate buffer and a standalone thread is responsible for
|
||||
flushing them to the corresponding outputs.
|
||||
The intermediate buffer is bounded and on buffer exhaustion the
|
||||
enqueuing message is discarded.
|
||||
Log entry write operations are guaranteed non\-blocking.
|
||||
.PP
|
||||
The option \f[CB]\-XX:AsyncLogBufferSize=N\f[R] specifies the memory
|
||||
budget in bytes for the intermediate buffer.
|
||||
The default value should be big enough to cater for most cases.
|
||||
Users can provide a custom value to trade memory overhead for log
|
||||
accuracy if they need to.
|
||||
.SS Decorations
|
||||
.PP
|
||||
Logging messages are decorated with information about the message.
|
||||
|
@ -468,7 +468,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
if (tsym == null || tsym.name == null) {
|
||||
sb.append("<none>");
|
||||
} else {
|
||||
sb.append(tsym.name);
|
||||
sb.append(tsym.name.toString());
|
||||
}
|
||||
if (moreInfo && hasTag(TYPEVAR)) {
|
||||
sb.append(hashCode());
|
||||
|
@ -2392,6 +2392,10 @@ public class Flow {
|
||||
JCCase c = l.head;
|
||||
for (JCCaseLabel pat : c.labels) {
|
||||
scan(pat);
|
||||
if (inits.isReset()) {
|
||||
inits.assign(initsWhenTrue);
|
||||
uninits.assign(uninitsWhenTrue);
|
||||
}
|
||||
}
|
||||
if (l.head.stats.isEmpty() &&
|
||||
l.tail.nonEmpty() &&
|
||||
|
@ -431,6 +431,7 @@ public class TransPatterns extends TreeTranslator {
|
||||
|
||||
int i = 0;
|
||||
boolean previousCompletesNormally = false;
|
||||
boolean hasDefault = false;
|
||||
|
||||
for (var c : cases) {
|
||||
List<JCCaseLabel> clearedPatterns = c.labels;
|
||||
@ -477,7 +478,9 @@ public class TransPatterns extends TreeTranslator {
|
||||
for (var p : c.labels) {
|
||||
if (p.hasTag(Tag.DEFAULTCASELABEL)) {
|
||||
translatedLabels.add(p);
|
||||
} else if (hasTotalPattern && c == lastCase && p.isPattern()) {
|
||||
hasDefault = true;
|
||||
} else if (hasTotalPattern && !hasDefault &&
|
||||
c == lastCase && p.isPattern()) {
|
||||
//If the switch has total pattern, the last case will contain it.
|
||||
//Convert the total pattern to default:
|
||||
translatedLabels.add(make.DefaultCaseLabel());
|
||||
|
@ -2668,6 +2668,9 @@ public class JavacParser implements Parser {
|
||||
case PLUSPLUS: case SUBSUB:
|
||||
isYieldStatement = S.token(2).kind != SEMI;
|
||||
break;
|
||||
case BANG: case TILDE:
|
||||
isYieldStatement = S.token(1).kind != SEMI;
|
||||
break;
|
||||
case LPAREN:
|
||||
int lookahead = 2;
|
||||
int balance = 1;
|
||||
|
@ -1432,7 +1432,7 @@ public class HtmlDocletWriter {
|
||||
|
||||
@Override
|
||||
public Boolean visitAttribute(AttributeTree node, Content c) {
|
||||
StringBuilder sb = new StringBuilder(SPACER).append(node.getName());
|
||||
StringBuilder sb = new StringBuilder(SPACER).append(node.getName().toString());
|
||||
if (node.getValueKind() == ValueKind.EMPTY) {
|
||||
result.add(sb);
|
||||
return false;
|
||||
@ -2050,18 +2050,18 @@ public class HtmlDocletWriter {
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Element e: chain) {
|
||||
CharSequence name;
|
||||
String name;
|
||||
switch (e.getKind()) {
|
||||
case MODULE:
|
||||
case PACKAGE:
|
||||
name = ((QualifiedNameable) e).getQualifiedName();
|
||||
name = ((QualifiedNameable) e).getQualifiedName().toString();
|
||||
if (name.length() == 0) {
|
||||
name = "<unnamed>";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
name = e.getSimpleName();
|
||||
name = e.getSimpleName().toString();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ public class HtmlIds {
|
||||
* @return the 1.4.x style anchor for the executable element
|
||||
*/
|
||||
protected HtmlId forErasure(ExecutableElement executableElement) {
|
||||
final StringBuilder buf = new StringBuilder(executableElement.getSimpleName());
|
||||
final StringBuilder buf = new StringBuilder(executableElement.getSimpleName().toString());
|
||||
buf.append("(");
|
||||
List<? extends VariableElement> parameters = executableElement.getParameters();
|
||||
boolean foundTypeVariable = false;
|
||||
@ -237,7 +237,7 @@ public class HtmlIds {
|
||||
|
||||
@Override
|
||||
public Boolean visitTypeVariable(TypeVariable t, Void p) {
|
||||
buf.append(utils.asTypeElement(t).getQualifiedName());
|
||||
buf.append(utils.asTypeElement(t).getQualifiedName().toString());
|
||||
foundTypeVariable = true;
|
||||
return foundTypeVariable;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, 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
|
||||
@ -70,17 +70,19 @@ public class Entity extends Content {
|
||||
* @return the string with all of the HTML characters escaped
|
||||
*/
|
||||
static String escapeHtmlChars(CharSequence s) {
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
// Convert to string as CharSequence implementations can be slow - see JDK-8263321
|
||||
String str = s.toString();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char ch = str.charAt(i);
|
||||
switch (ch) {
|
||||
// only start building a new string if we need to
|
||||
case '<': case '>': case '&':
|
||||
StringBuilder sb = new StringBuilder(s.subSequence(0, i));
|
||||
escapeHtmlChars(s, i, sb);
|
||||
StringBuilder sb = new StringBuilder(str.substring(0, i));
|
||||
escapeHtmlChars(str, i, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,10 +93,10 @@ public class Entity extends Content {
|
||||
* @param sb the string builder
|
||||
*/
|
||||
static void escapeHtmlChars(CharSequence s, StringBuilder sb) {
|
||||
escapeHtmlChars(s, 0, sb);
|
||||
escapeHtmlChars(s.toString(), 0, sb);
|
||||
}
|
||||
|
||||
private static void escapeHtmlChars(CharSequence s, int start, StringBuilder sb) {
|
||||
private static void escapeHtmlChars(String s, int start, StringBuilder sb) {
|
||||
for (int i = start ; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
switch (ch) {
|
||||
|
@ -55,7 +55,7 @@ public class Text extends Content {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to construct FixedStringContent object.
|
||||
* Constructs an immutable text object.
|
||||
*
|
||||
* @param content content for the object
|
||||
*/
|
||||
|
@ -225,7 +225,7 @@ public class CommentHelper {
|
||||
new SimpleDocTreeVisitor<Void, Void>() {
|
||||
@Override
|
||||
public Void visitAttribute(AttributeTree node, Void p) {
|
||||
sb.append(SPACER).append(node.getName());
|
||||
sb.append(SPACER).append(node.getName().toString());
|
||||
if (node.getValueKind() == ValueKind.EMPTY) {
|
||||
return null;
|
||||
}
|
||||
@ -252,7 +252,7 @@ public class CommentHelper {
|
||||
@Override
|
||||
public Void visitEndElement(EndElementTree node, Void p) {
|
||||
sb.append("</")
|
||||
.append(node.getName())
|
||||
.append(node.getName().toString())
|
||||
.append(">");
|
||||
return null;
|
||||
}
|
||||
@ -307,7 +307,7 @@ public class CommentHelper {
|
||||
@Override
|
||||
public Void visitStartElement(StartElementTree node, Void p) {
|
||||
sb.append("<");
|
||||
sb.append(node.getName());
|
||||
sb.append(node.getName().toString());
|
||||
node.getAttributes().forEach(dt -> dt.accept(this, null));
|
||||
sb.append(node.isSelfClosing() ? "/>" : ">");
|
||||
return null;
|
||||
|
@ -2158,7 +2158,7 @@ public class Utils {
|
||||
|
||||
@Override
|
||||
public String visitType(TypeElement e, Void p) {
|
||||
StringBuilder sb = new StringBuilder(e.getSimpleName());
|
||||
StringBuilder sb = new StringBuilder(e.getSimpleName().toString());
|
||||
Element enclosed = e.getEnclosingElement();
|
||||
while (enclosed != null
|
||||
&& (enclosed.getKind().isClass() || enclosed.getKind().isInterface())) {
|
||||
|
@ -27,9 +27,16 @@
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
vmTestbase/jit/escape/AdaptiveBlocking/AdaptiveBlocking001/AdaptiveBlocking001.java 8260303 windows-x64
|
||||
|
||||
resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 8220624 generic-all
|
||||
serviceability/sa/CDSJMapClstats.java 8220624 generic-all
|
||||
serviceability/sa/ClhsdbJhisto.java 8220624 generic-all
|
||||
serviceability/sa/TestHeapDumpForLargeArray.java 8220624 generic-all
|
||||
vmTestbase/jit/escape/AdaptiveBlocking/AdaptiveBlocking001/AdaptiveBlocking001.java 8260303 windows-x64
|
||||
serviceability/sa/TestJmapCore.java 8268283 linux-aarch64
|
||||
|
||||
serviceability/sa/ClhsdbCDSCore.java 8268722 macosx-x64
|
||||
serviceability/sa/ClhsdbFindPC.java#id1 8268722 macosx-x64
|
||||
serviceability/sa/ClhsdbFindPC.java#id3 8268722 macosx-x64
|
||||
serviceability/sa/ClhsdbPmap.java#id1 8268722 macosx-x64
|
||||
serviceability/sa/ClhsdbPstack.java#id1 8268722 macosx-x64
|
||||
serviceability/sa/TestJmapCore.java 8268722,8268283 macosx-x64,linux-aarch64
|
||||
serviceability/sa/TestJmapCoreMetaspace.java 8268722 macosx-x64
|
||||
|
@ -70,6 +70,8 @@ compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64
|
||||
|
||||
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-x64
|
||||
|
||||
compiler/intrinsics/VectorizedMismatchTest.java 8268482 windows-x64
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_gc
|
||||
|
@ -129,6 +129,7 @@ tier1_compiler_2 = \
|
||||
tier1_compiler_3 = \
|
||||
compiler/intrinsics/ \
|
||||
compiler/jsr292/ \
|
||||
compiler/locks/ \
|
||||
compiler/loopopts/ \
|
||||
compiler/macronodes/ \
|
||||
compiler/memoryinitialization/ \
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8268366
|
||||
* @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1
|
||||
* compiler.c1.TestLinearScanHasFPURegisters
|
||||
*/
|
||||
|
||||
package compiler.c1;
|
||||
|
||||
public class TestLinearScanHasFPURegisters {
|
||||
void test(String[] args) {
|
||||
String arr[] = new String[4];
|
||||
float f = -1;
|
||||
try {
|
||||
arr[0] = "-1"; // exception edge 1 with value -1
|
||||
if (args.length > 1) {
|
||||
f = 42;
|
||||
arr[1] = "42"; // exception edge 2 with value 42
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// exception handler block with incoming phi for "f"
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
f = f; // generates bytecodes, but no JIT IR
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
TestLinearScanHasFPURegisters t = new TestLinearScanHasFPURegisters();
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
t.test(args);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8268347
|
||||
* @summary Nested locks optimization may create unbalanced monitor enter/exit code
|
||||
*
|
||||
* @run main/othervm -XX:-BackgroundCompilation
|
||||
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::foo
|
||||
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getNext
|
||||
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getHolder
|
||||
* TestNestedLocksElimination
|
||||
*/
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class TestNestedLocksElimination {
|
||||
|
||||
private LinkedList<char[]> buffers = new LinkedList<>();
|
||||
private boolean complete = false;
|
||||
private int bufferSize;
|
||||
|
||||
void foo(char[] ca) {
|
||||
// Don't inline dummy method
|
||||
}
|
||||
|
||||
// Don't inline
|
||||
char[] getNext(int length, int count) {
|
||||
if (this.buffers.isEmpty()) {
|
||||
return new char[100];
|
||||
}
|
||||
char[] b = (char[]) this.buffers.getFirst();
|
||||
if (count >= 100) {
|
||||
this.complete = true;
|
||||
this.buffers.clear(); // empty
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
synchronized boolean isComplete() {
|
||||
return this.complete;
|
||||
}
|
||||
|
||||
synchronized boolean availableSegment() {
|
||||
return (buffers.isEmpty() == false);
|
||||
}
|
||||
|
||||
// Don't inline
|
||||
TestNestedLocksElimination getHolder(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int count) {
|
||||
return (count & 7) == 0 ? s2 : s1;
|
||||
}
|
||||
|
||||
int test(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int maxToSend) {
|
||||
boolean isComplete = true;
|
||||
boolean availableSegment = false;
|
||||
int size = 0;
|
||||
int count = 0;
|
||||
do {
|
||||
TestNestedLocksElimination s = getHolder(s1, s2, count++);
|
||||
|
||||
synchronized(s) {
|
||||
isComplete = s.isComplete();
|
||||
availableSegment = s.availableSegment();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
size = 0;
|
||||
while (size < maxToSend) {
|
||||
char[] b = null;
|
||||
// This is outer Lock region for object 's'.
|
||||
// Locks from following inlined methods are "nested"
|
||||
// because they reference the same object.
|
||||
synchronized(s) {
|
||||
b = s.getNext(maxToSend - size, count);
|
||||
|
||||
// The next is bi-morphic call with both calls inlined.
|
||||
// But one is synchronized and the other is not.
|
||||
// Class check for bi-morphic call is loop invariant
|
||||
// and will trigger loop unswitching.
|
||||
// Loop unswitching will create two versions of loop
|
||||
// with gollowing calls inlinined in both versions.
|
||||
|
||||
isComplete = s.isComplete();
|
||||
|
||||
// The next synchronized method availableSegment() is
|
||||
// inlined and its Lock will be "coarsened" with Unlock
|
||||
// in version of loop with inlined synchronized method
|
||||
// isComplete().
|
||||
// Nested Lock Optimization will mark only this Unlock
|
||||
// as nested (as part of "nested" pair lock/unlock).
|
||||
// Locks elimination will remove "coarsened" Lock from
|
||||
// availableSegment() method leaving unmatched unlock.
|
||||
|
||||
availableSegment = s.availableSegment();
|
||||
}
|
||||
foo(b);
|
||||
size += b.length;
|
||||
}
|
||||
}
|
||||
} while (availableSegment == true || isComplete == false);
|
||||
return size;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int count = 0;
|
||||
int n = 0;
|
||||
|
||||
TestNestedLocksElimination t = new TestNestedLocksElimination();
|
||||
TestNestedLocksElimination s1 = new TestNestedLocksElimination();
|
||||
TestNestedLocksElimination s2 = new TestNestedLocksEliminationSub();
|
||||
|
||||
char[] c = new char[100];
|
||||
while (n++ < 20_000) {
|
||||
s1.buffers.add(c);
|
||||
s2.buffers.add(c);
|
||||
count += t.test(s1, s2, 10000);
|
||||
}
|
||||
|
||||
System.out.println(" count: " + count);
|
||||
}
|
||||
}
|
||||
|
||||
class TestNestedLocksEliminationSub extends TestNestedLocksElimination {
|
||||
public boolean isComplete() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,12 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8248268
|
||||
* @bug 8248268 8268621
|
||||
* @summary Verify general properties of the AES/KW/NoPadding,
|
||||
* AES/KW/PKCS5Padding, and AES/KWP/NoPadding.
|
||||
* @run main TestGeneral
|
||||
*/
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.security.Key;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import javax.crypto.*;
|
||||
@ -37,7 +36,10 @@ import javax.crypto.spec.*;
|
||||
|
||||
public class TestGeneral {
|
||||
|
||||
private static final SecretKey KEY = new SecretKeySpec(new byte[16], "AES");;
|
||||
private static final byte[] DATA_128 =
|
||||
Arrays.copyOf("1234567890123456789012345678901234".getBytes(), 128);
|
||||
private static final SecretKey KEY =
|
||||
new SecretKeySpec(DATA_128, 0, 16, "AES");
|
||||
private static final int KW_IV_LEN = 8;
|
||||
private static final int KWP_IV_LEN = 4;
|
||||
private static final int MAX_KW_PKCS5PAD_LEN = 16; // 1-16
|
||||
@ -133,12 +135,27 @@ public class TestGeneral {
|
||||
}
|
||||
|
||||
public static void testIv(Cipher c) throws Exception {
|
||||
// get a fresh Cipher instance so we can test iv with pre-init state
|
||||
Cipher c2 = Cipher.getInstance(c.getAlgorithm(), c.getProvider());
|
||||
if (c2.getIV() != null) {
|
||||
throw new RuntimeException("Expects null iv");
|
||||
}
|
||||
if (c2.getParameters() == null) {
|
||||
throw new RuntimeException("Expects non-null default parameters");
|
||||
}
|
||||
|
||||
c2.init(Cipher.ENCRYPT_MODE, KEY);
|
||||
byte[] defIv2 = c2.getIV();
|
||||
c.init(Cipher.ENCRYPT_MODE, KEY);
|
||||
byte[] defIv = c.getIV();
|
||||
// try init w/ an iv w/ different length
|
||||
if (!Arrays.equals(defIv, defIv2)) {
|
||||
throw new RuntimeException("Failed default iv check");
|
||||
}
|
||||
// try init w/ an iv w/ invalid length
|
||||
try {
|
||||
c.init(Cipher.ENCRYPT_MODE, KEY, new IvParameterSpec(defIv, 0,
|
||||
defIv.length/2));
|
||||
throw new RuntimeException("Invalid iv accepted");
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
System.out.println("Invalid IV rejected as expected");
|
||||
}
|
||||
@ -146,19 +163,23 @@ public class TestGeneral {
|
||||
c.init(Cipher.ENCRYPT_MODE, KEY, new IvParameterSpec(defIv));
|
||||
byte[] newIv = c.getIV();
|
||||
if (!Arrays.equals(newIv, defIv)) {
|
||||
throw new RuntimeException("Failed iv check");
|
||||
throw new RuntimeException("Failed set iv check");
|
||||
}
|
||||
byte[] newIv2 = c.getIV();
|
||||
if (newIv == newIv2) {
|
||||
throw new RuntimeException("Failed getIV copy check");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] argv) throws Exception {
|
||||
// test all possible pad lengths, i.e. 1 - 16
|
||||
byte[] data = new byte[128];
|
||||
new Random().nextBytes(data);
|
||||
byte[] data = DATA_128;
|
||||
|
||||
String ALGO = "AES/KW/PKCS5Padding";
|
||||
System.out.println("Testing " + ALGO);
|
||||
Cipher c = Cipher.getInstance(ALGO, "SunJCE");
|
||||
for (int i = 0; i < MAX_KW_PKCS5PAD_LEN; i++) {
|
||||
|
||||
// test all possible pad lengths, i.e. 1 - 16
|
||||
for (int i = 1; i <= MAX_KW_PKCS5PAD_LEN; i++) {
|
||||
testEnc(c, data, data.length - i, KW_IV_LEN, MAX_KW_PKCS5PAD_LEN);
|
||||
testWrap(c, data, data.length - i, KW_IV_LEN, MAX_KW_PKCS5PAD_LEN);
|
||||
}
|
||||
@ -176,7 +197,9 @@ public class TestGeneral {
|
||||
ALGO = "AES/KWP/NoPadding";
|
||||
System.out.println("Testing " + ALGO);
|
||||
c = Cipher.getInstance(ALGO, "SunJCE");
|
||||
for (int i = 0; i < MAX_KWP_PAD_LEN; i++) {
|
||||
|
||||
// test all possible pad lengths, i.e. 0 - 7
|
||||
for (int i = 0; i <= MAX_KWP_PAD_LEN; i++) {
|
||||
testEnc(c, data, data.length - i, KWP_IV_LEN, MAX_KWP_PAD_LEN);
|
||||
testWrap(c, data, data.length - i, KWP_IV_LEN, MAX_KWP_PAD_LEN);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,60 +23,100 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4162868 8130181 8242151
|
||||
* @bug 4162868 8130181 8242151 8267397
|
||||
* @modules java.base/sun.security.x509
|
||||
* @modules java.base/sun.security.util
|
||||
* @run main/othervm ExtensibleAlgorithmId
|
||||
* @summary Algorithm Name-to-OID mapping needs to be made extensible.
|
||||
* @summary Check that AlgorithmId Name-to-OID mapping is extensible and
|
||||
* up-to-date.
|
||||
*/
|
||||
|
||||
// Run in othervm, coz AlgorithmId.oidTable is only initialized once
|
||||
|
||||
import java.security.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
public class ExtensibleAlgorithmId {
|
||||
|
||||
private static void test(String alg, String expOid) throws Exception {
|
||||
System.out.println("Testing " + alg + " and " + expOid );
|
||||
try {
|
||||
AlgorithmId algid = AlgorithmId.get(alg);
|
||||
if (expOid == null) {
|
||||
throw new Exception("Expected NSAE not thrown");
|
||||
}
|
||||
if (!expOid.equals(algid.getOID().toString())) {
|
||||
throw new Exception("Oid mismatch, expected " + expOid +
|
||||
", got " + algid.getOID().toString());
|
||||
}
|
||||
if (!alg.equals(algid.getName())) {
|
||||
throw new Exception("Name mismatch, expected " + alg +
|
||||
", got " + algid.getName());
|
||||
}
|
||||
// try AlgorithmId.get() using 'expOid' if (alg != expOid)
|
||||
if (alg != expOid) {
|
||||
algid = AlgorithmId.get(expOid);
|
||||
if (!expOid.equals(algid.getOID().toString())) {
|
||||
throw new Exception("Oid2 mismatch, expected " + expOid +
|
||||
", got " + algid.getOID().toString());
|
||||
}
|
||||
if (!alg.equals(algid.getName())) {
|
||||
throw new Exception("Name2 mismatch, expected " + alg +
|
||||
", got " + algid.getName());
|
||||
}
|
||||
}
|
||||
System.out.println(" => passed");
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
if (expOid != null) {
|
||||
nsae.printStackTrace();
|
||||
throw new Exception("Unexpected NSAE for " + alg);
|
||||
}
|
||||
System.out.println(" => expected NSAE thrown");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
TestProvider p = new TestProvider();
|
||||
Security.addProvider(p);
|
||||
AlgorithmId algid = AlgorithmId.getAlgorithmId(TestProvider.ALG_NAME);
|
||||
String oid = algid.getOID().toString();
|
||||
if (!oid.equals(TestProvider.ALG_OID)) {
|
||||
throw new Exception("Provider alias oid not used, found " + oid);
|
||||
}
|
||||
String name = algid.getName();
|
||||
if (!name.equalsIgnoreCase(TestProvider.ALG_NAME)) {
|
||||
throw new Exception("provider alias name not used, found " + name);
|
||||
}
|
||||
String alias = "Alg.Alias.Signature.OID." + oid;
|
||||
String alias = "Alg.Alias.Signature.OID." + TestProvider.ALG_OID;
|
||||
String stdAlgName = p.getProperty(alias);
|
||||
if (stdAlgName == null ||
|
||||
!stdAlgName.equalsIgnoreCase(TestProvider.ALG_NAME)) {
|
||||
throw new Exception("Wrong OID");
|
||||
}
|
||||
|
||||
// scenario#1: test before adding TestProvider
|
||||
System.out.println("Before adding test provider");
|
||||
test(TestProvider.ALG_NAME, null);
|
||||
test(TestProvider.ALG_OID, TestProvider.ALG_OID);
|
||||
test(TestProvider.ALG_OID2, TestProvider.ALG_OID2);
|
||||
|
||||
Security.addProvider(p);
|
||||
// scenario#2: test again after adding TestProvider
|
||||
System.out.println("After adding test provider");
|
||||
test(TestProvider.ALG_NAME, TestProvider.ALG_OID);
|
||||
test(TestProvider.ALG_OID2, TestProvider.ALG_OID2);
|
||||
|
||||
Security.removeProvider(p.getName());
|
||||
// scenario#3: test after removing TestProvider; should be same as
|
||||
// scenario#1
|
||||
System.out.println("After removing test provider");
|
||||
test(TestProvider.ALG_NAME, null);
|
||||
test(TestProvider.ALG_OID, TestProvider.ALG_OID);
|
||||
test(TestProvider.ALG_OID2, TestProvider.ALG_OID2);
|
||||
}
|
||||
|
||||
static class TestProvider extends Provider {
|
||||
|
||||
static String ALG_OID = "1.2.3.4.5.6.7.8.9.0";
|
||||
static String ALG_OID2 = "0.2.7.6.5.4.3.2.1.0";
|
||||
static String ALG_NAME = "XYZ";
|
||||
|
||||
public TestProvider() {
|
||||
super("Dummy", "1.0", "XYZ algorithm");
|
||||
super("Dummy", "1.0", "XYZ algorithm");
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
|
||||
put("Signature." + ALG_NAME, "test.xyz");
|
||||
// preferred OID
|
||||
put("Alg.Alias.Signature.OID." + ALG_OID,
|
||||
ALG_NAME);
|
||||
put("Alg.Alias.Signature.9.8.7.6.5.4.3.2.1.0",
|
||||
ALG_NAME);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
put("Signature." + ALG_NAME, "test.xyz");
|
||||
// preferred OID for name<->oid mapping
|
||||
put("Alg.Alias.Signature.OID." + ALG_OID, ALG_NAME);
|
||||
put("Alg.Alias.Signature." + ALG_OID2, ALG_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8262891
|
||||
* @bug 8262891 8268663
|
||||
* @summary Check guards implementation.
|
||||
* @compile --enable-preview -source ${jdk.version} Guards.java
|
||||
* @run main/othervm --enable-preview Guards
|
||||
@ -43,6 +43,9 @@ public class Guards {
|
||||
run(this::testBooleanSwitchExpression);
|
||||
assertEquals("a", testPatternInGuard("a"));
|
||||
assertEquals(null, testPatternInGuard(1));
|
||||
runIfTrue(this::typeGuardIfTrueIfStatement);
|
||||
runIfTrue(this::typeGuardIfTrueSwitchExpression);
|
||||
runIfTrue(this::typeGuardIfTrueSwitchStatement);
|
||||
}
|
||||
|
||||
void run(Function<Object, String> convert) {
|
||||
@ -52,6 +55,12 @@ public class Guards {
|
||||
assertEquals("any", convert.apply(""));
|
||||
}
|
||||
|
||||
void runIfTrue(Function<Object, String> convert) {
|
||||
assertEquals("true", convert.apply(0));
|
||||
assertEquals("second", convert.apply(2));
|
||||
assertEquals("any", convert.apply(""));
|
||||
}
|
||||
|
||||
String typeTestPatternSwitchTest(Object o) {
|
||||
switch (o) {
|
||||
case Integer i && i == 0: return "zero";
|
||||
@ -84,6 +93,35 @@ public class Guards {
|
||||
}
|
||||
}
|
||||
|
||||
String typeGuardIfTrueSwitchStatement(Object o) {
|
||||
Object o2 = "";
|
||||
switch (o) {
|
||||
case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); return "true";
|
||||
case Integer i && i == 0 || i > 1: o = String.valueOf(i); return "second";
|
||||
case Object x: return "any";
|
||||
}
|
||||
}
|
||||
|
||||
String typeGuardIfTrueSwitchExpression(Object o) {
|
||||
Object o2 = "";
|
||||
return switch (o) {
|
||||
case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); yield "true";
|
||||
case Integer i && i == 0 || i > 1: o = String.valueOf(i); yield "second";
|
||||
case Object x: yield "any";
|
||||
};
|
||||
}
|
||||
|
||||
String typeGuardIfTrueIfStatement(Object o) {
|
||||
Object o2 = "";
|
||||
if (o != null && o instanceof (Integer i && i == 0 && i < 1) && (o = i) != null && o2 instanceof String s) {
|
||||
return s != null ? "true" : null;
|
||||
} else if (o != null && o instanceof (Integer i && i == 0 || i > 1) && (o = i) != null) {
|
||||
return "second";
|
||||
} else {
|
||||
return "any";
|
||||
}
|
||||
}
|
||||
|
||||
String testPatternInGuard(Object o) {
|
||||
if (o instanceof (CharSequence cs && cs instanceof String s)) {
|
||||
return s;
|
||||
|
@ -190,4 +190,16 @@ public class SwitchErrors {
|
||||
}
|
||||
sealed class SealedNonAbstract permits A {}
|
||||
final class A extends SealedNonAbstract {}
|
||||
Object guardWithMatchingStatement(Object o1, Object o2) {
|
||||
switch (o1) {
|
||||
case String s && s.isEmpty() || o2 instanceof Number n: return n;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
Object guardWithMatchingExpression(Object o1, Object o2) {
|
||||
return switch (o1) {
|
||||
case String s && s.isEmpty() || o2 instanceof Number n -> n;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ SwitchErrors.java:166:18: compiler.err.flows.through.from.pattern
|
||||
SwitchErrors.java:171:27: compiler.err.flows.through.to.pattern
|
||||
SwitchErrors.java:177:18: compiler.err.flows.through.to.pattern
|
||||
SwitchErrors.java:183:13: compiler.err.pattern.dominated
|
||||
SwitchErrors.java:195:76: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
||||
SwitchErrors.java:201:71: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
||||
SwitchErrors.java:32:9: compiler.err.not.exhaustive.statement
|
||||
SwitchErrors.java:38:9: compiler.err.not.exhaustive.statement
|
||||
SwitchErrors.java:44:9: compiler.err.not.exhaustive.statement
|
||||
@ -41,4 +43,4 @@ SwitchErrors.java:127:9: compiler.err.not.exhaustive.statement
|
||||
SwitchErrors.java:187:9: compiler.err.not.exhaustive.statement
|
||||
- compiler.note.preview.filename: SwitchErrors.java, DEFAULT
|
||||
- compiler.note.preview.recompile
|
||||
41 errors
|
||||
43 errors
|
||||
|
@ -27,7 +27,7 @@ import java.util.function.Function;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8262891
|
||||
* @bug 8262891 8268333
|
||||
* @summary Check behavior of pattern switches.
|
||||
* @compile --enable-preview -source ${jdk.version} Switches.java
|
||||
* @run main/othervm --enable-preview Switches
|
||||
@ -46,6 +46,8 @@ public class Switches {
|
||||
assertTrue(testNullSwitch(""));
|
||||
runArrayTypeTest(this::testArrayTypeStatement);
|
||||
runArrayTypeTest(this::testArrayTypeExpression);
|
||||
runDefaultTest(this::testDefaultDoesNotDominateStatement);
|
||||
runDefaultTest(this::testDefaultDoesNotDominateExpression);
|
||||
runEnumTest(this::testEnumExpression1);
|
||||
runEnumTest(this::testEnumExpression2);
|
||||
runEnumTest(this::testEnumWithGuards1);
|
||||
@ -81,6 +83,13 @@ public class Switches {
|
||||
assertEquals("", mapper.apply(1.0));
|
||||
}
|
||||
|
||||
void runDefaultTest(Function<Object, String> mapper) {
|
||||
assertEquals("default", mapper.apply(new int[0]));
|
||||
assertEquals("str6", mapper.apply("string"));
|
||||
assertEquals("default", mapper.apply(1));
|
||||
assertEquals("default", mapper.apply(1.0));
|
||||
}
|
||||
|
||||
void runEnumTest(Function<E, String> mapper) {
|
||||
assertEquals("a", mapper.apply(E.A));
|
||||
assertEquals("b", mapper.apply(E.B));
|
||||
@ -172,6 +181,22 @@ public class Switches {
|
||||
};
|
||||
}
|
||||
|
||||
String testDefaultDoesNotDominateStatement(Object o) {
|
||||
String res;
|
||||
switch (o) {
|
||||
default -> res = "default";
|
||||
case String str -> res = "str" + str.length();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
String testDefaultDoesNotDominateExpression(Object o) {
|
||||
return switch (o) {
|
||||
case default -> "default";
|
||||
case String str -> "str" + str.length();
|
||||
};
|
||||
}
|
||||
|
||||
int testStringWithConstant(String str) {
|
||||
switch (str) {
|
||||
case "A": return 1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8206986 8222169 8224031 8240964 8267119
|
||||
* @bug 8206986 8222169 8224031 8240964 8267119 8268670
|
||||
* @summary Check expression switch works.
|
||||
* @compile/fail/ref=ExpressionSwitch-old.out -source 9 -Xlint:-options -XDrawDiagnostics ExpressionSwitch.java
|
||||
* @compile ExpressionSwitch.java
|
||||
@ -120,6 +120,26 @@ public class ExpressionSwitch {
|
||||
};
|
||||
}
|
||||
|
||||
private int yieldUnaryNumberOperator(String s, int a) {
|
||||
return switch (s) {
|
||||
case "a": yield +a;
|
||||
case "b": yield -a;
|
||||
case "c": yield ~a; // intentionally repeated ~a, test the case clause
|
||||
case "d": yield ++a;
|
||||
case "e": yield --a;
|
||||
case "f": yield a++;
|
||||
case "g": yield a--;
|
||||
default: yield ~a; // intentionally repeated ~a, test the default clause
|
||||
};
|
||||
}
|
||||
|
||||
private boolean yieldUnaryNotOperator(String s, boolean b) {
|
||||
return switch (s) {
|
||||
case "a": yield !b; // intentionally repeated !b, test the case clause
|
||||
default: yield !b; // intentionally repeated !b, test the default clause
|
||||
};
|
||||
}
|
||||
|
||||
private void localClass(T t) {
|
||||
String good = "good";
|
||||
class L {
|
||||
|
Loading…
Reference in New Issue
Block a user