This commit is contained in:
Jesper Wilhelmsson 2021-06-15 22:45:28 +00:00
commit e0f6f70d3f
62 changed files with 1423 additions and 424 deletions

View File

@ -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

View File

@ -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)
])

View File

@ -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@

View 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>

View File

@ -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

View 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>

View File

@ -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>

View File

@ -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" />

View File

@ -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" />

View File

@ -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>

View 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());
}
}

View 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);
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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), \

View File

@ -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, &not_precolored_cpu_intervals,
is_precolored_cpu_interval, is_virtual_cpu_interval);
// allocate fpu registers
// collect fpu intervals
create_unhandled_lists(&precolored_fpu_intervals, &not_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();

View File

@ -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) {

View File

@ -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");
}

View File

@ -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);

View File

@ -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.

View File

@ -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) {

View File

@ -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;)
}

View File

@ -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.

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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();

View File

@ -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(); }

View File

@ -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
*/

View File

@ -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

View File

@ -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
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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
};

View File

@ -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,
};

View File

@ -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));

View File

@ -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

View File

@ -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();
}
/**

View File

@ -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

View File

@ -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.

View File

@ -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());

View File

@ -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() &&

View File

@ -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());

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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
*/

View File

@ -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;

View File

@ -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())) {

View File

@ -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

View File

@ -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

View File

@ -129,6 +129,7 @@ tier1_compiler_2 = \
tier1_compiler_3 = \
compiler/intrinsics/ \
compiler/jsr292/ \
compiler/locks/ \
compiler/loopopts/ \
compiler/macronodes/ \
compiler/memoryinitialization/ \

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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;
};
}
}

View File

@ -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

View File

@ -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;

View File

@ -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 {