--- a/.hgtags Wed Apr 10 10:32:43 2019 +0530
+++ b/.hgtags Wed Apr 10 10:46:53 2019 +0530
@@ -552,3 +552,4 @@
b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga
83cace4142c8563b6a921787db02388e1bc48d01 jdk-13+13
46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14
+f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15
--- a/doc/testing.html Wed Apr 10 10:32:43 2019 +0530
+++ b/doc/testing.html Wed Apr 10 10:46:53 2019 +0530
@@ -1,19 +1,24 @@
<!DOCTYPE html>
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
- <meta charset="utf-8">
- <meta name="generator" content="pandoc">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
+ <meta charset="utf-8" />
+ <meta name="generator" content="pandoc" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Testing the JDK</title>
- <style type="text/css">code{white-space: pre;}</style>
- <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css">
+ <style type="text/css">
+ code{white-space: pre-wrap;}
+ span.smallcaps{font-variant: small-caps;}
+ span.underline{text-decoration: underline;}
+ div.column{display: inline-block; vertical-align: top; width: 50%;}
+ </style>
+ <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
</head>
<body>
-<header>
+<header id="title-block-header">
<h1 class="title">Testing the JDK</h1>
</header>
<nav id="TOC">
@@ -34,6 +39,9 @@
<li><a href="#gtest-keywords">Gtest keywords</a></li>
<li><a href="#microbenchmark-keywords">Microbenchmark keywords</a></li>
</ul></li>
+<li><a href="#notes-for-specific-tests">Notes for Specific Tests</a><ul>
+<li><a href="#docker-tests">Docker Tests</a></li>
+</ul></li>
</ul>
</nav>
<h2 id="using-make-test-the-run-test-framework">Using "make test" (the run-test framework)</h2>
@@ -180,5 +188,11 @@
<p>Additional VM arguments to provide to forked off VMs. Same as <code>-jvmArgs <args></code></p>
<h4 id="options-2">OPTIONS</h4>
<p>Additional arguments to send to JMH.</p>
+<h2 id="notes-for-specific-tests">Notes for Specific Tests</h2>
+<h3 id="docker-tests">Docker Tests</h3>
+<p>Docker tests with default parameters may fail on systems with glibc versions not compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:</p>
+<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker"</code></pre>
+<p>To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using <code>JAVA_OPTIONS</code>.</p>
+<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"</code></pre>
</body>
</html>
--- a/doc/testing.md Wed Apr 10 10:32:43 2019 +0530
+++ b/doc/testing.md Wed Apr 10 10:46:53 2019 +0530
@@ -373,6 +373,21 @@
#### OPTIONS
Additional arguments to send to JMH.
+## Notes for Specific Tests
+
+### Docker Tests
+
+Docker tests with default parameters may fail on systems with glibc versions not
+compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86).
+For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:
+
+ $ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker"
+
+To run these tests correctly, additional parameters for the correct docker image are
+required on Ubuntu 18.04 by using `JAVA_OPTIONS`.
+
+ $ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
+
---
# Override some definitions in the global css file that are not optimal for
# this document.
--- a/make/Init.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/Init.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -238,11 +238,13 @@
ifeq ($(LOG_NOFILE), true)
# Disable build log if LOG=[level,]nofile was given
override BUILD_LOG_PIPE :=
+ override BUILD_LOG_PIPE_SIMPLE :=
endif
ifeq ($(filter dist-clean, $(SEQUENTIAL_TARGETS)), dist-clean)
# We can't have a log file if we're about to remove it.
override BUILD_LOG_PIPE :=
+ override BUILD_LOG_PIPE_SIMPLE :=
endif
ifeq ($(OUTPUT_SYNC_SUPPORTED), true)
@@ -277,7 +279,7 @@
else
$(ECHO) "Re-running configure using default settings"
endif
- ( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" AUTOCONF="$(AUTOCONF)" \
+ ( cd $(CONFIGURE_START_DIR) && PATH="$(ORIGINAL_PATH)" AUTOCONF="$(AUTOCONF)" \
CUSTOM_ROOT="$(CUSTOM_ROOT)" \
CUSTOM_CONFIG_DIR="$(CUSTOM_CONFIG_DIR)" \
$(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) )
@@ -303,7 +305,7 @@
main: $(INIT_TARGETS)
ifneq ($(SEQUENTIAL_TARGETS)$(PARALLEL_TARGETS), )
$(call RotateLogFiles)
- $(PRINTF) "Building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE)
+ $(PRINTF) "Building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE_SIMPLE)
ifneq ($(SEQUENTIAL_TARGETS), )
# Don't touch build output dir since we might be cleaning. That
# means no log pipe.
@@ -325,7 +327,7 @@
$(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) $(BUILD_LOG_PIPE) || \
( exitcode=$$? && \
$(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" \
- $(BUILD_LOG_PIPE) && \
+ $(BUILD_LOG_PIPE_SIMPLE) && \
cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -j 1 -f make/Init.gmk \
HAS_SPEC=true on-failure ; \
exit $$exitcode ) )
@@ -336,7 +338,7 @@
if test -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error ; then \
exit 1 ; \
fi
- $(PRINTF) "Finished building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE)
+ $(PRINTF) "Finished building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE_SIMPLE)
$(call ReportProfileTimes)
endif
--- a/make/InitSupport.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/InitSupport.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -296,6 +296,9 @@
BUILD_PROFILE_LOG := $(OUTPUTDIR)/build-profile.log
BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait
+ # Use this for simple echo/printf commands that are never expected to print
+ # to stderr.
+ BUILD_LOG_PIPE_SIMPLE := | $(TEE) -a $(BUILD_LOG)
ifneq ($(CUSTOM_ROOT), )
topdir=$(CUSTOM_ROOT)
@@ -514,7 +517,7 @@
"`$(LS) $(BUILDTIMESDIR)/build_time_diff_* | $(GREP) -v _TOTAL | \
$(XARGS) $(CAT) | $(SORT) -k 2`" \
"`$(CAT) $(BUILDTIMESDIR)/build_time_diff_TOTAL`" \
- $(BUILD_LOG_PIPE)
+ $(BUILD_LOG_PIPE_SIMPLE)
endef
define ReportProfileTimes
@@ -524,7 +527,7 @@
$(CAT) $(BUILD_PROFILE_LOG) && \
$(ECHO) End $(notdir $(BUILD_PROFILE_LOG)); \
} \
- $(BUILD_LOG_PIPE)
+ $(BUILD_LOG_PIPE_SIMPLE)
)
endef
--- a/make/Main.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/Main.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -335,6 +335,7 @@
bootcycle-images:
ifneq ($(COMPILE_TYPE), cross)
$(call LogWarn, Boot cycle build step 2: Building a new JDK image using previously built image)
+ $(call MakeDir, $(OUTPUTDIR)/bootcycle-build)
+$(MAKE) $(MAKE_ARGS) -f $(TOPDIR)/make/Init.gmk PARALLEL_TARGETS=$(BOOTCYCLE_TARGET) \
JOBS= SPEC=$(dir $(SPEC))bootcycle-spec.gmk main
else
@@ -650,7 +651,6 @@
# Declare dependencies between hotspot-<variant>* targets
$(foreach v, $(JVM_VARIANTS), \
- $(eval hotspot-$v: hotspot-$v-gensrc hotspot-$v-libs) \
$(eval hotspot-$v-gensrc: java.base-copy) \
$(eval hotspot-$v-libs: hotspot-$v-gensrc java.base-copy) \
)
@@ -943,6 +943,10 @@
buildtools: buildtools-langtools interim-langtools interim-rmic \
buildtools-jdk $(JVM_TOOLS_TARGETS)
+# Declare dependencies from hotspot-<variant> targets
+$(foreach v, $(JVM_VARIANTS), \
+ $(eval hotspot-$v: hotspot-$v-gensrc hotspot-$v-libs) \
+)
hotspot: $(HOTSPOT_VARIANT_TARGETS)
# Create targets hotspot-libs and hotspot-gensrc.
--- a/make/autoconf/basics.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/basics.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -627,7 +627,7 @@
AC_DEFUN_ONCE([BASIC_SETUP_PATHS],
[
# Save the current directory this script was started from
- CURDIR="$PWD"
+ CONFIGURE_START_DIR="$PWD"
# We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them
# for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED
@@ -653,9 +653,10 @@
AC_MSG_CHECKING([for top-level directory])
AC_MSG_RESULT([$TOPDIR])
AC_SUBST(TOPDIR)
+ AC_SUBST(CONFIGURE_START_DIR)
# We can only call BASIC_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS.
- BASIC_FIXUP_PATH(CURDIR)
+ BASIC_FIXUP_PATH(CONFIGURE_START_DIR)
BASIC_FIXUP_PATH(TOPDIR)
# Locate the directory of this script.
@@ -868,9 +869,10 @@
# Test from where we are running configure, in or outside of src root.
AC_MSG_CHECKING([where to store configuration])
- if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$CUSTOM_ROOT" \
- || test "x$CURDIR" = "x$TOPDIR/make/autoconf" \
- || test "x$CURDIR" = "x$TOPDIR/make" ; then
+ if test "x$CONFIGURE_START_DIR" = "x$TOPDIR" \
+ || test "x$CONFIGURE_START_DIR" = "x$CUSTOM_ROOT" \
+ || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make/autoconf" \
+ || test "x$CONFIGURE_START_DIR" = "x$TOPDIR/make" ; then
# We are running configure from the src root.
# Create a default ./build/target-variant-debuglevel output root.
if test "x${CONF_NAME}" = x; then
@@ -895,9 +897,9 @@
# If configuration is situated in normal build directory, just use the build
# directory name as configuration name, otherwise use the complete path.
if test "x${CONF_NAME}" = x; then
- CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${TOPDIR}/build/!!"`
+ CONF_NAME=`$ECHO $CONFIGURE_START_DIR | $SED -e "s!^${TOPDIR}/build/!!"`
fi
- OUTPUTDIR="$CURDIR"
+ OUTPUTDIR="$CONFIGURE_START_DIR"
AC_MSG_RESULT([in current directory])
# WARNING: This might be a bad thing to do. You need to be sure you want to
@@ -917,14 +919,14 @@
-e 's/ //g' \
| $TR -d '\n'`
if test "x$filtered_files" != x; then
- AC_MSG_NOTICE([Current directory is $CURDIR.])
+ AC_MSG_NOTICE([Current directory is $CONFIGURE_START_DIR.])
AC_MSG_NOTICE([Since this is not the source root, configure will output the configuration here])
AC_MSG_NOTICE([(as opposed to creating a configuration in <src_root>/build/<conf-name>).])
AC_MSG_NOTICE([However, this directory is not empty. This is not allowed, since it could])
AC_MSG_NOTICE([seriously mess up just about everything.])
AC_MSG_NOTICE([Try 'cd $TOPDIR' and restart configure])
AC_MSG_NOTICE([(or create a new empty directory and cd to it).])
- AC_MSG_ERROR([Will not continue creating configuration in $CURDIR])
+ AC_MSG_ERROR([Will not continue creating configuration in $CONFIGURE_START_DIR])
fi
fi
fi
--- a/make/autoconf/basics_windows.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/basics_windows.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -551,7 +551,7 @@
$MKDIR -p $FIXPATH_DIR $CONFIGURESUPPORT_OUTPUTDIR/bin
cd $FIXPATH_DIR
$CC $FIXPATH_SRC_W -Fe$FIXPATH_BIN_W > $FIXPATH_DIR/fixpath1.log 2>&1
- cd $CURDIR
+ cd $CONFIGURE_START_DIR
if test ! -x $FIXPATH_BIN; then
AC_MSG_RESULT([no])
@@ -574,7 +574,7 @@
cd $FIXPATH_DIR
$FIXPATH $CC $FIXPATH_SRC -Fe$FIXPATH_DIR/fixpath2.exe \
> $FIXPATH_DIR/fixpath2.log 2>&1
- cd $CURDIR
+ cd $CONFIGURE_START_DIR
if test ! -x $FIXPATH_DIR/fixpath2.exe; then
AC_MSG_RESULT([no])
cat $FIXPATH_DIR/fixpath2.log
--- a/make/autoconf/flags-other.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/flags-other.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2019, 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
@@ -81,10 +81,10 @@
RC_FLAGS="$RC_FLAGS \
-D\"JDK_VERSION_STRING=\$(VERSION_STRING)\" \
-D\"JDK_COMPANY=\$(COMPANY_NAME)\" \
- -D\"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \
+ -D\"JDK_COMPONENT=\$(JDK_RC_NAME) binary\" \
-D\"JDK_VER=\$(VERSION_NUMBER)\" \
-D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \
- -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_FEATURE)\" \
+ -D\"JDK_NAME=\$(JDK_RC_NAME) \$(VERSION_FEATURE)\" \
-D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\""
JVM_RCFLAGS="$JVM_RCFLAGS \
--- a/make/autoconf/jdk-version.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/jdk-version.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2019, 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
@@ -69,6 +69,23 @@
AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
AC_SUBST(MACOSX_BUNDLE_ID_BASE)
+ # Set the JDK RC name
+ AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name],
+ [Set JDK RC name. This is used for FileDescription and ProductName properties
+ of MS Windows binaries. @<:@not specified@:>@])])
+ if test "x$with_jdk_rc_name" = xyes; then
+ AC_MSG_ERROR([--with-jdk-rc-name must have a value])
+ elif [ ! [[ $with_jdk_rc_name =~ ^[[:print:]]*$ ]] ]; then
+ AC_MSG_ERROR([--with-jdk-rc-name contains non-printing characters: $with_jdk_rc_name])
+ elif test "x$with_jdk_rc_name" != x; then
+ # Set JDK_RC_NAME to a custom value if '--with-jdk-rc-name' was used and is not empty.
+ JDK_RC_NAME="$with_jdk_rc_name"
+ else
+ # Otherwise calculate from "version-numbers" included above.
+ JDK_RC_NAME="$PRODUCT_NAME $JDK_RC_PLATFORM_NAME"
+ fi
+ AC_SUBST(JDK_RC_NAME)
+
# The vendor name, if any
AC_ARG_WITH(vendor-name, [AS_HELP_STRING([--with-vendor-name],
[Set vendor name. Among others, used to set the 'java.vendor'
--- a/make/autoconf/spec.gmk.in Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/spec.gmk.in Wed Apr 10 10:46:53 2019 +0530
@@ -32,6 +32,8 @@
# The command line given to configure.
CONFIGURE_COMMAND_LINE:=@CONFIGURE_COMMAND_LINE@
+# The current directory when configure was run
+CONFIGURE_START_DIR:=@CONFIGURE_START_DIR@
# A self-referential reference to this file.
SPEC:=@SPEC@
@@ -139,7 +141,6 @@
# The top-level directory of the source repository
TOPDIR:=@TOPDIR@
-
IMPORT_MODULES_CLASSES:=@IMPORT_MODULES_CLASSES@
IMPORT_MODULES_CMDS:=@IMPORT_MODULES_CMDS@
IMPORT_MODULES_LIBS:=@IMPORT_MODULES_LIBS@
@@ -156,6 +157,7 @@
PRODUCT_NAME:=@PRODUCT_NAME@
PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@
JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@
+JDK_RC_NAME:=@JDK_RC_NAME@
COMPANY_NAME:=@COMPANY_NAME@
HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@
MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@
--- a/make/autoconf/toolchain_windows.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/make/autoconf/toolchain_windows.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -472,7 +472,7 @@
# Change directory so we don't need to mess with Windows paths in redirects.
cd $VS_ENV_TMP_DIR
$CMD /c extract-vs-env.bat | $CAT
- cd $CURDIR
+ cd $CONFIGURE_START_DIR
if test ! -s $VS_ENV_TMP_DIR/set-vs-env.sh; then
AC_MSG_NOTICE([Could not succesfully extract the environment variables needed for the VS setup.])
--- a/make/common/NativeCompilation.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/common/NativeCompilation.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -231,8 +231,8 @@
# Only continue if this object file hasn't been processed already. This lets
# the first found source file override any other with the same name.
- ifeq ($$(findstring $$($1_OBJ), $$($$($1_BASE)_OBJS_SO_FAR)), )
- $$($1_BASE)_OBJS_SO_FAR += $$($1_OBJ)
+ ifeq ($$($1_OBJ_PROCESSED), )
+ $1_OBJ_PROCESSED := true
# This is the definite source file to use for $1_FILENAME.
$1_SRC_FILE := $$($1_FILE)
@@ -308,14 +308,18 @@
ifeq ($$(filter %.s %.S, $$($1_FILENAME)), )
# And this is the dependency file for this obj file.
- $1_DEP := $$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_OBJ))
+ $1_DEPS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_OBJ))
# The dependency target file lists all dependencies as empty targets to
# avoid make error "No rule to make target" for removed files
- $1_DEP_TARGETS := $$(patsubst %$(OBJ_SUFFIX),%.d.targets,$$($1_OBJ))
+ $1_DEPS_TARGETS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d.targets,$$($1_OBJ))
- # Include previously generated dependency information. (if it exists)
- -include $$($1_DEP)
- -include $$($1_DEP_TARGETS)
+ # Only try to load individual dependency information files if the global
+ # file hasn't been loaded (could happen if make was interrupted).
+ ifneq ($$($$($1_BASE)_DEPS_FILE_LOADED), true)
+ # Include previously generated dependency information. (if it exists)
+ -include $$($1_DEPS_FILE)
+ -include $$($1_DEPS_TARGETS_FILE)
+ endif
endif
ifneq ($$(strip $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)), )
@@ -340,16 +344,16 @@
# object file in the generated deps files. Fixing it with sed. If
# compiling assembly, don't try this.
$$(call ExecuteWithLog, $$@, \
- $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEP).tmp $$($1_COMPILE_OPTIONS))
- $(SED) 's|^$$(@F):|$$@:|' $$($1_DEP).tmp > $$($1_DEP)
+ $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEPS_FILE).tmp $$($1_COMPILE_OPTIONS))
+ $(SED) 's|^$$(@F):|$$@:|' $$($1_DEPS_FILE).tmp > $$($1_DEPS_FILE)
else
$$(call ExecuteWithLog, $$@, \
- $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEP) $$($1_COMPILE_OPTIONS))
+ $$($1_COMPILER) $$($1_DEP_FLAG) $$($1_DEPS_FILE) $$($1_COMPILE_OPTIONS))
endif
# Create a dependency target file from the dependency file.
# Solution suggested by http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
- ifneq ($$($1_DEP), )
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEP) > $$($1_DEP_TARGETS)
+ ifneq ($$($1_DEPS_FILE), )
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) > $$($1_DEPS_TARGETS_FILE)
endif
else
# The Visual Studio compiler lacks a feature for generating make
@@ -363,10 +367,10 @@
$$($1_COMPILER) -showIncludes $$($1_COMPILE_OPTIONS)) \
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
-e "^$$($1_FILENAME)$$$$" || test "$$$$?" = "1" ; \
- $(ECHO) $$@: \\ > $$($1_DEP) ; \
+ $(ECHO) $$@: \\ > $$($1_DEPS_FILE) ; \
$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_OBJ).log \
- | $(SORT) -u >> $$($1_DEP) ; \
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEP) > $$($1_DEP_TARGETS)
+ | $(SORT) -u >> $$($1_DEPS_FILE) ; \
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) > $$($1_DEPS_TARGETS_FILE)
endif
endif
endef
@@ -486,6 +490,9 @@
$1_NOSUFFIX := $$($1_PREFIX)$$($1_NAME)
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
+# Need to make sure TARGET is first on list
+ $1 := $$($1_TARGET)
+
# Setup the toolchain to be used
$$(call SetIfEmpty, $1_TOOLCHAIN, TOOLCHAIN_DEFAULT)
$$(call SetIfEmpty, $1_CC, $$($$($1_TOOLCHAIN)_CC))
@@ -719,20 +726,21 @@
$1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch
$1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE)
endif
- $1_PCH_DEP := $$($1_PCH_FILE).d
- $1_PCH_DEP_TARGETS := $$($1_PCH_FILE).d.targets
+ $1_PCH_DEPS_FILE := $$($1_PCH_FILE).d
+ $1_PCH_DEPS_TARGETS_FILE := $$($1_PCH_FILE).d.targets
- -include $$($1_PCH_DEP)
- -include $$($1_PCH_DEP_TARGETS)
+ -include $$($1_PCH_DEPS_FILE)
+ -include $$($1_PCH_DEPS_TARGETS_FILE)
$1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
- $$($1_OPT_CFLAGS) -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP)
+ $$($1_OPT_CFLAGS) -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEPS_FILE)
$$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
$$(call LogInfo, Generating precompiled header)
$$(call MakeDir, $$(@D))
$$(call ExecuteWithLog, $$@, $$($1_PCH_COMMAND) $$< -o $$@)
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEP) > $$($1_PCH_DEP_TARGETS)
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEPS_FILE) \
+ > $$($1_PCH_DEPS_TARGETS_FILE)
$$($1_ALL_OBJS): $$($1_PCH_FILE)
@@ -748,6 +756,34 @@
endif
endif
+ # Create a rule to collect all the individual make dependency files into a
+ # single makefile.
+ $1_DEPS_FILE := $$($1_OBJECT_DIR)/$1.d
+
+ $$($1_DEPS_FILE): $$($1_ALL_OBJS)
+ $(RM) $$@
+ # CD into dir to reduce risk of hitting command length limits, which
+ # could otherwise happen if TOPDIR is a very long path.
+ $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d > $$@.tmp
+ $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d.targets | $(SORT) -u >> $$@.tmp
+ # After generating the file, which happens after all objects have been
+ # compiled, copy it to .old extension. On the next make invocation, this
+ # .old file will be included by make.
+ $(CP) $$@.tmp $$@.old
+ $(MV) $$@.tmp $$@
+
+ $1 += $$($1_DEPS_FILE)
+
+ # The include must be on the .old file, which represents the state from the
+ # previous invocation of make. The file being included must not have a rule
+ # defined for it as otherwise make will think it has to run the rule before
+ # being able to include the file, which would be wrong since we specifically
+ # need the file as it was generated by a previous make invocation.
+ ifneq ($$(wildcard $$($1_DEPS_FILE).old), )
+ $1_DEPS_FILE_LOADED := true
+ -include $$($1_DEPS_FILE).old
+ endif
+
# Now call SetupCompileNativeFile for each source file we are going to compile.
$$(foreach file, $$($1_SRCS), \
$$(eval $$(call SetupCompileNativeFile, $1_$$(notdir $$(file)),\
@@ -774,10 +810,10 @@
ifeq ($(call isTargetOs, windows), true)
ifneq ($$($1_VERSIONINFO_RESOURCE), )
$1_RES := $$($1_OBJECT_DIR)/$$($1_BASENAME).res
- $1_RES_DEP := $$($1_RES).d
- $1_RES_DEP_TARGETS := $$($1_RES).d.targets
- -include $$($1_RES_DEP)
- -include $$($1_RES_DEP_TARGETS)
+ $1_RES_DEPS_FILE := $$($1_RES).d
+ $1_RES_DEPS_TARGETS_FILE := $$($1_RES).d.targets
+ -include $$($1_RES_DEPS_FILE)
+ -include $$($1_RES_DEPS_TARGETS_FILE)
$1_RES_VARDEPS := $$($1_RC) $$($1_RC_FLAGS)
$1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
@@ -794,16 +830,18 @@
# For some unknown reason, in this case CL actually outputs the show
# includes to stderr so need to redirect it to hide the output from the
# main log.
- $$(call ExecuteWithLog, $$($1_RES_DEP).obj, \
+ $$(call ExecuteWithLog, $$($1_RES_DEPS_FILE).obj, \
$$($1_CC) $$(filter-out -l%, $$($1_RC_FLAGS)) \
$$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
- $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \
+ $(CC_OUT_OPTION)$$($1_RES_DEPS_FILE).obj -P -Fi$$($1_RES_DEPS_FILE).pp \
$$($1_VERSIONINFO_RESOURCE)) 2>&1 \
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
-e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
- $(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \
- $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).obj.log >> $$($1_RES_DEP) ; \
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS)
+ $(ECHO) $$($1_RES): \\ > $$($1_RES_DEPS_FILE) ; \
+ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEPS_FILE).obj.log \
+ >> $$($1_RES_DEPS_FILE) ; \
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEPS_FILE) \
+ > $$($1_RES_DEPS_TARGETS_FILE)
endif
endif
@@ -830,9 +868,6 @@
$1_EXTRA_LDFLAGS += $(call SET_SHARED_LIBRARY_MAPFILE,$$($1_REAL_MAPFILE))
endif
- # Need to make sure TARGET is first on list
- $1 := $$($1_TARGET)
-
ifneq ($$($1_COPY_DEBUG_SYMBOLS), false)
$1_COPY_DEBUG_SYMBOLS := $(COPY_DEBUG_SYMBOLS)
endif
--- a/make/hotspot/lib/JvmFeatures.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/hotspot/lib/JvmFeatures.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -172,8 +172,6 @@
ifneq ($(call check-jvm-feature, shenandoahgc), true)
JVM_CFLAGS_FEATURES += -DINCLUDE_SHENANDOAHGC=0
JVM_EXCLUDE_PATTERNS += gc/shenandoah
-else
- JVM_CFLAGS_FEATURES += -DSUPPORT_BARRIER_ON_PRIMITIVES -DSUPPORT_NOT_TO_SPACE_INVARIANT
endif
ifneq ($(call check-jvm-feature, jfr), true)
--- a/make/test/JtregNativeJdk.gmk Wed Apr 10 10:32:43 2019 +0530
+++ b/make/test/JtregNativeJdk.gmk Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2019, 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
@@ -61,6 +61,7 @@
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := $(WIN_LIB_JAVA)
WIN_LIB_JLI := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := $(WIN_LIB_JLI)
+ BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib
else
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava
BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava
@@ -70,6 +71,7 @@
BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava -lsocket -lnsl
endif
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := -ljli
+ BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := -ljvm
endif
ifeq ($(call isTargetOs, macosx), true)
--- a/src/hotspot/cpu/aarch64/aarch64.ad Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Wed Apr 10 10:46:53 2019 +0530
@@ -3932,7 +3932,8 @@
operand immL_bitmask()
%{
- predicate(((n->get_long() & 0xc000000000000000l) == 0)
+ predicate((n->get_long() != 0)
+ && ((n->get_long() & 0xc000000000000000l) == 0)
&& is_power_of_2(n->get_long() + 1));
match(ConL);
@@ -3943,7 +3944,8 @@
operand immI_bitmask()
%{
- predicate(((n->get_int() & 0xc0000000) == 0)
+ predicate((n->get_int() != 0)
+ && ((n->get_int() & 0xc0000000) == 0)
&& is_power_of_2(n->get_int() + 1));
match(ConI);
@@ -11432,11 +11434,13 @@
instruct ubfxwI(iRegINoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
%{
match(Set dst (AndI (URShiftI src rshift) mask));
+ // Make sure we are not going to exceed what ubfxw can do.
+ predicate((exact_log2(n->in(2)->get_int() + 1) + (n->in(1)->in(2)->get_int() & 31)) <= (31 + 1));
ins_cost(INSN_COST);
format %{ "ubfxw $dst, $src, $rshift, $mask" %}
ins_encode %{
- int rshift = $rshift$$constant;
+ int rshift = $rshift$$constant & 31;
long mask = $mask$$constant;
int width = exact_log2(mask+1);
__ ubfxw(as_Register($dst$$reg),
@@ -11447,13 +11451,15 @@
instruct ubfxL(iRegLNoSp dst, iRegL src, immI rshift, immL_bitmask mask)
%{
match(Set dst (AndL (URShiftL src rshift) mask));
+ // Make sure we are not going to exceed what ubfx can do.
+ predicate((exact_log2_long(n->in(2)->get_long() + 1) + (n->in(1)->in(2)->get_int() & 63)) <= (63 + 1));
ins_cost(INSN_COST);
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
- int rshift = $rshift$$constant;
+ int rshift = $rshift$$constant & 63;
long mask = $mask$$constant;
- int width = exact_log2(mask+1);
+ int width = exact_log2_long(mask+1);
__ ubfx(as_Register($dst$$reg),
as_Register($src$$reg), rshift, width);
%}
@@ -11465,11 +11471,13 @@
instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
%{
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
+ // Make sure we are not going to exceed what ubfxw can do.
+ predicate((exact_log2(n->in(1)->in(2)->get_int() + 1) + (n->in(1)->in(1)->in(2)->get_int() & 31)) <= (31 + 1));
ins_cost(INSN_COST * 2);
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
- int rshift = $rshift$$constant;
+ int rshift = $rshift$$constant & 31;
long mask = $mask$$constant;
int width = exact_log2(mask+1);
__ ubfx(as_Register($dst$$reg),
@@ -11510,7 +11518,7 @@
ins_encode %{
int lshift = $lshift$$constant;
long mask = $mask$$constant;
- int width = exact_log2(mask+1);
+ int width = exact_log2_long(mask+1);
__ ubfiz(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width);
%}
--- a/src/hotspot/cpu/aarch64/aarch64_ad.m4 Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/aarch64_ad.m4 Wed Apr 10 10:46:53 2019 +0530
@@ -181,31 +181,35 @@
`instruct $3$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI rshift, imm$1_bitmask mask)
%{
match(Set dst (And$1 ($2$1 src rshift) mask));
+ // Make sure we are not going to exceed what $3 can do.
+ predicate((exact_log2$6(n->in(2)->get_$5() + 1) + (n->in(1)->in(2)->get_int() & $4)) <= ($4 + 1));
ins_cost(INSN_COST);
format %{ "$3 $dst, $src, $rshift, $mask" %}
ins_encode %{
- int rshift = $rshift$$constant;
+ int rshift = $rshift$$constant & $4;
long mask = $mask$$constant;
- int width = exact_log2(mask+1);
+ int width = exact_log2$6(mask+1);
__ $3(as_Register($dst$$reg),
as_Register($src$$reg), rshift, width);
%}
ins_pipe(ialu_reg_shift);
%}')
-BFX_INSN(I,URShift,ubfxw)
-BFX_INSN(L,URShift,ubfx)
+BFX_INSN(I, URShift, ubfxw, 31, int)
+BFX_INSN(L, URShift, ubfx, 63, long, _long)
// We can use ubfx when extending an And with a mask when we know mask
// is positive. We know that because immI_bitmask guarantees it.
instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
%{
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
+ // Make sure we are not going to exceed what ubfxw can do.
+ predicate((exact_log2(n->in(1)->in(2)->get_int() + 1) + (n->in(1)->in(1)->in(2)->get_int() & 31)) <= (31 + 1));
ins_cost(INSN_COST * 2);
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
- int rshift = $rshift$$constant;
+ int rshift = $rshift$$constant & 31;
long mask = $mask$$constant;
int width = exact_log2(mask+1);
__ ubfx(as_Register($dst$$reg),
@@ -228,7 +232,7 @@
ins_encode %{
int lshift = $lshift$$constant;
long mask = $mask$$constant;
- int width = exact_log2(mask+1);
+ int width = exact_log2$5(mask+1);
__ $2(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width);
%}
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -1211,8 +1211,8 @@
/* The size bit is in bit 30, not 31 */
sz = (operand_size)(sz == word ? 0b00:0b01);
}
- f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21);
- rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0);
+ f(sz, 31, 30), f(0b001000, 29, 24), f(not_pair ? 1 : 0, 23), f(a, 22), f(1, 21);
+ zrf(Rs, 16), f(r, 15), f(0b11111, 14, 10), srf(Rn, 5), zrf(Rt, 0);
}
// CAS
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -34,6 +34,7 @@
#include "c1/c1_ValueStack.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
+#include "code/compiledIC.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/collectedHeap.hpp"
@@ -2063,11 +2064,10 @@
int start = __ offset();
__ relocate(static_stub_Relocation::spec(call_pc));
- __ mov_metadata(rmethod, (Metadata*)NULL);
- __ movptr(rscratch1, 0);
- __ br(rscratch1);
-
- assert(__ offset() - start <= call_stub_size(), "stub too big");
+ __ emit_static_call_stub();
+
+ assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
+ <= call_stub_size(), "stub too big");
__ end_a_stub();
}
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -69,7 +69,9 @@
void deoptimize_trap(CodeEmitInfo *info);
enum {
- _call_stub_size = 12 * NativeInstruction::instruction_size,
+ // call stub: CompiledStaticCall::to_interp_stub_size() +
+ // CompiledStaticCall::to_trampoline_stub_size()
+ _call_stub_size = 13 * NativeInstruction::instruction_size,
_call_aot_stub_size = 0,
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
_deopt_handler_size = 7 * NativeInstruction::instruction_size
--- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -61,14 +61,14 @@
// Don't create a Metadata reloc if we're generating immutable PIC.
if (cbuf.immutable_PIC()) {
__ movptr(rmethod, 0);
- } else {
- __ mov_metadata(rmethod, (Metadata*)NULL);
+ __ movptr(rscratch1, 0);
+ __ br(rscratch1);
+
+ } else
+#endif
+ {
+ __ emit_static_call_stub();
}
-#else
- __ mov_metadata(rmethod, (Metadata*)NULL);
-#endif
- __ movptr(rscratch1, 0);
- __ br(rscratch1);
assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big");
__ end_a_stub();
@@ -77,7 +77,8 @@
#undef __
int CompiledStaticCall::to_interp_stub_size() {
- return 7 * NativeInstruction::instruction_size;
+ // isb; movk; movz; movz; movk; movz; movz; br
+ return 8 * NativeInstruction::instruction_size;
}
int CompiledStaticCall::to_trampoline_stub_size() {
@@ -159,7 +160,8 @@
}
// Creation also verifies the object.
- NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
+ NativeMovConstReg* method_holder
+ = nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
#ifndef PRODUCT
NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
@@ -184,7 +186,8 @@
assert(stub != NULL, "stub not found");
assert(CompiledICLocker::is_safe(stub), "mt unsafe call");
// Creation also verifies the object.
- NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
+ NativeMovConstReg* method_holder
+ = nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
method_holder->set_data(0);
}
@@ -201,8 +204,9 @@
address stub = find_stub(false /* is_aot */);
assert(stub != NULL, "no stub found for static call");
// Creation also verifies the object.
- NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
+ NativeMovConstReg* method_holder
+ = nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
// Verify state.
assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -559,7 +559,7 @@
// validate constantPoolCache*
ConstantPoolCache* cp = *interpreter_frame_cache_addr();
- if (cp == NULL || !cp->is_metaspace_object()) return false;
+ if (MetaspaceObj::is_valid(cp) == false) return false;
// validate locals
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -40,7 +40,7 @@
#define __ masm->
-address ShenandoahBarrierSetAssembler::_shenandoah_wb = NULL;
+address ShenandoahBarrierSetAssembler::_shenandoah_lrb = NULL;
void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
Register addr, Register count, RegSet saved_regs) {
@@ -87,6 +87,16 @@
void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
Register start, Register count, Register scratch, RegSet saved_regs) {
if (is_oop) {
+ Label done;
+
+ // Avoid calling runtime if count == 0
+ __ cbz(count, done);
+
+ // Is updating references?
+ Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+ __ ldrb(rscratch1, gc_state);
+ __ tbz(rscratch1, ShenandoahHeap::UPDATEREFS_BITPOS, done);
+
__ push(saved_regs, sp);
assert_different_registers(start, count, scratch);
assert_different_registers(c_rarg0, count);
@@ -94,6 +104,8 @@
__ mov(c_rarg1, count);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_post_entry), 2);
__ pop(saved_regs, sp);
+
+ __ bind(done);
}
}
@@ -198,60 +210,31 @@
__ bind(done);
}
-void ShenandoahBarrierSetAssembler::read_barrier(MacroAssembler* masm, Register dst) {
- if (ShenandoahReadBarrier) {
- read_barrier_impl(masm, dst);
- }
-}
-
-void ShenandoahBarrierSetAssembler::read_barrier_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier || ShenandoahCASBarrier), "should be enabled");
+void ShenandoahBarrierSetAssembler::resolve_forward_pointer(MacroAssembler* masm, Register dst) {
+ assert(ShenandoahLoadRefBarrier || ShenandoahCASBarrier, "Should be enabled");
Label is_null;
__ cbz(dst, is_null);
- read_barrier_not_null_impl(masm, dst);
+ resolve_forward_pointer_not_null(masm, dst);
__ bind(is_null);
}
-void ShenandoahBarrierSetAssembler::read_barrier_not_null(MacroAssembler* masm, Register dst) {
- if (ShenandoahReadBarrier) {
- read_barrier_not_null_impl(masm, dst);
- }
-}
-
-
-void ShenandoahBarrierSetAssembler::read_barrier_not_null_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier || ShenandoahCASBarrier), "should be enabled");
+// IMPORTANT: This must preserve all registers, even rscratch1 and rscratch2.
+void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst) {
+ assert(ShenandoahLoadRefBarrier || ShenandoahCASBarrier, "Should be enabled");
__ ldr(dst, Address(dst, ShenandoahBrooksPointer::byte_offset()));
}
-void ShenandoahBarrierSetAssembler::write_barrier(MacroAssembler* masm, Register dst) {
- if (ShenandoahWriteBarrier) {
- write_barrier_impl(masm, dst);
- }
-}
-
-void ShenandoahBarrierSetAssembler::write_barrier_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
- assert(dst != rscratch1, "need rscratch1");
+void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, Register dst, Register tmp) {
+ assert(ShenandoahLoadRefBarrier, "Should be enabled");
assert(dst != rscratch2, "need rscratch2");
Label done;
-
+ __ enter();
Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
- __ ldrb(rscratch1, gc_state);
+ __ ldrb(rscratch2, gc_state);
// Check for heap stability
- __ mov(rscratch2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL);
- __ tst(rscratch1, rscratch2);
- __ br(Assembler::EQ, done);
-
- // Heap is unstable, need to perform the read-barrier even if WB is inactive
- __ ldr(dst, Address(dst, ShenandoahBrooksPointer::byte_offset()));
-
- // Check for evacuation-in-progress and jump to WB slow-path if needed
- __ mov(rscratch2, ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL);
- __ tst(rscratch1, rscratch2);
- __ br(Assembler::EQ, done);
+ __ tbz(rscratch2, ShenandoahHeap::HAS_FORWARDED_BITPOS, done);
RegSet to_save = RegSet::of(r0);
if (dst != r0) {
@@ -259,7 +242,7 @@
__ mov(r0, dst);
}
- __ far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_wb())));
+ __ far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_lrb())));
if (dst != r0) {
__ mov(dst, r0);
@@ -267,14 +250,11 @@
}
__ bind(done);
+ __ leave();
}
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
if (ShenandoahStoreValEnqueueBarrier) {
- Label is_null;
- __ cbz(dst, is_null);
- write_barrier_impl(masm, dst);
- __ bind(is_null);
// Save possibly live regs.
RegSet live_regs = RegSet::range(r0, r4) - dst;
__ push(live_regs, sp);
@@ -286,44 +266,45 @@
__ ldrd(v0, __ post(sp, 2 * wordSize));
__ pop(live_regs, sp);
}
- if (ShenandoahStoreValReadBarrier) {
- read_barrier_impl(masm, dst);
+}
+
+void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, Register dst, Register tmp) {
+ if (ShenandoahLoadRefBarrier) {
+ Label is_null;
+ __ cbz(dst, is_null);
+ load_reference_barrier_not_null(masm, dst, tmp);
+ __ bind(is_null);
}
}
void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register dst, Address src, Register tmp1, Register tmp_thread) {
bool on_oop = type == T_OBJECT || type == T_ARRAY;
- bool in_heap = (decorators & IN_HEAP) != 0;
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
bool on_reference = on_weak || on_phantom;
- if (in_heap) {
- read_barrier_not_null(masm, src.base());
- }
+ BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
+ if (on_oop) {
+ load_reference_barrier(masm, dst, tmp1);
- BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
- if (ShenandoahKeepAliveBarrier && on_oop && on_reference) {
- __ enter();
- satb_write_barrier_pre(masm /* masm */,
- noreg /* obj */,
- dst /* pre_val */,
- rthread /* thread */,
- tmp1 /* tmp */,
- true /* tosca_live */,
- true /* expand_call */);
- __ leave();
+ if (ShenandoahKeepAliveBarrier && on_reference) {
+ __ enter();
+ satb_write_barrier_pre(masm /* masm */,
+ noreg /* obj */,
+ dst /* pre_val */,
+ rthread /* thread */,
+ tmp1 /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ __ leave();
+ }
}
}
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) {
bool on_oop = type == T_OBJECT || type == T_ARRAY;
- bool in_heap = (decorators & IN_HEAP) != 0;
- if (in_heap) {
- write_barrier(masm, dst.base());
- }
if (!on_oop) {
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
return;
@@ -361,21 +342,6 @@
}
-void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, Register op1, Register op2) {
- __ cmp(op1, op2);
- if (ShenandoahAcmpBarrier) {
- Label done;
- __ br(Assembler::EQ, done);
- // The object may have been evacuated, but we won't see it without a
- // membar here.
- __ membar(Assembler::LoadStore| Assembler::LoadLoad);
- read_barrier(masm, op1);
- read_barrier(masm, op2);
- __ cmp(op1, op2);
- __ bind(done);
- }
-}
-
void ShenandoahBarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
@@ -410,27 +376,6 @@
}
}
-void ShenandoahBarrierSetAssembler::resolve(MacroAssembler* masm, DecoratorSet decorators, Register obj) {
- bool oop_not_null = (decorators & IS_NOT_NULL) != 0;
- bool is_write = (decorators & ACCESS_WRITE) != 0;
- if (is_write) {
- if (oop_not_null) {
- write_barrier(masm, obj);
- } else {
- Label done;
- __ cbz(obj, done);
- write_barrier(masm, obj);
- __ bind(done);
- }
- } else {
- if (oop_not_null) {
- read_barrier_not_null(masm, obj);
- } else {
- read_barrier(masm, obj);
- }
- }
-}
-
void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val,
bool acquire, bool release, bool weak, bool is_cae,
Register result) {
@@ -469,8 +414,8 @@
__ decode_heap_oop(tmp1, tmp1);
__ decode_heap_oop(tmp2, tmp2);
}
- read_barrier_impl(masm, tmp1);
- read_barrier_impl(masm, tmp2);
+ resolve_forward_pointer(masm, tmp1);
+ resolve_forward_pointer(masm, tmp2);
__ cmp(tmp1, tmp2);
// Retry with expected now being the value we just loaded from addr.
__ br(Assembler::EQ, retry);
@@ -515,7 +460,7 @@
__ b(*stub->continuation());
}
-void ShenandoahBarrierSetAssembler::gen_write_barrier_stub(LIR_Assembler* ce, ShenandoahWriteBarrierStub* stub) {
+void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
@@ -532,7 +477,7 @@
__ cbz(res, done);
}
- write_barrier(ce->masm(), res);
+ load_reference_barrier_not_null(ce->masm(), res, rscratch1);
__ bind(done);
__ b(*stub->continuation());
@@ -592,14 +537,14 @@
#endif // COMPILER1
-address ShenandoahBarrierSetAssembler::shenandoah_wb() {
- assert(_shenandoah_wb != NULL, "need write barrier stub");
- return _shenandoah_wb;
+address ShenandoahBarrierSetAssembler::shenandoah_lrb() {
+ assert(_shenandoah_lrb != NULL, "need load reference barrier stub");
+ return _shenandoah_lrb;
}
#define __ cgen->assembler()->
-// Shenandoah write barrier.
+// Shenandoah load reference barrier.
//
// Input:
// r0: OOP to evacuate. Not null.
@@ -608,13 +553,13 @@
// r0: Pointer to evacuated OOP.
//
// Trash rscratch1, rscratch2. Preserve everything else.
-address ShenandoahBarrierSetAssembler::generate_shenandoah_wb(StubCodeGenerator* cgen) {
+address ShenandoahBarrierSetAssembler::generate_shenandoah_lrb(StubCodeGenerator* cgen) {
__ align(6);
- StubCodeMark mark(cgen, "StubRoutines", "shenandoah_wb");
+ StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb");
address start = __ pc();
- Label work;
+ Label work, done;
__ mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
__ lsr(rscratch1, r0, ShenandoahHeapRegion::region_size_bytes_shift_jint());
__ ldrb(rscratch2, Address(rscratch2, rscratch1));
@@ -622,19 +567,23 @@
__ ret(lr);
__ bind(work);
- Register obj = r0;
+ __ mov(rscratch2, r0);
+ resolve_forward_pointer_not_null(cgen->assembler(), r0);
+ __ cmp(rscratch2, r0);
+ __ br(Assembler::NE, done);
__ enter(); // required for proper stackwalking of RuntimeStub frame
__ push_call_clobbered_registers();
- __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT));
+ __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_JRT));
__ blrt(lr, 1, 0, MacroAssembler::ret_type_integral);
- __ mov(rscratch1, obj);
+ __ mov(rscratch1, r0);
__ pop_call_clobbered_registers();
- __ mov(obj, rscratch1);
+ __ mov(r0, rscratch1);
__ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ bind(done);
__ ret(lr);
return start;
@@ -643,12 +592,12 @@
#undef __
void ShenandoahBarrierSetAssembler::barrier_stubs_init() {
- if (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier) {
+ if (ShenandoahLoadRefBarrier) {
int stub_code_size = 2048;
ResourceMark rm;
BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size);
CodeBuffer buf(bb);
StubCodeGenerator cgen(&buf);
- _shenandoah_wb = generate_shenandoah_wb(&cgen);
+ _shenandoah_lrb = generate_shenandoah_lrb(&cgen);
}
}
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -29,7 +29,7 @@
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
-class ShenandoahWriteBarrierStub;
+class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
class StubCodeGenerator;
#endif
@@ -37,7 +37,7 @@
class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
private:
- static address _shenandoah_wb;
+ static address _shenandoah_lrb;
void satb_write_barrier_pre(MacroAssembler* masm,
Register obj,
@@ -54,24 +54,21 @@
bool tosca_live,
bool expand_call);
- void read_barrier(MacroAssembler* masm, Register dst);
- void read_barrier_impl(MacroAssembler* masm, Register dst);
- void read_barrier_not_null(MacroAssembler* masm, Register dst);
- void read_barrier_not_null_impl(MacroAssembler* masm, Register dst);
- void write_barrier(MacroAssembler* masm, Register dst);
- void write_barrier_impl(MacroAssembler* masm, Register dst);
- void asm_acmp_barrier(MacroAssembler* masm, Register op1, Register op2);
+ void resolve_forward_pointer(MacroAssembler* masm, Register dst);
+ void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst);
+ void load_reference_barrier(MacroAssembler* masm, Register dst, Register tmp);
+ void load_reference_barrier_not_null(MacroAssembler* masm, Register dst, Register tmp);
- address generate_shenandoah_wb(StubCodeGenerator* cgen);
+ address generate_shenandoah_lrb(StubCodeGenerator* cgen);
public:
- static address shenandoah_wb();
+ static address shenandoah_lrb();
void storeval_barrier(MacroAssembler* masm, Register dst, Register tmp);
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
- void gen_write_barrier_stub(LIR_Assembler* ce, ShenandoahWriteBarrierStub* stub);
+ void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
#endif
@@ -83,8 +80,6 @@
Register dst, Address src, Register tmp1, Register tmp_thread);
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
- virtual void obj_equals(MacroAssembler* masm, Register src1, Register src2);
- virtual void resolve(MacroAssembler* masm, DecoratorSet decorators, Register obj);
virtual void tlab_allocate(MacroAssembler* masm, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetC1_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetC1_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -99,6 +99,7 @@
__ xchg(access.resolved_addr(), value_opr, result, tmp);
if (access.is_oop()) {
+ result = load_reference_barrier(access.gen(), result, access.access_emit_info(), true);
if (ShenandoahSATBBarrier) {
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
result /* pre_val */);
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad Wed Apr 10 10:46:53 2019 +0530
@@ -45,18 +45,6 @@
%}
%}
-instruct shenandoahRB(iRegPNoSp dst, iRegP src, rFlagsReg cr) %{
- match(Set dst (ShenandoahReadBarrier src));
- format %{ "shenandoah_rb $dst,$src" %}
- ins_encode %{
- Register s = $src$$Register;
- Register d = $dst$$Register;
- __ ldr(d, Address(s, ShenandoahBrooksPointer::byte_offset()));
- %}
- ins_pipe(pipe_class_memory);
-%}
-
-
instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -812,6 +812,18 @@
return stub_start_addr;
}
+void MacroAssembler::emit_static_call_stub() {
+ // CompiledDirectStaticCall::set_to_interpreted knows the
+ // exact layout of this stub.
+
+ isb();
+ mov_metadata(rmethod, (Metadata*)NULL);
+
+ // Jump to the entry point of the i2c stub.
+ movptr(rscratch1, 0);
+ br(rscratch1);
+}
+
void MacroAssembler::c2bool(Register x) {
// implements x == 0 ? 0 : 1
// note: must only look at least-significant byte of x
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -607,6 +607,7 @@
static int patch_narrow_klass(address insn_addr, narrowKlass n);
address emit_trampoline_stub(int insts_call_instruction_offset, address target);
+ void emit_static_call_stub();
// The following 4 methods return the offset of the appropriate move instruction
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -232,7 +232,11 @@
//-------------------------------------------------------------------
void NativeMovConstReg::verify() {
- // make sure code pattern is actually mov reg64, imm64 instructions
+ if (! (nativeInstruction_at(instruction_address())->is_movz() ||
+ is_adrp_at(instruction_address()) ||
+ is_ldr_literal_at(instruction_address())) ) {
+ fatal("should be MOVZ or ADRP or LDR (literal)");
+ }
}
--- a/src/hotspot/cpu/arm/frame_arm.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/arm/frame_arm.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -494,7 +494,7 @@
// validate ConstantPoolCache*
ConstantPoolCache* cp = *interpreter_frame_cache_addr();
- if (cp == NULL || !cp->is_metaspace_object()) return false;
+ if (MetaspaceObj::is_valid(cp) == false) return false;
// validate locals
--- a/src/hotspot/cpu/sparc/frame_sparc.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/sparc/frame_sparc.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -665,7 +665,7 @@
// validate ConstantPoolCache*
ConstantPoolCache* cp = *interpreter_frame_cache_addr();
- if (cp == NULL || !cp->is_metaspace_object()) return false;
+ if (MetaspaceObj::is_valid(cp) == false) return false;
// validate locals
--- a/src/hotspot/cpu/x86/frame_x86.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/frame_x86.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -546,7 +546,7 @@
// validate ConstantPoolCache*
ConstantPoolCache* cp = *interpreter_frame_cache_addr();
- if (cp == NULL || !cp->is_metaspace_object()) return false;
+ if (MetaspaceObj::is_valid(cp) == false) return false;
// validate locals
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -41,7 +41,7 @@
#define __ masm->
-address ShenandoahBarrierSetAssembler::_shenandoah_wb = NULL;
+address ShenandoahBarrierSetAssembler::_shenandoah_lrb = NULL;
void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register src, Register dst, Register count) {
@@ -138,6 +138,22 @@
}
#endif
+ Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+#ifndef _LP64
+ __ push(thread);
+ __ get_thread(thread);
+#endif
+
+ // Short-circuit if count == 0.
+ Label done;
+ __ testptr(count, count);
+ __ jcc(Assembler::zero, done);
+
+ // Skip runtime call if no forwarded objects.
+ Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+ __ testb(gc_state, ShenandoahHeap::UPDATEREFS);
+ __ jcc(Assembler::zero, done);
+
__ pusha(); // push registers (overkill)
#ifdef _LP64
if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
@@ -155,6 +171,9 @@
dst, count);
#endif
__ popa();
+
+ __ bind(done);
+ NOT_LP64(__ pop(thread);)
}
}
@@ -293,41 +312,23 @@
__ bind(done);
}
-void ShenandoahBarrierSetAssembler::read_barrier(MacroAssembler* masm, Register dst) {
- if (ShenandoahReadBarrier) {
- read_barrier_impl(masm, dst);
- }
-}
-
-void ShenandoahBarrierSetAssembler::read_barrier_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier || ShenandoahCASBarrier), "should be enabled");
+void ShenandoahBarrierSetAssembler::resolve_forward_pointer(MacroAssembler* masm, Register dst) {
+ assert(ShenandoahCASBarrier, "should be enabled");
Label is_null;
__ testptr(dst, dst);
__ jcc(Assembler::zero, is_null);
- read_barrier_not_null_impl(masm, dst);
+ resolve_forward_pointer_not_null(masm, dst);
__ bind(is_null);
}
-void ShenandoahBarrierSetAssembler::read_barrier_not_null(MacroAssembler* masm, Register dst) {
- if (ShenandoahReadBarrier) {
- read_barrier_not_null_impl(masm, dst);
- }
-}
-
-void ShenandoahBarrierSetAssembler::read_barrier_not_null_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier || ShenandoahCASBarrier), "should be enabled");
+void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst) {
+ assert(ShenandoahCASBarrier || ShenandoahLoadRefBarrier, "should be enabled");
__ movptr(dst, Address(dst, ShenandoahBrooksPointer::byte_offset()));
}
-void ShenandoahBarrierSetAssembler::write_barrier(MacroAssembler* masm, Register dst) {
- if (ShenandoahWriteBarrier) {
- write_barrier_impl(masm, dst);
- }
-}
-
-void ShenandoahBarrierSetAssembler::write_barrier_impl(MacroAssembler* masm, Register dst) {
- assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
+void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, Register dst) {
+ assert(ShenandoahLoadRefBarrier, "Should be enabled");
#ifdef _LP64
Label done;
@@ -335,8 +336,8 @@
__ testb(gc_state, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL);
__ jccb(Assembler::zero, done);
- // Heap is unstable, need to perform the read-barrier even if WB is inactive
- read_barrier_not_null(masm, dst);
+ // Heap is unstable, need to perform the resolve even if LRB is inactive
+ resolve_forward_pointer_not_null(masm, dst);
__ testb(gc_state, ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL);
__ jccb(Assembler::zero, done);
@@ -345,7 +346,7 @@
__ xchgptr(dst, rax); // Move obj into rax and save rax into obj.
}
- __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_wb())));
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_lrb())));
if (dst != rax) {
__ xchgptr(rax, dst); // Swap back obj with rax.
@@ -358,24 +359,18 @@
}
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
- if (ShenandoahStoreValReadBarrier || ShenandoahStoreValEnqueueBarrier) {
+ if (ShenandoahStoreValEnqueueBarrier) {
storeval_barrier_impl(masm, dst, tmp);
}
}
void ShenandoahBarrierSetAssembler::storeval_barrier_impl(MacroAssembler* masm, Register dst, Register tmp) {
- assert(UseShenandoahGC && (ShenandoahStoreValReadBarrier || ShenandoahStoreValEnqueueBarrier), "should be enabled");
+ assert(ShenandoahStoreValEnqueueBarrier, "should be enabled");
if (dst == noreg) return;
#ifdef _LP64
if (ShenandoahStoreValEnqueueBarrier) {
- Label is_null;
- __ testptr(dst, dst);
- __ jcc(Assembler::zero, is_null);
- write_barrier_impl(masm, dst);
- __ bind(is_null);
-
// The set of registers to be saved+restored is the same as in the write-barrier above.
// Those are the commonly used registers in the interpreter.
__ pusha();
@@ -389,50 +384,54 @@
//__ pop_callee_saved_registers();
__ popa();
}
- if (ShenandoahStoreValReadBarrier) {
- read_barrier_impl(masm, dst);
- }
#else
Unimplemented();
#endif
}
+void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, Register dst) {
+ if (ShenandoahLoadRefBarrier) {
+ Label done;
+ __ testptr(dst, dst);
+ __ jcc(Assembler::zero, done);
+ load_reference_barrier_not_null(masm, dst);
+ __ bind(done);
+ }
+}
+
void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register dst, Address src, Register tmp1, Register tmp_thread) {
bool on_oop = type == T_OBJECT || type == T_ARRAY;
- bool in_heap = (decorators & IN_HEAP) != 0;
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
bool on_reference = on_weak || on_phantom;
- if (in_heap) {
- read_barrier_not_null(masm, src.base());
- }
- BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
- if (ShenandoahKeepAliveBarrier && on_oop && on_reference) {
- const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
- NOT_LP64(__ get_thread(thread));
+ BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
+ if (on_oop) {
+ load_reference_barrier(masm, dst);
- // Generate the SATB pre-barrier code to log the value of
- // the referent field in an SATB buffer.
- shenandoah_write_barrier_pre(masm /* masm */,
- noreg /* obj */,
- dst /* pre_val */,
- thread /* thread */,
- tmp1 /* tmp */,
- true /* tosca_live */,
- true /* expand_call */);
+ if (ShenandoahKeepAliveBarrier && on_reference) {
+ const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
+ NOT_LP64(__ get_thread(thread));
+ // Generate the SATB pre-barrier code to log the value of
+ // the referent field in an SATB buffer.
+ shenandoah_write_barrier_pre(masm /* masm */,
+ noreg /* obj */,
+ dst /* pre_val */,
+ thread /* thread */,
+ tmp1 /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ }
}
}
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) {
+ bool on_oop = type == T_OBJECT || type == T_ARRAY;
bool in_heap = (decorators & IN_HEAP) != 0;
bool as_normal = (decorators & AS_NORMAL) != 0;
- if (in_heap) {
- write_barrier(masm, dst.base());
- }
- if (type == T_OBJECT || type == T_ARRAY) {
+ if (on_oop && in_heap) {
bool needs_pre_barrier = as_normal;
Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
@@ -475,44 +474,6 @@
}
}
-#ifndef _LP64
-void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm,
- Address obj1, jobject obj2) {
- Unimplemented();
-}
-
-void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm,
- Register obj1, jobject obj2) {
- Unimplemented();
-}
-#endif
-
-
-void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, Register op1, Register op2) {
- __ cmpptr(op1, op2);
- if (ShenandoahAcmpBarrier) {
- Label done;
- __ jccb(Assembler::equal, done);
- read_barrier(masm, op1);
- read_barrier(masm, op2);
- __ cmpptr(op1, op2);
- __ bind(done);
- }
-}
-
-void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, Register src1, Address src2) {
- __ cmpptr(src1, src2);
- if (ShenandoahAcmpBarrier) {
- Label done;
- __ jccb(Assembler::equal, done);
- __ movptr(rscratch2, src2);
- read_barrier(masm, src1);
- read_barrier(masm, rscratch2);
- __ cmpptr(src1, rscratch2);
- __ bind(done);
- }
-}
-
void ShenandoahBarrierSetAssembler::tlab_allocate(MacroAssembler* masm,
Register thread, Register obj,
Register var_size_in_bytes,
@@ -562,28 +523,6 @@
__ verify_tlab();
}
-void ShenandoahBarrierSetAssembler::resolve(MacroAssembler* masm, DecoratorSet decorators, Register obj) {
- bool oop_not_null = (decorators & IS_NOT_NULL) != 0;
- bool is_write = (decorators & ACCESS_WRITE) != 0;
- if (is_write) {
- if (oop_not_null) {
- write_barrier(masm, obj);
- } else {
- Label done;
- __ testptr(obj, obj);
- __ jcc(Assembler::zero, done);
- write_barrier(masm, obj);
- __ bind(done);
- }
- } else {
- if (oop_not_null) {
- read_barrier_not_null(masm, obj);
- } else {
- read_barrier(masm, obj);
- }
- }
-}
-
// Special Shenandoah CAS implementation that handles false negatives
// due to concurrent evacuation.
#ifndef _LP64
@@ -622,14 +561,14 @@
// Step 2. CAS had failed. This may be a false negative.
//
// The trouble comes when we compare the to-space pointer with the from-space
- // pointer to the same object. To resolve this, it will suffice to read both
- // oldval and the value from memory through the read barriers -- this will give
- // both to-space pointers. If they mismatch, then it was a legitimate failure.
+ // pointer to the same object. To resolve this, it will suffice to resolve both
+ // oldval and the value from memory -- this will give both to-space pointers.
+ // If they mismatch, then it was a legitimate failure.
//
if (UseCompressedOops) {
__ decode_heap_oop(tmp1);
}
- read_barrier_impl(masm, tmp1);
+ resolve_forward_pointer(masm, tmp1);
if (UseCompressedOops) {
__ movl(tmp2, oldval);
@@ -637,7 +576,7 @@
} else {
__ movptr(tmp2, oldval);
}
- read_barrier_impl(masm, tmp2);
+ resolve_forward_pointer(masm, tmp2);
__ cmpptr(tmp1, tmp2);
__ jcc(Assembler::notEqual, done, true);
@@ -646,8 +585,8 @@
//
// Corner case: it may happen that somebody stored the from-space pointer
// to memory while we were preparing for retry. Therefore, we can fail again
- // on retry, and so need to do this in loop, always re-reading the failure
- // witness through the read barrier.
+ // on retry, and so need to do this in loop, always resolving the failure
+ // witness.
__ bind(retry);
if (os::is_MP()) __ lock();
if (UseCompressedOops) {
@@ -663,7 +602,7 @@
} else {
__ movptr(tmp2, oldval);
}
- read_barrier_impl(masm, tmp2);
+ resolve_forward_pointer(masm, tmp2);
__ cmpptr(tmp1, tmp2);
__ jcc(Assembler::equal, retry, true);
@@ -811,7 +750,7 @@
}
-void ShenandoahBarrierSetAssembler::gen_write_barrier_stub(LIR_Assembler* ce, ShenandoahWriteBarrierStub* stub) {
+void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
__ bind(*stub->entry());
Label done;
@@ -828,7 +767,7 @@
__ jcc(Assembler::zero, done);
}
- write_barrier(ce->masm(), res);
+ load_reference_barrier_not_null(ce->masm(), res);
__ bind(done);
__ jmp(*stub->continuation());
@@ -898,16 +837,16 @@
#endif // COMPILER1
-address ShenandoahBarrierSetAssembler::shenandoah_wb() {
- assert(_shenandoah_wb != NULL, "need write barrier stub");
- return _shenandoah_wb;
+address ShenandoahBarrierSetAssembler::shenandoah_lrb() {
+ assert(_shenandoah_lrb != NULL, "need load reference barrier stub");
+ return _shenandoah_lrb;
}
#define __ cgen->assembler()->
-address ShenandoahBarrierSetAssembler::generate_shenandoah_wb(StubCodeGenerator* cgen) {
+address ShenandoahBarrierSetAssembler::generate_shenandoah_lrb(StubCodeGenerator* cgen) {
__ align(CodeEntryAlignment);
- StubCodeMark mark(cgen, "StubRoutines", "shenandoah_wb");
+ StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb");
address start = __ pc();
#ifdef _LP64
@@ -955,7 +894,7 @@
__ push(r15);
save_vector_registers(cgen->assembler());
__ movptr(rdi, rax);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT), rdi);
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_JRT), rdi);
restore_vector_registers(cgen->assembler());
__ pop(r15);
__ pop(r14);
@@ -982,12 +921,12 @@
#undef __
void ShenandoahBarrierSetAssembler::barrier_stubs_init() {
- if (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier) {
+ if (ShenandoahLoadRefBarrier) {
int stub_code_size = 4096;
ResourceMark rm;
BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size);
CodeBuffer buf(bb);
StubCodeGenerator cgen(&buf);
- _shenandoah_wb = generate_shenandoah_wb(&cgen);
+ _shenandoah_lrb = generate_shenandoah_lrb(&cgen);
}
}
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -29,7 +29,7 @@
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
-class ShenandoahWriteBarrierStub;
+class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
class StubCodeGenerator;
#endif
@@ -37,7 +37,7 @@
class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
private:
- static address _shenandoah_wb;
+ static address _shenandoah_lrb;
void satb_write_barrier_pre(MacroAssembler* masm,
Register obj,
@@ -55,32 +55,30 @@
bool tosca_live,
bool expand_call);
- void read_barrier(MacroAssembler* masm, Register dst);
- void read_barrier_impl(MacroAssembler* masm, Register dst);
+ void resolve_forward_pointer(MacroAssembler* masm, Register dst);
+ void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst);
- void read_barrier_not_null(MacroAssembler* masm, Register dst);
- void read_barrier_not_null_impl(MacroAssembler* masm, Register dst);
-
- void write_barrier(MacroAssembler* masm, Register dst);
- void write_barrier_impl(MacroAssembler* masm, Register dst);
+ void load_reference_barrier_not_null(MacroAssembler* masm, Register dst);
void storeval_barrier_impl(MacroAssembler* masm, Register dst, Register tmp);
- address generate_shenandoah_wb(StubCodeGenerator* cgen);
+ address generate_shenandoah_lrb(StubCodeGenerator* cgen);
void save_vector_registers(MacroAssembler* masm);
void restore_vector_registers(MacroAssembler* masm);
public:
- static address shenandoah_wb();
+ static address shenandoah_lrb();
void storeval_barrier(MacroAssembler* masm, Register dst, Register tmp);
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
- void gen_write_barrier_stub(LIR_Assembler* ce, ShenandoahWriteBarrierStub* stub);
+ void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
#endif
+ void load_reference_barrier(MacroAssembler* masm, Register dst);
+
void cmpxchg_oop(MacroAssembler* masm,
Register res, Address addr, Register oldval, Register newval,
bool exchange, Register tmp1, Register tmp2);
@@ -93,16 +91,6 @@
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
-#ifndef _LP64
- virtual void obj_equals(MacroAssembler* masm,
- Address obj1, jobject obj2);
- virtual void obj_equals(MacroAssembler* masm,
- Register obj1, jobject obj2);
-#endif
-
- virtual void obj_equals(MacroAssembler* masm, Register src1, Register src2);
- virtual void obj_equals(MacroAssembler* masm, Register src1, Address src2);
-
virtual void tlab_allocate(MacroAssembler* masm,
Register thread, Register obj,
Register var_size_in_bytes,
@@ -110,8 +98,6 @@
Register t1, Register t2,
Label& slow_case);
- virtual void resolve(MacroAssembler* masm, DecoratorSet decorators, Register obj);
-
virtual void barrier_stubs_init();
};
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -107,6 +107,7 @@
__ xchg(access.resolved_addr(), result, result, LIR_OprFact::illegalOpr);
if (access.is_oop()) {
+ result = load_reference_barrier(access.gen(), result, access.access_emit_info(), true);
if (ShenandoahSATBBarrier) {
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
result /* pre_val */);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoah_x86_64.ad Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoah_x86_64.ad Wed Apr 10 10:46:53 2019 +0530
@@ -23,47 +23,7 @@
source_hpp %{
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
-%}
-
-instruct shenandoahRB(rRegP dst, rRegP src, rFlagsReg cr) %{
- match(Set dst (ShenandoahReadBarrier src));
- effect(DEF dst, USE src);
- ins_cost(125); // XXX
- format %{ "shenandoah_rb $dst, $src" %}
- ins_encode %{
- Register d = $dst$$Register;
- Register s = $src$$Register;
- __ movptr(d, Address(s, ShenandoahBrooksPointer::byte_offset()));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct shenandoahRBNarrow(rRegP dst, rRegN src) %{
- predicate(UseCompressedOops && (Universe::narrow_oop_shift() == 0));
- match(Set dst (ShenandoahReadBarrier (DecodeN src)));
- effect(DEF dst, USE src);
- ins_cost(125); // XXX
- format %{ "shenandoah_rb $dst, $src" %}
- ins_encode %{
- Register d = $dst$$Register;
- Register s = $src$$Register;
- __ movptr(d, Address(r12, s, Address::times_1, ShenandoahBrooksPointer::byte_offset()));
- %}
- ins_pipe(ialu_reg_mem);
-%}
-
-instruct shenandoahRBNarrowShift(rRegP dst, rRegN src) %{
- predicate(UseCompressedOops && (Universe::narrow_oop_shift() == Address::times_8));
- match(Set dst (ShenandoahReadBarrier (DecodeN src)));
- effect(DEF dst, USE src);
- ins_cost(125); // XXX
- format %{ "shenandoah_rb $dst, $src" %}
- ins_encode %{
- Register d = $dst$$Register;
- Register s = $src$$Register;
- __ movptr(d, Address(r12, s, Address::times_8, ShenandoahBrooksPointer::byte_offset()));
- %}
- ins_pipe(ialu_reg_mem);
+#include "gc/shenandoah/c2/shenandoahSupport.hpp"
%}
instruct compareAndSwapP_shenandoah(rRegI res,
--- a/src/hotspot/cpu/x86/x86_32.ad Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/cpu/x86/x86_32.ad Wed Apr 10 10:46:53 2019 +0530
@@ -1309,7 +1309,7 @@
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation( NULL, ra_, true, NULL );
+ return MachNode::size(ra_);
}
--- a/src/hotspot/os/aix/os_perf_aix.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os/aix/os_perf_aix.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -336,20 +336,8 @@
fclose(fh);
if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read failed");
-#endif
return OS_ERR;
}
-
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
- userTicks, niceTicks, systemTicks, idleTicks,
- iowTicks, irqTicks, sirqTicks);
-#endif
-
pticks->used = userTicks + niceTicks;
pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
--- a/src/hotspot/os/bsd/os_bsd.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os/bsd/os_bsd.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1598,6 +1598,8 @@
}
void os::print_memory_info(outputStream* st) {
+ xsw_usage swap_usage;
+ size_t size = sizeof(swap_usage);
st->print("Memory:");
st->print(" %dk page", os::vm_page_size()>>10);
@@ -1606,6 +1608,16 @@
os::physical_memory() >> 10);
st->print("(" UINT64_FORMAT "k free)",
os::available_memory() >> 10);
+
+ if((sysctlbyname("vm.swapusage", &swap_usage, &size, NULL, 0) == 0) || (errno == ENOMEM)) {
+ if (size >= offset_of(xsw_usage, xsu_used)) {
+ st->print(", swap " UINT64_FORMAT "k",
+ ((julong) swap_usage.xsu_total) >> 10);
+ st->print("(" UINT64_FORMAT "k free)",
+ ((julong) swap_usage.xsu_avail) >> 10);
+ }
+ }
+
st->cr();
}
--- a/src/hotspot/os/linux/os_linux.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os/linux/os_linux.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -227,6 +227,82 @@
return phys_mem;
}
+static uint64_t initial_total_ticks = 0;
+static uint64_t initial_steal_ticks = 0;
+static bool has_initial_tick_info = false;
+
+static void next_line(FILE *f) {
+ int c;
+ do {
+ c = fgetc(f);
+ } while (c != '\n' && c != EOF);
+}
+
+bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu) {
+ FILE* fh;
+ uint64_t userTicks, niceTicks, systemTicks, idleTicks;
+ // since at least kernel 2.6 : iowait: time waiting for I/O to complete
+ // irq: time servicing interrupts; softirq: time servicing softirqs
+ uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
+ // steal (since kernel 2.6.11): time spent in other OS when running in a virtualized environment
+ uint64_t stealTicks = 0;
+ // guest (since kernel 2.6.24): time spent running a virtual CPU for guest OS under the
+ // control of the Linux kernel
+ uint64_t guestNiceTicks = 0;
+ int logical_cpu = -1;
+ const int required_tickinfo_count = (which_logical_cpu == -1) ? 4 : 5;
+ int n;
+
+ memset(pticks, 0, sizeof(CPUPerfTicks));
+
+ if ((fh = fopen("/proc/stat", "r")) == NULL) {
+ return false;
+ }
+
+ if (which_logical_cpu == -1) {
+ n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " ",
+ &userTicks, &niceTicks, &systemTicks, &idleTicks,
+ &iowTicks, &irqTicks, &sirqTicks,
+ &stealTicks, &guestNiceTicks);
+ } else {
+ // Move to next line
+ next_line(fh);
+
+ // find the line for requested cpu faster to just iterate linefeeds?
+ for (int i = 0; i < which_logical_cpu; i++) {
+ next_line(fh);
+ }
+
+ n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " ",
+ &logical_cpu, &userTicks, &niceTicks,
+ &systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks,
+ &stealTicks, &guestNiceTicks);
+ }
+
+ fclose(fh);
+ if (n < required_tickinfo_count || logical_cpu != which_logical_cpu) {
+ return false;
+ }
+ pticks->used = userTicks + niceTicks;
+ pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
+ pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
+ iowTicks + irqTicks + sirqTicks + stealTicks + guestNiceTicks;
+
+ if (n > required_tickinfo_count + 3) {
+ pticks->steal = stealTicks;
+ pticks->has_steal_ticks = true;
+ } else {
+ pticks->steal = 0;
+ pticks->has_steal_ticks = false;
+ }
+
+ return true;
+}
+
// Return true if user is running as root.
bool os::have_special_privileges() {
@@ -1977,6 +2053,8 @@
os::Linux::print_container_info(st);
os::Linux::print_virtualization_info(st);
+
+ os::Linux::print_steal_info(st);
}
// Try to identify popular distros.
@@ -2265,6 +2343,24 @@
#endif
}
+void os::Linux::print_steal_info(outputStream* st) {
+ if (has_initial_tick_info) {
+ CPUPerfTicks pticks;
+ bool res = os::Linux::get_tick_information(&pticks, -1);
+
+ if (res && pticks.has_steal_ticks) {
+ uint64_t steal_ticks_difference = pticks.steal - initial_steal_ticks;
+ uint64_t total_ticks_difference = pticks.total - initial_total_ticks;
+ double steal_ticks_perc = 0.0;
+ if (total_ticks_difference != 0) {
+ steal_ticks_perc = (double) steal_ticks_difference / total_ticks_difference;
+ }
+ st->print_cr("Steal ticks since vm start: " UINT64_FORMAT, steal_ticks_difference);
+ st->print_cr("Steal ticks percentage since vm start:%7.3f", steal_ticks_perc);
+ }
+ }
+}
+
void os::print_memory_info(outputStream* st) {
st->print("Memory:");
@@ -4989,6 +5085,15 @@
Linux::initialize_os_info();
+ os::Linux::CPUPerfTicks pticks;
+ bool res = os::Linux::get_tick_information(&pticks, -1);
+
+ if (res && pticks.has_steal_ticks) {
+ has_initial_tick_info = true;
+ initial_total_ticks = pticks.total;
+ initial_steal_ticks = pticks.steal;
+ }
+
// _main_thread points to the thread that created/loaded the JVM.
Linux::_main_thread = pthread_self();
--- a/src/hotspot/os/linux/os_linux.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os/linux/os_linux.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -109,12 +109,23 @@
static void print_full_memory_info(outputStream* st);
static void print_container_info(outputStream* st);
static void print_virtualization_info(outputStream* st);
+ static void print_steal_info(outputStream* st);
static void print_distro_info(outputStream* st);
static void print_libversion_info(outputStream* st);
static void print_proc_sys_info(outputStream* st);
static void print_ld_preload_file(outputStream* st);
public:
+ struct CPUPerfTicks {
+ uint64_t used;
+ uint64_t usedKernel;
+ uint64_t total;
+ uint64_t steal;
+ bool has_steal_ticks;
+ };
+
+ // which_logical_cpu=-1 returns accumulated ticks for all cpus.
+ static bool get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu);
static bool _stack_is_executable;
static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
--- a/src/hotspot/os/linux/os_perf_linux.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os/linux/os_perf_linux.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -206,13 +206,6 @@
# define _SCANFMT_
#endif
-
-struct CPUPerfTicks {
- uint64_t used;
- uint64_t usedKernel;
- uint64_t total;
-};
-
typedef enum {
CPU_LOAD_VM_ONLY,
CPU_LOAD_GLOBAL,
@@ -227,8 +220,8 @@
struct CPUPerfCounters {
int nProcs;
- CPUPerfTicks jvmTicks;
- CPUPerfTicks* cpus;
+ os::Linux::CPUPerfTicks jvmTicks;
+ os::Linux::CPUPerfTicks* cpus;
};
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
@@ -287,80 +280,6 @@
return f;
}
-static void
-next_line(FILE *f) {
- int c;
- do {
- c = fgetc(f);
- } while (c != '\n' && c != EOF);
-}
-
-/**
- * Return the total number of ticks since the system was booted.
- * If the usedTicks parameter is not NULL, it will be filled with
- * the number of ticks spent on actual processes (user, system or
- * nice processes) since system boot. Note that this is the total number
- * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
- * n times the number of ticks that has passed in clock time.
- *
- * Returns a negative value if the reading of the ticks failed.
- */
-static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) {
- FILE* fh;
- uint64_t userTicks, niceTicks, systemTicks, idleTicks;
- uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
- int logical_cpu = -1;
- const int expected_assign_count = (-1 == which_logical_cpu) ? 4 : 5;
- int n;
-
- if ((fh = open_statfile()) == NULL) {
- return OS_ERR;
- }
- if (-1 == which_logical_cpu) {
- n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
- &userTicks, &niceTicks, &systemTicks, &idleTicks,
- &iowTicks, &irqTicks, &sirqTicks);
- } else {
- // Move to next line
- next_line(fh);
-
- // find the line for requested cpu faster to just iterate linefeeds?
- for (int i = 0; i < which_logical_cpu; i++) {
- next_line(fh);
- }
-
- n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
- &logical_cpu, &userTicks, &niceTicks,
- &systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks);
- }
-
- fclose(fh);
- if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read failed");
-#endif
- return OS_ERR;
- }
-
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
- userTicks, niceTicks, systemTicks, idleTicks,
- iowTicks, irqTicks, sirqTicks);
-#endif
-
- pticks->used = userTicks + niceTicks;
- pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
- pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
- iowTicks + irqTicks + sirqTicks;
-
- return OS_OK;
-}
-
-
static int get_systemtype(void) {
static int procEntriesType = UNDETECTED;
DIR *taskDir;
@@ -391,7 +310,7 @@
* Return the number of ticks spent in any of the processes belonging
* to the JVM on any CPU.
*/
-static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
+static OSReturn get_jvm_ticks(os::Linux::CPUPerfTicks* pticks) {
uint64_t userTicks;
uint64_t systemTicks;
@@ -404,7 +323,7 @@
}
// get the total
- if (get_total_ticks(-1, pticks) != OS_OK) {
+ if (! os::Linux::get_tick_information(pticks, -1)) {
return OS_ERR;
}
@@ -423,8 +342,8 @@
*/
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
uint64_t udiff, kdiff, tdiff;
- CPUPerfTicks* pticks;
- CPUPerfTicks tmp;
+ os::Linux::CPUPerfTicks* pticks;
+ os::Linux::CPUPerfTicks tmp;
double user_load;
*pkernelLoad = 0.0;
@@ -443,7 +362,7 @@
if (get_jvm_ticks(pticks) != OS_OK) {
return -1.0;
}
- } else if (get_total_ticks(which_logical_cpu, pticks) != OS_OK) {
+ } else if (! os::Linux::get_tick_information(pticks, which_logical_cpu)) {
return -1.0;
}
@@ -584,19 +503,19 @@
}
bool CPUPerformanceInterface::CPUPerformance::initialize() {
- size_t tick_array_size = (_counters.nProcs +1) * sizeof(CPUPerfTicks);
- _counters.cpus = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
+ size_t tick_array_size = (_counters.nProcs +1) * sizeof(os::Linux::CPUPerfTicks);
+ _counters.cpus = (os::Linux::CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
if (NULL == _counters.cpus) {
return false;
}
memset(_counters.cpus, 0, tick_array_size);
// For the CPU load total
- get_total_ticks(-1, &_counters.cpus[_counters.nProcs]);
+ os::Linux::get_tick_information(&_counters.cpus[_counters.nProcs], -1);
// For each CPU
for (int i = 0; i < _counters.nProcs; i++) {
- get_total_ticks(i, &_counters.cpus[i]);
+ os::Linux::get_tick_information(&_counters.cpus[i], i);
}
// For JVM load
get_jvm_ticks(&_counters.jvmTicks);
--- a/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -66,7 +66,7 @@
if (ret_frame.is_interpreted_frame()) {
frame::ijava_state* istate = ret_frame.get_ijava_state();
- if (!((Method*)(istate->method))->is_metaspace_object()) {
+ if (MetaspaceObj::is_valid((Method*)(istate->method)) == false) {
return false;
}
uint64_t reg_bcp = uc->uc_mcontext.regs->gpr[14/*R14_bcp*/];
--- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -63,7 +63,8 @@
if (ret_frame.is_interpreted_frame()) {
frame::z_ijava_state* istate = ret_frame.ijava_state_unchecked();
- if ((stack_base() >= (address)istate && (address)istate > stack_end()) || !((Method*)(istate->method))->is_metaspace_object()) {
+ if ((stack_base() >= (address)istate && (address)istate > stack_end()) ||
+ MetaspaceObj::is_valid((Method*)(istate->method)) == false) {
return false;
}
uint64_t reg_bcp = uc->uc_mcontext.gregs[13/*Z_BCP*/];
--- a/src/hotspot/share/adlc/formssel.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/adlc/formssel.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -777,8 +777,7 @@
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN") ||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
- !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
- !strcmp(_matrule->_rChild->_opType,"ShenandoahReadBarrier"))) return true;
+ !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN"))) return true;
else if ( is_ideal_load() == Form::idealP ) return true;
else if ( is_ideal_store() != Form::none ) return true;
@@ -3506,7 +3505,6 @@
"ClearArray",
"GetAndSetB", "GetAndSetS", "GetAndAddI", "GetAndSetI", "GetAndSetP",
"GetAndAddB", "GetAndAddS", "GetAndAddL", "GetAndSetL", "GetAndSetN",
- "ShenandoahReadBarrier",
"LoadBarrierSlowReg", "LoadBarrierWeakSlowReg"
};
int cnt = sizeof(needs_ideal_memory_list)/sizeof(char*);
--- a/src/hotspot/share/classfile/javaClasses.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/javaClasses.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -218,7 +218,7 @@
void java_lang_String::set_compact_strings(bool value) {
CompactStringsFixup fix(value);
- InstanceKlass::cast(SystemDictionary::String_klass())->do_local_static_fields(&fix);
+ SystemDictionary::String_klass()->do_local_static_fields(&fix);
}
Handle java_lang_String::basic_create(int length, bool is_latin1, TRAPS) {
@@ -3991,6 +3991,48 @@
int java_lang_System::out_offset_in_bytes() { return static_out_offset; }
int java_lang_System::err_offset_in_bytes() { return static_err_offset; }
+// Support for jdk_internal_misc_UnsafeConstants
+//
+class UnsafeConstantsFixup : public FieldClosure {
+private:
+ int _address_size;
+ int _page_size;
+ bool _big_endian;
+ bool _use_unaligned_access;
+public:
+ UnsafeConstantsFixup() {
+ // round up values for all static final fields
+ _address_size = sizeof(void*);
+ _page_size = os::vm_page_size();
+ _big_endian = LITTLE_ENDIAN_ONLY(false) BIG_ENDIAN_ONLY(true);
+ _use_unaligned_access = UseUnalignedAccesses;
+ }
+
+ void do_field(fieldDescriptor* fd) {
+ oop mirror = fd->field_holder()->java_mirror();
+ assert(mirror != NULL, "UnsafeConstants must have mirror already");
+ assert(fd->field_holder() == SystemDictionary::UnsafeConstants_klass(), "Should be UnsafeConstants");
+ assert(fd->is_final(), "fields of UnsafeConstants must be final");
+ assert(fd->is_static(), "fields of UnsafeConstants must be static");
+ if (fd->name() == vmSymbols::address_size_name()) {
+ mirror->int_field_put(fd->offset(), _address_size);
+ } else if (fd->name() == vmSymbols::page_size_name()) {
+ mirror->int_field_put(fd->offset(), _page_size);
+ } else if (fd->name() == vmSymbols::big_endian_name()) {
+ mirror->bool_field_put(fd->offset(), _big_endian);
+ } else if (fd->name() == vmSymbols::use_unaligned_access_name()) {
+ mirror->bool_field_put(fd->offset(), _use_unaligned_access);
+ } else {
+ assert(false, "unexpected UnsafeConstants field");
+ }
+ }
+};
+
+void jdk_internal_misc_UnsafeConstants::set_unsafe_constants() {
+ UnsafeConstantsFixup fixup;
+ SystemDictionary::UnsafeConstants_klass()->do_local_static_fields(&fixup);
+}
+
int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_oop_size_offset;
--- a/src/hotspot/share/classfile/javaClasses.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/javaClasses.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -81,6 +81,7 @@
f(java_lang_StackFrameInfo) \
f(java_lang_LiveStackFrameInfo) \
f(java_util_concurrent_locks_AbstractOwnableSynchronizer) \
+ f(jdk_internal_misc_UnsafeConstants) \
//end
#define BASIC_JAVA_CLASSES_DO(f) \
@@ -1483,6 +1484,15 @@
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
};
+ // Interface to jdk.internal.misc.UnsafeConsants
+
+class jdk_internal_misc_UnsafeConstants : AllStatic {
+ public:
+ static void set_unsafe_constants();
+ static void compute_offsets() { }
+ static void serialize_offsets(SerializeClosure* f) { }
+};
+
// Use to declare fields that need to be injected into Java classes
// for the JVM to use. The name_index and signature_index are
// declared in vmSymbols. The may_be_java flag is used to declare
--- a/src/hotspot/share/classfile/protectionDomainCache.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/protectionDomainCache.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -45,7 +45,7 @@
}
ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
- : Hashtable<ClassLoaderWeakHandle, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
+ : Hashtable<WeakHandle<vm_class_loader_data>, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
{ _dead_entries = false;
_total_oops_removed = 0;
}
@@ -180,8 +180,8 @@
protection_domain->print_value_on(&ls);
ls.cr();
}
- ClassLoaderWeakHandle w = ClassLoaderWeakHandle::create(protection_domain);
+ WeakHandle<vm_class_loader_data> w = WeakHandle<vm_class_loader_data>::create(protection_domain);
ProtectionDomainCacheEntry* p = new_entry(hash, w);
- Hashtable<ClassLoaderWeakHandle, mtClass>::add_entry(index, p);
+ Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::add_entry(index, p);
return p;
}
--- a/src/hotspot/share/classfile/protectionDomainCache.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/protectionDomainCache.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -35,18 +35,18 @@
// to dictionary.hpp pd_set for more information about how protection domain entries
// are used.
// This table is walked during GC, rather than the class loader data graph dictionaries.
-class ProtectionDomainCacheEntry : public HashtableEntry<ClassLoaderWeakHandle, mtClass> {
+class ProtectionDomainCacheEntry : public HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass> {
friend class VMStructs;
public:
oop object();
oop object_no_keepalive();
ProtectionDomainCacheEntry* next() {
- return (ProtectionDomainCacheEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next();
+ return (ProtectionDomainCacheEntry*)HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass>::next();
}
ProtectionDomainCacheEntry** next_addr() {
- return (ProtectionDomainCacheEntry**)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next_addr();
+ return (ProtectionDomainCacheEntry**)HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass>::next_addr();
}
void verify();
@@ -61,21 +61,21 @@
// we only need to iterate over this set.
// The amount of different protection domains used is typically magnitudes smaller
// than the number of system dictionary entries (loaded classes).
-class ProtectionDomainCacheTable : public Hashtable<ClassLoaderWeakHandle, mtClass> {
+class ProtectionDomainCacheTable : public Hashtable<WeakHandle<vm_class_loader_data>, mtClass> {
friend class VMStructs;
private:
ProtectionDomainCacheEntry* bucket(int i) const {
- return (ProtectionDomainCacheEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket(i);
+ return (ProtectionDomainCacheEntry*) Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
ProtectionDomainCacheEntry** bucket_addr(int i) {
- return (ProtectionDomainCacheEntry**) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket_addr(i);
+ return (ProtectionDomainCacheEntry**) Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::bucket_addr(i);
}
- ProtectionDomainCacheEntry* new_entry(unsigned int hash, ClassLoaderWeakHandle protection_domain) {
+ ProtectionDomainCacheEntry* new_entry(unsigned int hash, WeakHandle<vm_class_loader_data> protection_domain) {
ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*)
- Hashtable<ClassLoaderWeakHandle, mtClass>::new_entry(hash, protection_domain);
+ Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::new_entry(hash, protection_domain);
return entry;
}
--- a/src/hotspot/share/classfile/systemDictionary.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/systemDictionary.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -177,6 +177,7 @@
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives ) \
do_klass(StringBuffer_klass, java_lang_StringBuffer ) \
do_klass(StringBuilder_klass, java_lang_StringBuilder ) \
+ do_klass(UnsafeConstants_klass, jdk_internal_misc_UnsafeConstants ) \
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe ) \
do_klass(module_Modules_klass, jdk_internal_module_Modules ) \
\
--- a/src/hotspot/share/classfile/verifier.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/verifier.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -2060,7 +2060,9 @@
ss.vprint(msg, va);
va_end(va);
if (!_method.is_null()) {
- ss.print(" in method %s", _method->name_and_sig_as_C_string());
+ ss.print(" in method '");
+ _method->print_external_name(&ss);
+ ss.print("'");
}
_message = ss.as_string();
}
--- a/src/hotspot/share/classfile/vmSymbols.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/classfile/vmSymbols.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -446,6 +446,10 @@
template(module_entry_name, "module_entry") \
template(resolved_references_name, "<resolved_references>") \
template(init_lock_name, "<init_lock>") \
+ template(address_size_name, "ADDRESS_SIZE0") \
+ template(page_size_name, "PAGE_SIZE") \
+ template(big_endian_name, "BIG_ENDIAN") \
+ template(use_unaligned_access_name, "UNALIGNED_ACCESS") \
\
/* name symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
@@ -1070,6 +1074,9 @@
do_intrinsic(_updateByteBufferAdler32, java_util_zip_Adler32, updateByteBuffer_A_name, updateByteBuffer_signature, F_SN) \
do_name( updateByteBuffer_A_name, "updateByteBuffer") \
\
+ /* support for UnsafeConstants */ \
+ do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \
+ \
/* support for Unsafe */ \
do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \
\
--- a/src/hotspot/share/code/codeCache.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/code/codeCache.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -780,13 +780,14 @@
CodeCache::UnloadingScope::UnloadingScope(BoolObjectClosure* is_alive)
: _is_unloading_behaviour(is_alive)
{
+ _saved_behaviour = IsUnloadingBehaviour::current();
IsUnloadingBehaviour::set_current(&_is_unloading_behaviour);
increment_unloading_cycle();
DependencyContext::cleaning_start();
}
CodeCache::UnloadingScope::~UnloadingScope() {
- IsUnloadingBehaviour::set_current(NULL);
+ IsUnloadingBehaviour::set_current(_saved_behaviour);
DependencyContext::cleaning_end();
}
--- a/src/hotspot/share/code/codeCache.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/code/codeCache.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -170,6 +170,7 @@
// "unloading_occurred" controls whether metadata should be cleaned because of class unloading.
class UnloadingScope: StackObj {
ClosureIsUnloadingBehaviour _is_unloading_behaviour;
+ IsUnloadingBehaviour* _saved_behaviour;
public:
UnloadingScope(BoolObjectClosure* is_alive);
--- a/src/hotspot/share/compiler/compileBroker.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/compiler/compileBroker.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -135,11 +135,6 @@
volatile jint CompileBroker::_compilation_id = 0;
volatile jint CompileBroker::_osr_compilation_id = 0;
-// Debugging information
-int CompileBroker::_last_compile_type = no_compile;
-int CompileBroker::_last_compile_level = CompLevel_none;
-char CompileBroker::_last_method_compiled[CompileBroker::name_buffer_length];
-
// Performance counters
PerfCounter* CompileBroker::_perf_total_compilation = NULL;
PerfCounter* CompileBroker::_perf_osr_compilation = NULL;
@@ -577,8 +572,6 @@
//
// Initialize the Compilation object
void CompileBroker::compilation_init_phase1(TRAPS) {
- _last_method_compiled[0] = '\0';
-
// No need to initialize compilation system if we do not use it.
if (!UseCompiler) {
return;
@@ -2032,8 +2025,10 @@
// Look up matching directives
directive = DirectivesStack::getMatchingDirective(method, comp);
- // Save information about this method in case of failure.
- set_last_compile(thread, method, is_osr, task_level);
+ // Update compile information when using perfdata.
+ if (UsePerfData) {
+ update_compile_perf_data(thread, method, is_osr);
+ }
DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, compiler_name(task_level));
}
@@ -2264,58 +2259,49 @@
}
// ------------------------------------------------------------------
-// CompileBroker::set_last_compile
+// CompileBroker::update_compile_perf_data
//
// Record this compilation for debugging purposes.
-void CompileBroker::set_last_compile(CompilerThread* thread, const methodHandle& method, bool is_osr, int comp_level) {
+void CompileBroker::update_compile_perf_data(CompilerThread* thread, const methodHandle& method, bool is_osr) {
ResourceMark rm;
char* method_name = method->name()->as_C_string();
- strncpy(_last_method_compiled, method_name, CompileBroker::name_buffer_length);
- _last_method_compiled[CompileBroker::name_buffer_length - 1] = '\0'; // ensure null terminated
char current_method[CompilerCounters::cmname_buffer_length];
size_t maxLen = CompilerCounters::cmname_buffer_length;
- if (UsePerfData) {
- const char* class_name = method->method_holder()->name()->as_C_string();
-
- size_t s1len = strlen(class_name);
- size_t s2len = strlen(method_name);
+ const char* class_name = method->method_holder()->name()->as_C_string();
- // check if we need to truncate the string
- if (s1len + s2len + 2 > maxLen) {
+ size_t s1len = strlen(class_name);
+ size_t s2len = strlen(method_name);
- // the strategy is to lop off the leading characters of the
- // class name and the trailing characters of the method name.
+ // check if we need to truncate the string
+ if (s1len + s2len + 2 > maxLen) {
- if (s2len + 2 > maxLen) {
- // lop of the entire class name string, let snprintf handle
- // truncation of the method name.
- class_name += s1len; // null string
- }
- else {
- // lop off the extra characters from the front of the class name
- class_name += ((s1len + s2len + 2) - maxLen);
- }
+ // the strategy is to lop off the leading characters of the
+ // class name and the trailing characters of the method name.
+
+ if (s2len + 2 > maxLen) {
+ // lop of the entire class name string, let snprintf handle
+ // truncation of the method name.
+ class_name += s1len; // null string
}
-
- jio_snprintf(current_method, maxLen, "%s %s", class_name, method_name);
+ else {
+ // lop off the extra characters from the front of the class name
+ class_name += ((s1len + s2len + 2) - maxLen);
+ }
}
- if (CICountOSR && is_osr) {
- _last_compile_type = osr_compile;
- } else {
- _last_compile_type = normal_compile;
- }
- _last_compile_level = comp_level;
+ jio_snprintf(current_method, maxLen, "%s %s", class_name, method_name);
- if (UsePerfData) {
- CompilerCounters* counters = thread->counters();
- counters->set_current_method(current_method);
- counters->set_compile_type((jlong)_last_compile_type);
+ int last_compile_type = normal_compile;
+ if (CICountOSR && is_osr) {
+ last_compile_type = osr_compile;
}
+
+ CompilerCounters* counters = thread->counters();
+ counters->set_current_method(current_method);
+ counters->set_compile_type((jlong) last_compile_type);
}
-
// ------------------------------------------------------------------
// CompileBroker::push_jni_handle_block
//
@@ -2618,21 +2604,6 @@
tty->print_cr(" nmethod total size : %8d bytes", nmethods_size);
}
-// Debugging output for failure
-void CompileBroker::print_last_compile() {
- if (_last_compile_level != CompLevel_none &&
- compiler(_last_compile_level) != NULL &&
- _last_compile_type != no_compile) {
- if (_last_compile_type == osr_compile) {
- tty->print_cr("Last parse: [osr]%d+++(%d) %s",
- _osr_compilation_id, _last_compile_level, _last_method_compiled);
- } else {
- tty->print_cr("Last parse: %d+++(%d) %s",
- _compilation_id, _last_compile_level, _last_method_compiled);
- }
- }
-}
-
// Print general/accumulated JIT information.
void CompileBroker::print_info(outputStream *out) {
if (out == NULL) out = tty;
--- a/src/hotspot/share/compiler/compileBroker.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/compiler/compileBroker.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -173,10 +173,6 @@
static volatile jint _compilation_id;
static volatile jint _osr_compilation_id;
- static int _last_compile_type;
- static int _last_compile_level;
- static char _last_method_compiled[name_buffer_length];
-
static CompileQueue* _c2_compile_queue;
static CompileQueue* _c1_compile_queue;
@@ -254,7 +250,8 @@
static void invoke_compiler_on_method(CompileTask* task);
static void post_compile(CompilerThread* thread, CompileTask* task, bool success, ciEnv* ci_env,
int compilable, const char* failure_reason);
- static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level);
+ static void update_compile_perf_data(CompilerThread *thread, const methodHandle& method, bool is_osr);
+
static void push_jni_handle_block();
static void pop_jni_handle_block();
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
@@ -382,9 +379,6 @@
// Print a detailed accounting of compilation time
static void print_times(bool per_compiler = true, bool aggregate = true);
- // Debugging output for failure
- static void print_last_compile();
-
// compiler name for debugging
static const char* compiler_name(int comp_level);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -154,6 +154,11 @@
reset_from_card_cache(start_idx, num_regions);
}
+Tickspan G1CollectedHeap::run_task(AbstractGangTask* task) {
+ Ticks start = Ticks::now();
+ workers()->run_task(task, workers()->active_workers());
+ return Ticks::now() - start;
+}
HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
MemRegion mr) {
@@ -2242,12 +2247,12 @@
_hrm->par_iterate(cl, hrclaimer, 0);
}
-void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
+void G1CollectedHeap::collection_set_iterate_all(HeapRegionClosure* cl) {
_collection_set.iterate(cl);
}
-void G1CollectedHeap::collection_set_iterate_from(HeapRegionClosure *cl, uint worker_id) {
- _collection_set.iterate_from(cl, worker_id, workers()->active_workers());
+void G1CollectedHeap::collection_set_iterate_increment_from(HeapRegionClosure *cl, uint worker_id) {
+ _collection_set.iterate_incremental_part_from(cl, worker_id, workers()->active_workers());
}
HeapWord* G1CollectedHeap::block_start(const void* addr) const {
@@ -2484,7 +2489,7 @@
void G1CollectedHeap::print_cset_rsets() {
PrintRSetsClosure cl("Printing CSet RSets");
- collection_set_iterate(&cl);
+ collection_set_iterate_all(&cl);
}
void G1CollectedHeap::print_all_rsets() {
@@ -2495,8 +2500,8 @@
G1HeapSummary G1CollectedHeap::create_g1_heap_summary() {
- size_t eden_used_bytes = heap()->eden_regions_count() * HeapRegion::GrainBytes;
- size_t survivor_used_bytes = heap()->survivor_regions_count() * HeapRegion::GrainBytes;
+ size_t eden_used_bytes = _eden.used_bytes();
+ size_t survivor_used_bytes = _survivor.used_bytes();
size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked();
size_t eden_capacity_bytes =
@@ -2880,15 +2885,18 @@
phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0);
}
-void G1CollectedHeap::calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms){
- policy()->finalize_collection_set(target_pause_time_ms, &_survivor);
- evacuation_info.set_collectionset_regions(collection_set()->region_length());
+void G1CollectedHeap::calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms) {
+
+ _collection_set.finalize_initial_collection_set(target_pause_time_ms, &_survivor);
+ evacuation_info.set_collectionset_regions(collection_set()->region_length() +
+ collection_set()->optional_region_length());
_cm->verify_no_collection_set_oops();
if (_hr_printer.is_active()) {
G1PrintCollectionSetClosure cl(&_hr_printer);
_collection_set.iterate(&cl);
+ _collection_set.iterate_optional(&cl);
}
}
@@ -3060,9 +3068,10 @@
pre_evacuate_collection_set(evacuation_info);
// Actually do the work...
- evacuate_collection_set(&per_thread_states);
- evacuate_optional_collection_set(&per_thread_states);
-
+ evacuate_initial_collection_set(&per_thread_states);
+ if (_collection_set.optional_region_length() != 0) {
+ evacuate_optional_collection_set(&per_thread_states);
+ }
post_evacuate_collection_set(evacuation_info, &per_thread_states);
start_new_collection_set();
@@ -3088,7 +3097,8 @@
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
- size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards);
+ size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards) +
+ phase_times()->sum_thread_work_items(G1GCPhaseTimes::OptScanRS, G1GCPhaseTimes::ScanRSScannedCards);
policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc);
}
@@ -3192,86 +3202,6 @@
} while (!offer_termination());
}
-class G1ParTask : public AbstractGangTask {
-protected:
- G1CollectedHeap* _g1h;
- G1ParScanThreadStateSet* _pss;
- RefToScanQueueSet* _queues;
- G1RootProcessor* _root_processor;
- TaskTerminator _terminator;
- uint _n_workers;
-
-public:
- G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
- : AbstractGangTask("G1 collection"),
- _g1h(g1h),
- _pss(per_thread_states),
- _queues(task_queues),
- _root_processor(root_processor),
- _terminator(n_workers, _queues),
- _n_workers(n_workers)
- {}
-
- void work(uint worker_id) {
- if (worker_id >= _n_workers) return; // no work needed this round
-
- double start_sec = os::elapsedTime();
- _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerStart, worker_id, start_sec);
-
- {
- ResourceMark rm;
- HandleMark hm;
-
- ReferenceProcessor* rp = _g1h->ref_processor_stw();
-
- G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
- pss->set_ref_discoverer(rp);
-
- double start_strong_roots_sec = os::elapsedTime();
-
- _root_processor->evacuate_roots(pss, worker_id);
-
- _g1h->rem_set()->oops_into_collection_set_do(pss, worker_id);
-
- double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
-
- double term_sec = 0.0;
- size_t evac_term_attempts = 0;
- {
- double start = os::elapsedTime();
- G1ParEvacuateFollowersClosure evac(_g1h, pss, _queues, _terminator.terminator(), G1GCPhaseTimes::ObjCopy);
- evac.do_void();
-
- evac_term_attempts = evac.term_attempts();
- term_sec = evac.term_time();
- double elapsed_sec = os::elapsedTime() - start;
-
- G1GCPhaseTimes* p = _g1h->phase_times();
- p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_id, elapsed_sec - term_sec);
-
- p->record_or_add_thread_work_item(G1GCPhaseTimes::ObjCopy,
- worker_id,
- pss->lab_waste_words() * HeapWordSize,
- G1GCPhaseTimes::ObjCopyLABWaste);
- p->record_or_add_thread_work_item(G1GCPhaseTimes::ObjCopy,
- worker_id,
- pss->lab_undo_waste_words() * HeapWordSize,
- G1GCPhaseTimes::ObjCopyLABUndoWaste);
-
- p->record_time_secs(G1GCPhaseTimes::Termination, worker_id, term_sec);
- p->record_thread_work_item(G1GCPhaseTimes::Termination, worker_id, evac_term_attempts);
- }
-
- assert(pss->queue_is_empty(), "should be empty");
-
- // Close the inner scope so that the ResourceMark and HandleMark
- // destructors are executed here and are included as part of the
- // "GC Worker Time".
- }
- _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerEnd, worker_id, os::elapsedTime());
- }
-};
-
void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
bool class_unloading_occurred) {
uint num_workers = workers()->active_workers();
@@ -3675,176 +3605,196 @@
double recorded_clear_claimed_marks_time_ms = (os::elapsedTime() - start_clear_claimed_marks) * 1000.0;
phase_times()->record_clear_claimed_marks_time_ms(recorded_clear_claimed_marks_time_ms);
}
-}
-
-void G1CollectedHeap::evacuate_collection_set(G1ParScanThreadStateSet* per_thread_states) {
+
// Should G1EvacuationFailureALot be in effect for this GC?
NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
-
- double start_par_time_sec = os::elapsedTime();
- double end_par_time_sec;
-
- {
- const uint n_workers = workers()->active_workers();
- G1RootProcessor root_processor(this, n_workers);
- G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
-
- workers()->run_task(&g1_par_task);
- end_par_time_sec = os::elapsedTime();
-
- // Closing the inner scope will execute the destructor
- // for the G1RootProcessor object. We record the current
- // elapsed time before closing the scope so that time
- // taken for the destructor is NOT included in the
- // reported parallel time.
- }
-
- double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
- phase_times()->record_par_time(par_time_ms);
-
- double code_root_fixup_time_ms =
- (os::elapsedTime() - end_par_time_sec) * 1000.0;
- phase_times()->record_code_root_fixup_time(code_root_fixup_time_ms);
}
-class G1EvacuateOptionalRegionTask : public AbstractGangTask {
+class G1EvacuateRegionsBaseTask : public AbstractGangTask {
+protected:
G1CollectedHeap* _g1h;
G1ParScanThreadStateSet* _per_thread_states;
- G1OptionalCSet* _optional;
- RefToScanQueueSet* _queues;
- ParallelTaskTerminator _terminator;
-
- Tickspan trim_ticks(G1ParScanThreadState* pss) {
- Tickspan copy_time = pss->trim_ticks();
- pss->reset_trim_ticks();
- return copy_time;
+ RefToScanQueueSet* _task_queues;
+ TaskTerminator _terminator;
+ uint _num_workers;
+
+ void evacuate_live_objects(G1ParScanThreadState* pss,
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases objcopy_phase,
+ G1GCPhaseTimes::GCParPhases termination_phase) {
+ G1GCPhaseTimes* p = _g1h->phase_times();
+
+ Ticks start = Ticks::now();
+ G1ParEvacuateFollowersClosure cl(_g1h, pss, _task_queues, _terminator.terminator(), objcopy_phase);
+ cl.do_void();
+
+ assert(pss->queue_is_empty(), "should be empty");
+
+ Tickspan evac_time = (Ticks::now() - start);
+ p->record_or_add_time_secs(objcopy_phase, worker_id, evac_time.seconds() - cl.term_time());
+
+ p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABWaste);
+ p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_undo_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABUndoWaste);
+
+ if (termination_phase == G1GCPhaseTimes::Termination) {
+ p->record_time_secs(termination_phase, worker_id, cl.term_time());
+ p->record_thread_work_item(termination_phase, worker_id, cl.term_attempts());
+ } else {
+ p->record_or_add_time_secs(termination_phase, worker_id, cl.term_time());
+ p->record_or_add_thread_work_item(termination_phase, worker_id, cl.term_attempts());
+ }
+ assert(pss->trim_ticks().seconds() == 0.0, "Unexpected partial trimming during evacuation");
}
+ virtual void start_work(uint worker_id) { }
+
+ virtual void end_work(uint worker_id) { }
+
+ virtual void scan_roots(G1ParScanThreadState* pss, uint worker_id) = 0;
+
+ virtual void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) = 0;
+
+public:
+ G1EvacuateRegionsBaseTask(const char* name, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet* task_queues, uint num_workers) :
+ AbstractGangTask(name),
+ _g1h(G1CollectedHeap::heap()),
+ _per_thread_states(per_thread_states),
+ _task_queues(task_queues),
+ _terminator(num_workers, _task_queues),
+ _num_workers(num_workers)
+ { }
+
+ void work(uint worker_id) {
+ start_work(worker_id);
+
+ {
+ ResourceMark rm;
+ HandleMark hm;
+
+ G1ParScanThreadState* pss = _per_thread_states->state_for_worker(worker_id);
+ pss->set_ref_discoverer(_g1h->ref_processor_stw());
+
+ scan_roots(pss, worker_id);
+ evacuate_live_objects(pss, worker_id);
+ }
+
+ end_work(worker_id);
+ }
+};
+
+class G1EvacuateRegionsTask : public G1EvacuateRegionsBaseTask {
+ G1RootProcessor* _root_processor;
+
void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
- G1EvacuationRootClosures* root_cls = pss->closures();
- G1ScanObjsDuringScanRSClosure obj_cl(_g1h, pss);
-
- size_t scanned = 0;
- size_t claimed = 0;
- size_t skipped = 0;
- size_t used_memory = 0;
-
- Ticks start = Ticks::now();
- Tickspan copy_time;
-
- for (uint i = _optional->current_index(); i < _optional->current_limit(); i++) {
- HeapRegion* hr = _optional->region_at(i);
- G1ScanRSForOptionalClosure scan_opt_cl(&obj_cl);
- pss->oops_into_optional_region(hr)->oops_do(&scan_opt_cl, root_cls->raw_strong_oops());
- copy_time += trim_ticks(pss);
-
- G1ScanRSForRegionClosure scan_rs_cl(_g1h->rem_set()->scan_state(), &obj_cl, pss, G1GCPhaseTimes::OptScanRS, worker_id);
- scan_rs_cl.do_heap_region(hr);
- copy_time += trim_ticks(pss);
- scanned += scan_rs_cl.cards_scanned();
- claimed += scan_rs_cl.cards_claimed();
- skipped += scan_rs_cl.cards_skipped();
-
- // Chunk lists for this region is no longer needed.
- used_memory += pss->oops_into_optional_region(hr)->used_memory();
- }
-
- Tickspan scan_time = (Ticks::now() - start) - copy_time;
- G1GCPhaseTimes* p = _g1h->phase_times();
- p->record_or_add_time_secs(G1GCPhaseTimes::OptScanRS, worker_id, scan_time.seconds());
- p->record_or_add_time_secs(G1GCPhaseTimes::OptObjCopy, worker_id, copy_time.seconds());
-
- p->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_id, scanned, G1GCPhaseTimes::OptCSetScannedCards);
- p->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_id, claimed, G1GCPhaseTimes::OptCSetClaimedCards);
- p->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_id, skipped, G1GCPhaseTimes::OptCSetSkippedCards);
- p->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_id, used_memory, G1GCPhaseTimes::OptCSetUsedMemory);
+ _root_processor->evacuate_roots(pss, worker_id);
+ _g1h->rem_set()->update_rem_set(pss, worker_id);
+ _g1h->rem_set()->scan_rem_set(pss, worker_id, G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::CodeRoots);
}
void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
- Ticks start = Ticks::now();
- G1ParEvacuateFollowersClosure cl(_g1h, pss, _queues, &_terminator, G1GCPhaseTimes::OptObjCopy);
- cl.do_void();
-
- Tickspan evac_time = (Ticks::now() - start);
- G1GCPhaseTimes* p = _g1h->phase_times();
- p->record_or_add_time_secs(G1GCPhaseTimes::OptObjCopy, worker_id, evac_time.seconds());
- assert(pss->trim_ticks().seconds() == 0.0, "Unexpected partial trimming done during optional evacuation");
+ G1EvacuateRegionsBaseTask::evacuate_live_objects(pss, worker_id, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::Termination);
+ }
+
+ void start_work(uint worker_id) {
+ _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerStart, worker_id, Ticks::now().seconds());
+ }
+
+ void end_work(uint worker_id) {
+ _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerEnd, worker_id, Ticks::now().seconds());
}
- public:
- G1EvacuateOptionalRegionTask(G1CollectedHeap* g1h,
- G1ParScanThreadStateSet* per_thread_states,
- G1OptionalCSet* cset,
- RefToScanQueueSet* queues,
- uint n_workers) :
- AbstractGangTask("G1 Evacuation Optional Region Task"),
- _g1h(g1h),
- _per_thread_states(per_thread_states),
- _optional(cset),
- _queues(queues),
- _terminator(n_workers, _queues) {
+public:
+ G1EvacuateRegionsTask(G1CollectedHeap* g1h,
+ G1ParScanThreadStateSet* per_thread_states,
+ RefToScanQueueSet* task_queues,
+ G1RootProcessor* root_processor,
+ uint num_workers) :
+ G1EvacuateRegionsBaseTask("G1 Evacuate Regions", per_thread_states, task_queues, num_workers),
+ _root_processor(root_processor)
+ { }
+};
+
+void G1CollectedHeap::evacuate_initial_collection_set(G1ParScanThreadStateSet* per_thread_states) {
+ Tickspan task_time;
+ const uint num_workers = workers()->active_workers();
+
+ Ticks start_processing = Ticks::now();
+ {
+ G1RootProcessor root_processor(this, num_workers);
+ G1EvacuateRegionsTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, num_workers);
+ task_time = run_task(&g1_par_task);
+ // Closing the inner scope will execute the destructor for the G1RootProcessor object.
+ // To extract its code root fixup time we measure total time of this scope and
+ // subtract from the time the WorkGang task took.
}
-
- void work(uint worker_id) {
- ResourceMark rm;
- HandleMark hm;
-
- G1ParScanThreadState* pss = _per_thread_states->state_for_worker(worker_id);
- pss->set_ref_discoverer(_g1h->ref_processor_stw());
-
- scan_roots(pss, worker_id);
- evacuate_live_objects(pss, worker_id);
+ Tickspan total_processing = Ticks::now() - start_processing;
+
+ G1GCPhaseTimes* p = phase_times();
+ p->record_initial_evac_time(task_time.seconds() * 1000.0);
+ p->record_or_add_code_root_fixup_time((total_processing - task_time).seconds() * 1000.0);
+}
+
+class G1EvacuateOptionalRegionsTask : public G1EvacuateRegionsBaseTask {
+
+ void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
+ _g1h->rem_set()->scan_rem_set(pss, worker_id, G1GCPhaseTimes::OptScanRS, G1GCPhaseTimes::OptObjCopy, G1GCPhaseTimes::OptCodeRoots);
+ }
+
+ void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
+ G1EvacuateRegionsBaseTask::evacuate_live_objects(pss, worker_id, G1GCPhaseTimes::OptObjCopy, G1GCPhaseTimes::OptTermination);
+ }
+
+public:
+ G1EvacuateOptionalRegionsTask(G1ParScanThreadStateSet* per_thread_states,
+ RefToScanQueueSet* queues,
+ uint num_workers) :
+ G1EvacuateRegionsBaseTask("G1 Evacuate Optional Regions", per_thread_states, queues, num_workers) {
}
};
-void G1CollectedHeap::evacuate_optional_regions(G1ParScanThreadStateSet* per_thread_states, G1OptionalCSet* ocset) {
- class G1MarkScope : public MarkScope {};
- G1MarkScope code_mark_scope;
-
- G1EvacuateOptionalRegionTask task(this, per_thread_states, ocset, _task_queues, workers()->active_workers());
- workers()->run_task(&task);
+void G1CollectedHeap::evacuate_next_optional_regions(G1ParScanThreadStateSet* per_thread_states) {
+ class G1MarkScope : public MarkScope { };
+
+ Tickspan task_time;
+
+ Ticks start_processing = Ticks::now();
+ {
+ G1MarkScope code_mark_scope;
+ G1EvacuateOptionalRegionsTask task(per_thread_states, _task_queues, workers()->active_workers());
+ task_time = run_task(&task);
+ // See comment in evacuate_collection_set() for the reason of the scope.
+ }
+ Tickspan total_processing = Ticks::now() - start_processing;
+
+ G1GCPhaseTimes* p = phase_times();
+ p->record_or_add_code_root_fixup_time((total_processing - task_time).seconds() * 1000.0);
}
void G1CollectedHeap::evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states) {
- G1OptionalCSet optional_cset(&_collection_set, per_thread_states);
- if (optional_cset.is_empty()) {
- return;
- }
-
- if (evacuation_failed()) {
- return;
- }
-
const double gc_start_time_ms = phase_times()->cur_collection_start_sec() * 1000.0;
- double start_time_sec = os::elapsedTime();
-
- do {
+ Ticks start = Ticks::now();
+
+ while (!evacuation_failed() && _collection_set.optional_region_length() > 0) {
+
double time_used_ms = os::elapsedTime() * 1000.0 - gc_start_time_ms;
double time_left_ms = MaxGCPauseMillis - time_used_ms;
- if (time_left_ms < 0) {
- log_trace(gc, ergo, cset)("Skipping %u optional regions, pause time exceeded %.3fms", optional_cset.size(), time_used_ms);
- break;
- }
-
- optional_cset.prepare_evacuation(time_left_ms * _policy->optional_evacuation_fraction());
- if (optional_cset.prepare_failed()) {
- log_trace(gc, ergo, cset)("Skipping %u optional regions, no regions can be evacuated in %.3fms", optional_cset.size(), time_left_ms);
+ if (time_left_ms < 0 ||
+ !_collection_set.finalize_optional_for_evacuation(time_left_ms * policy()->optional_evacuation_fraction())) {
+ log_trace(gc, ergo, cset)("Skipping evacuation of %u optional regions, no more regions can be evacuated in %.3fms",
+ _collection_set.optional_region_length(), time_left_ms);
break;
}
- evacuate_optional_regions(per_thread_states, &optional_cset);
-
- optional_cset.complete_evacuation();
- if (optional_cset.evacuation_failed()) {
- break;
- }
- } while (!optional_cset.is_empty());
-
- phase_times()->record_optional_evacuation((os::elapsedTime() - start_time_sec) * 1000.0);
+ evacuate_next_optional_regions(per_thread_states);
+ }
+
+ _collection_set.abandon_optional_collection_set(per_thread_states);
+
+ phase_times()->record_or_add_optional_evac_time((Ticks::now() - start).seconds() * 1000.0);
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
@@ -4259,15 +4209,14 @@
double free_cset_start_time = os::elapsedTime();
{
- uint const num_chunks = MAX2(_collection_set.region_length() / G1FreeCollectionSetTask::chunk_size(), 1U);
+ uint const num_regions = _collection_set.region_length();
+ uint const num_chunks = MAX2(num_regions / G1FreeCollectionSetTask::chunk_size(), 1U);
uint const num_workers = MIN2(workers()->active_workers(), num_chunks);
G1FreeCollectionSetTask cl(collection_set, &evacuation_info, surviving_young_words);
log_debug(gc, ergo)("Running %s using %u workers for collection set length %u",
- cl.name(),
- num_workers,
- _collection_set.region_length());
+ cl.name(), num_workers, num_regions);
workers()->run_task(&cl, num_workers);
}
phase_times()->record_total_free_cset_time_ms((os::elapsedTime() - free_cset_start_time) * 1000.0);
@@ -4436,7 +4385,7 @@
void G1CollectedHeap::abandon_collection_set(G1CollectionSet* collection_set) {
G1AbandonCollectionSetClosure cl;
- collection_set->iterate(&cl);
+ collection_set_iterate_all(&cl);
collection_set->clear();
collection_set->stop_incremental_building();
@@ -4636,7 +4585,9 @@
collection_set()->add_eden_region(alloc_region);
increase_used(allocated_bytes);
+ _eden.add_used_bytes(allocated_bytes);
_hr_printer.retire(alloc_region);
+
// We update the eden sizes here, when the region is retired,
// instead of when it's allocated, since this is the point that its
// used space has been recorded in _summary_bytes_used.
@@ -4693,6 +4644,9 @@
policy()->record_bytes_copied_during_gc(allocated_bytes);
if (dest.is_old()) {
old_set_add(alloc_region);
+ } else {
+ assert(dest.is_young(), "Retiring alloc region should be young(%d)", dest.value());
+ _survivor.add_used_bytes(allocated_bytes);
}
bool const during_im = collector_state()->in_initial_mark_gc();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -143,9 +143,8 @@
// Closures used in implementation.
friend class G1ParScanThreadState;
friend class G1ParScanThreadStateSet;
- friend class G1ParTask;
+ friend class G1EvacuateRegionsTask;
friend class G1PLABAllocator;
- friend class G1PrepareCompactClosure;
// Other related classes.
friend class HeapRegionClaimer;
@@ -206,7 +205,7 @@
// Outside of GC pauses, the number of bytes used in all regions other
// than the current allocation region(s).
- size_t _summary_bytes_used;
+ volatile size_t _summary_bytes_used;
void increase_used(size_t bytes);
void decrease_used(size_t bytes);
@@ -519,6 +518,10 @@
WorkGang* workers() const { return _workers; }
+ // Runs the given AbstractGangTask with the current active workers, returning the
+ // total time taken.
+ Tickspan run_task(AbstractGangTask* task);
+
G1Allocator* allocator() {
return _allocator;
}
@@ -738,11 +741,14 @@
void calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms);
- // Actually do the work of evacuating the collection set.
- void evacuate_collection_set(G1ParScanThreadStateSet* per_thread_states);
+ // Actually do the work of evacuating the parts of the collection set.
+ void evacuate_initial_collection_set(G1ParScanThreadStateSet* per_thread_states);
void evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states);
- void evacuate_optional_regions(G1ParScanThreadStateSet* per_thread_states, G1OptionalCSet* ocset);
+private:
+ // Evacuate the next set of optional regions.
+ void evacuate_next_optional_regions(G1ParScanThreadStateSet* per_thread_states);
+public:
void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info);
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
@@ -1165,14 +1171,14 @@
void heap_region_par_iterate_from_start(HeapRegionClosure* cl,
HeapRegionClaimer* hrclaimer) const;
- // Iterate over the regions (if any) in the current collection set.
- void collection_set_iterate(HeapRegionClosure* blk);
+ // Iterate over all regions currently in the current collection set.
+ void collection_set_iterate_all(HeapRegionClosure* blk);
- // Iterate over the regions (if any) in the current collection set. Starts the
- // iteration over the entire collection set so that the start regions of a given
- // worker id over the set active_workers are evenly spread across the set of
- // collection set regions.
- void collection_set_iterate_from(HeapRegionClosure *blk, uint worker_id);
+ // Iterate over the regions in the current increment of the collection set.
+ // Starts the iteration so that the start regions of a given worker id over the
+ // set active_workers are evenly spread across the set of collection set regions
+ // to be iterated.
+ void collection_set_iterate_increment_from(HeapRegionClosure *blk, uint worker_id);
// Returns the HeapRegion that contains addr. addr must not be NULL.
template <class T>
@@ -1252,6 +1258,8 @@
uint eden_regions_count() const { return _eden.length(); }
uint survivor_regions_count() const { return _survivor.length(); }
+ size_t eden_regions_used_bytes() const { return _eden.used_bytes(); }
+ size_t survivor_regions_used_bytes() const { return _survivor.used_bytes(); }
uint young_regions_count() const { return _eden.length() + _survivor.length(); }
uint old_regions_count() const { return _old_set.length(); }
uint archive_regions_count() const { return _archive_set.length(); }
@@ -1420,7 +1428,7 @@
size_t _term_attempts;
void start_term_time() { _term_attempts++; _start_term = os::elapsedTime(); }
- void end_term_time() { _term_time += os::elapsedTime() - _start_term; }
+ void end_term_time() { _term_time += (os::elapsedTime() - _start_term); }
protected:
G1CollectedHeap* _g1h;
G1ParScanThreadState* _par_scan_state;
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -59,12 +59,11 @@
_collection_set_regions(NULL),
_collection_set_cur_length(0),
_collection_set_max_length(0),
- _optional_regions(NULL),
- _optional_region_length(0),
- _optional_region_max_length(0),
+ _num_optional_regions(0),
_bytes_used_before(0),
_recorded_rs_lengths(0),
_inc_build_state(Inactive),
+ _inc_part_start(0),
_inc_bytes_used_before(0),
_inc_recorded_rs_lengths(0),
_inc_recorded_rs_lengths_diffs(0),
@@ -90,8 +89,8 @@
assert((size_t) young_region_length() == _collection_set_cur_length,
"Young region length %u should match collection set length " SIZE_FORMAT, young_region_length(), _collection_set_cur_length);
- _old_region_length = 0;
- _optional_region_length = 0;
+ _old_region_length = 0;
+ free_optional_regions();
}
void G1CollectionSet::initialize(uint max_region_length) {
@@ -100,21 +99,8 @@
_collection_set_regions = NEW_C_HEAP_ARRAY(uint, max_region_length, mtGC);
}
-void G1CollectionSet::initialize_optional(uint max_length) {
- assert(_optional_regions == NULL, "Already initialized");
- assert(_optional_region_length == 0, "Already initialized");
- assert(_optional_region_max_length == 0, "Already initialized");
- _optional_region_max_length = max_length;
- _optional_regions = NEW_C_HEAP_ARRAY(HeapRegion*, _optional_region_max_length, mtGC);
-}
-
void G1CollectionSet::free_optional_regions() {
- _optional_region_length = 0;
- _optional_region_max_length = 0;
- if (_optional_regions != NULL) {
- FREE_C_HEAP_ARRAY(HeapRegion*, _optional_regions);
- _optional_regions = NULL;
- }
+ _num_optional_regions = 0;
}
void G1CollectionSet::clear_candidates() {
@@ -130,39 +116,32 @@
void G1CollectionSet::add_old_region(HeapRegion* hr) {
assert_at_safepoint_on_vm_thread();
- assert(_inc_build_state == Active || hr->index_in_opt_cset() != G1OptionalCSet::InvalidCSetIndex,
+ assert(_inc_build_state == Active,
"Precondition, actively building cset or adding optional later on");
assert(hr->is_old(), "the region should be old");
- assert(!hr->in_collection_set(), "should not already be in the CSet");
+ assert(!hr->in_collection_set(), "should not already be in the collection set");
_g1h->register_old_region_with_cset(hr);
_collection_set_regions[_collection_set_cur_length++] = hr->hrm_index();
assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set now larger than maximum size.");
_bytes_used_before += hr->used();
- size_t rs_length = hr->rem_set()->occupied();
- _recorded_rs_lengths += rs_length;
- _old_region_length += 1;
+ _recorded_rs_lengths += hr->rem_set()->occupied();
+ _old_region_length++;
- log_trace(gc, cset)("Added old region %d to collection set", hr->hrm_index());
+ _g1h->old_set_remove(hr);
}
void G1CollectionSet::add_optional_region(HeapRegion* hr) {
- assert(!optional_is_full(), "Precondition, must have room left for this region");
assert(hr->is_old(), "the region should be old");
assert(!hr->in_collection_set(), "should not already be in the CSet");
_g1h->register_optional_region_with_cset(hr);
- _optional_regions[_optional_region_length] = hr;
- uint index = _optional_region_length++;
- hr->set_index_in_opt_cset(index);
-
- log_trace(gc, cset)("Added region %d to optional collection set (%u)", hr->hrm_index(), _optional_region_length);
+ hr->set_index_in_opt_cset(_num_optional_regions++);
}
-// Initialize the per-collection-set information
void G1CollectionSet::start_incremental_building() {
assert(_collection_set_cur_length == 0, "Collection set must be empty before starting a new collection set.");
assert(_inc_build_state == Inactive, "Precondition");
@@ -173,7 +152,8 @@
_inc_recorded_rs_lengths_diffs = 0;
_inc_predicted_elapsed_time_ms = 0.0;
_inc_predicted_elapsed_time_ms_diffs = 0.0;
- _inc_build_state = Active;
+
+ update_incremental_marker();
}
void G1CollectionSet::finalize_incremental_building() {
@@ -211,29 +191,48 @@
void G1CollectionSet::clear() {
assert_at_safepoint_on_vm_thread();
_collection_set_cur_length = 0;
- _optional_region_length = 0;
}
void G1CollectionSet::iterate(HeapRegionClosure* cl) const {
- iterate_from(cl, 0, 1);
-}
-
-void G1CollectionSet::iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const {
size_t len = _collection_set_cur_length;
OrderAccess::loadload();
- if (len == 0) {
- return;
- }
- size_t start_pos = (worker_id * len) / total_workers;
- size_t cur_pos = start_pos;
- do {
- HeapRegion* r = _g1h->region_at(_collection_set_regions[cur_pos]);
+ for (uint i = 0; i < len; i++) {
+ HeapRegion* r = _g1h->region_at(_collection_set_regions[i]);
bool result = cl->do_heap_region(r);
if (result) {
cl->set_incomplete();
return;
}
+ }
+}
+
+void G1CollectionSet::iterate_optional(HeapRegionClosure* cl) const {
+ assert_at_safepoint();
+
+ for (uint i = 0; i < _num_optional_regions; i++) {
+ HeapRegion* r = _candidates->at(i);
+ bool result = cl->do_heap_region(r);
+ guarantee(!result, "Must not cancel iteration");
+ }
+}
+
+void G1CollectionSet::iterate_incremental_part_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const {
+ assert_at_safepoint();
+
+ size_t len = _collection_set_cur_length - _inc_part_start;
+ if (len == 0) {
+ return;
+ }
+
+ size_t start_pos = (worker_id * len) / total_workers;
+ size_t cur_pos = start_pos;
+
+ do {
+ HeapRegion* r = _g1h->region_at(_collection_set_regions[cur_pos + _inc_part_start]);
+ bool result = cl->do_heap_region(r);
+ guarantee(!result, "Must not cancel iteration");
+
cur_pos++;
if (cur_pos == len) {
cur_pos = 0;
@@ -440,30 +439,6 @@
return time_remaining_ms;
}
-void G1CollectionSet::add_as_old(HeapRegion* hr) {
- candidates()->pop_front(); // already have region via peek()
- _g1h->old_set_remove(hr);
- add_old_region(hr);
-}
-
-void G1CollectionSet::add_as_optional(HeapRegion* hr) {
- assert(_optional_regions != NULL, "Must not be called before array is allocated");
- candidates()->pop_front(); // already have region via peek()
- _g1h->old_set_remove(hr);
- add_optional_region(hr);
-}
-
-bool G1CollectionSet::optional_is_full() {
- assert(_optional_region_length <= _optional_region_max_length, "Invariant");
- return _optional_region_length == _optional_region_max_length;
-}
-
-void G1CollectionSet::clear_optional_region(const HeapRegion* hr) {
- assert(_optional_regions != NULL, "Must not be called before array is allocated");
- uint index = hr->index_in_opt_cset();
- _optional_regions[index] = NULL;
-}
-
static int compare_region_idx(const uint a, const uint b) {
if (a > b) {
return 1;
@@ -476,87 +451,25 @@
void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
double non_young_start_time_sec = os::elapsedTime();
- double predicted_old_time_ms = 0.0;
- double predicted_optional_time_ms = 0.0;
- double optional_threshold_ms = time_remaining_ms * _policy->optional_prediction_fraction();
- uint expensive_region_num = 0;
if (collector_state()->in_mixed_phase()) {
candidates()->verify();
- const uint min_old_cset_length = _policy->calc_min_old_cset_length();
- const uint max_old_cset_length = MAX2(min_old_cset_length, _policy->calc_max_old_cset_length());
- bool check_time_remaining = _policy->adaptive_young_list_length();
- initialize_optional(max_old_cset_length - min_old_cset_length);
- log_debug(gc, ergo, cset)("Start adding old regions for mixed gc. min %u regions, max %u regions, "
- "time remaining %1.2fms, optional threshold %1.2fms",
- min_old_cset_length, max_old_cset_length, time_remaining_ms, optional_threshold_ms);
-
- HeapRegion* hr = candidates()->peek_front();
- while (hr != NULL) {
- if (old_region_length() + optional_region_length() >= max_old_cset_length) {
- // Added maximum number of old regions to the CSet.
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). "
- "old %u regions, optional %u regions",
- old_region_length(), optional_region_length());
- break;
- }
-
- // Stop adding regions if the remaining reclaimable space is
- // not above G1HeapWastePercent.
- size_t reclaimable_bytes = candidates()->remaining_reclaimable_bytes();
- double reclaimable_percent = _policy->reclaimable_bytes_percent(reclaimable_bytes);
- double threshold = (double) G1HeapWastePercent;
- if (reclaimable_percent <= threshold) {
- // We've added enough old regions that the amount of uncollected
- // reclaimable space is at or below the waste threshold. Stop
- // adding old regions to the CSet.
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
- "reclaimable: " SIZE_FORMAT "%s (%1.2f%%) threshold: " UINTX_FORMAT "%%",
- byte_size_in_proper_unit(reclaimable_bytes), proper_unit_for_byte_size(reclaimable_bytes),
- reclaimable_percent, G1HeapWastePercent);
- break;
- }
+ uint num_initial_old_regions;
+ uint num_optional_old_regions;
- double predicted_time_ms = predict_region_elapsed_time_ms(hr);
- time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
- // Add regions to old set until we reach minimum amount
- if (old_region_length() < min_old_cset_length) {
- predicted_old_time_ms += predicted_time_ms;
- add_as_old(hr);
- // Record the number of regions added when no time remaining
- if (time_remaining_ms == 0.0) {
- expensive_region_num++;
- }
- } else {
- // In the non-auto-tuning case, we'll finish adding regions
- // to the CSet if we reach the minimum.
- if (!check_time_remaining) {
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached min).");
- break;
- }
- // Keep adding regions to old set until we reach optional threshold
- if (time_remaining_ms > optional_threshold_ms) {
- predicted_old_time_ms += predicted_time_ms;
- add_as_old(hr);
- } else if (time_remaining_ms > 0) {
- // Keep adding optional regions until time is up
- if (!optional_is_full()) {
- predicted_optional_time_ms += predicted_time_ms;
- add_as_optional(hr);
- } else {
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (optional set full).");
- break;
- }
- } else {
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high).");
- break;
- }
- }
- hr = candidates()->peek_front();
- }
- if (hr == NULL) {
- log_debug(gc, ergo, cset)("Finish adding old regions to CSet (candidate old regions not available)");
+ _policy->calculate_old_collection_set_regions(candidates(),
+ time_remaining_ms,
+ num_initial_old_regions,
+ num_optional_old_regions);
+
+ // Prepare initial old regions.
+ move_candidates_to_collection_set(num_initial_old_regions);
+
+ // Prepare optional old regions for evacuation.
+ uint candidate_idx = candidates()->cur_idx();
+ for (uint i = 0; i < num_optional_old_regions; i++) {
+ add_optional_region(candidates()->at(candidate_idx + i));
}
candidates()->verify();
@@ -564,99 +477,59 @@
stop_incremental_building();
- log_debug(gc, ergo, cset)("Finish choosing CSet regions old: %u, optional: %u, "
- "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f",
- old_region_length(), optional_region_length(),
- predicted_old_time_ms, predicted_optional_time_ms, time_remaining_ms);
- if (expensive_region_num > 0) {
- log_debug(gc, ergo, cset)("CSet contains %u old regions that were added although the predicted time was too high.",
- expensive_region_num);
- }
-
double non_young_end_time_sec = os::elapsedTime();
phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
QuickSort::sort(_collection_set_regions, _collection_set_cur_length, compare_region_idx, true);
}
-HeapRegion* G1OptionalCSet::region_at(uint index) {
- return _cset->optional_region_at(index);
+void G1CollectionSet::move_candidates_to_collection_set(uint num_old_candidate_regions) {
+ if (num_old_candidate_regions == 0) {
+ return;
+ }
+ uint candidate_idx = candidates()->cur_idx();
+ for (uint i = 0; i < num_old_candidate_regions; i++) {
+ HeapRegion* r = candidates()->at(candidate_idx + i);
+ // This potentially optional candidate region is going to be an actual collection
+ // set region. Clear cset marker.
+ _g1h->clear_in_cset(r);
+ add_old_region(r);
+ }
+ candidates()->remove(num_old_candidate_regions);
+
+ candidates()->verify();
}
-void G1OptionalCSet::prepare_evacuation(double time_limit) {
- assert(_current_index == _current_limit, "Before prepare no regions should be ready for evac");
-
- uint prepared_regions = 0;
- double prediction_ms = 0;
-
- _prepare_failed = true;
- for (uint i = _current_index; i < _cset->optional_region_length(); i++) {
- HeapRegion* hr = region_at(i);
- prediction_ms += _cset->predict_region_elapsed_time_ms(hr);
- if (prediction_ms > time_limit) {
- log_debug(gc, cset)("Prepared %u regions for optional evacuation. Predicted time: %.3fms", prepared_regions, prediction_ms);
- return;
- }
-
- // This region will be included in the next optional evacuation.
- prepare_to_evacuate_optional_region(hr);
- prepared_regions++;
- _current_limit++;
- _prepare_failed = false;
- }
-
- log_debug(gc, cset)("Prepared all %u regions for optional evacuation. Predicted time: %.3fms",
- prepared_regions, prediction_ms);
-}
-
-bool G1OptionalCSet::prepare_failed() {
- return _prepare_failed;
+void G1CollectionSet::finalize_initial_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
+ double time_remaining_ms = finalize_young_part(target_pause_time_ms, survivor);
+ finalize_old_part(time_remaining_ms);
}
-void G1OptionalCSet::complete_evacuation() {
- _evacuation_failed = false;
- for (uint i = _current_index; i < _current_limit; i++) {
- HeapRegion* hr = region_at(i);
- _cset->clear_optional_region(hr);
- if (hr->evacuation_failed()){
- _evacuation_failed = true;
- }
- }
- _current_index = _current_limit;
-}
+bool G1CollectionSet::finalize_optional_for_evacuation(double remaining_pause_time) {
+ update_incremental_marker();
-bool G1OptionalCSet::evacuation_failed() {
- return _evacuation_failed;
+ uint num_selected_regions;
+ _policy->calculate_optional_collection_set_regions(candidates(),
+ _num_optional_regions,
+ remaining_pause_time,
+ num_selected_regions);
+
+ move_candidates_to_collection_set(num_selected_regions);
+
+ _num_optional_regions -= num_selected_regions;
+
+ stop_incremental_building();
+ return num_selected_regions > 0;
}
-G1OptionalCSet::~G1OptionalCSet() {
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- while (!is_empty()) {
- // We want to return regions not evacuated to the collection set candidates
- // in reverse order to maintain the old order.
- HeapRegion* hr = _cset->remove_last_optional_region();
- assert(hr != NULL, "Should be valid region left");
- _pset->record_unused_optional_region(hr);
- g1h->old_set_add(hr);
- g1h->clear_in_cset(hr);
- hr->set_index_in_opt_cset(InvalidCSetIndex);
- _cset->candidates()->push_front(hr);
+void G1CollectionSet::abandon_optional_collection_set(G1ParScanThreadStateSet* pss) {
+ for (uint i = 0; i < _num_optional_regions; i++) {
+ HeapRegion* r = candidates()->at(candidates()->cur_idx() + i);
+ pss->record_unused_optional_region(r);
+ _g1h->clear_in_cset(r);
+ r->clear_index_in_opt_cset();
}
- _cset->free_optional_regions();
-}
-
-uint G1OptionalCSet::size() {
- return _cset->optional_region_length() - _current_index;
-}
-
-bool G1OptionalCSet::is_empty() {
- return size() == 0;
-}
-
-void G1OptionalCSet::prepare_to_evacuate_optional_region(HeapRegion* hr) {
- log_trace(gc, cset)("Adding region %u for optional evacuation", hr->hrm_index());
- G1CollectedHeap::heap()->clear_in_cset(hr);
- _cset->add_old_region(hr);
+ free_optional_regions();
}
#ifdef ASSERT
--- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -38,11 +38,101 @@
class HeapRegion;
class HeapRegionClosure;
+// The collection set.
+//
+// The set of regions that are evacuated during an evacuation pause.
+//
+// At the end of a collection, before freeing the collection set, this set
+// contains all regions that were evacuated during this collection:
+//
+// - survivor regions from the last collection (if any)
+// - eden regions allocated by the mutator
+// - old gen regions evacuated during mixed gc
+//
+// This set is built incrementally at mutator time as regions are retired, and
+// if this had been a mixed gc, some additional (during gc) incrementally added
+// old regions from the collection set candidates built during the concurrent
+// cycle.
+//
+// A more detailed overview of how the collection set changes over time follows:
+//
+// 0) at the end of GC the survivor regions are added to this collection set.
+// 1) the mutator incrementally adds eden regions as they retire
+//
+// ----- gc starts
+//
+// 2) prepare (finalize) young regions of the collection set for collection
+// - relabel the survivors as eden
+// - finish up the incremental building that happened at mutator time
+//
+// iff this is a young-only collection:
+//
+// a3) evacuate the current collection set in one "initial evacuation" phase
+//
+// iff this is a mixed collection:
+//
+// b3) calculate the set of old gen regions we may be able to collect in this
+// collection from the list of collection set candidates.
+// - one part is added to the current collection set
+// - the remainder regions are labeled as optional, and NOT yet added to the
+// collection set.
+// b4) evacuate the current collection set in the "initial evacuation" phase
+// b5) evacuate the optional regions in the "optional evacuation" phase. This is
+// done in increments (or rounds).
+// b5-1) add a few of the optional regions to the current collection set
+// b5-2) evacuate only these newly added optional regions. For this mechanism we
+// reuse the incremental collection set building infrastructure (used also at
+// mutator time).
+// b5-3) repeat from b5-1 until the policy determines we are done
+//
+// all collections
+//
+// 6) free the collection set (contains all regions now; empties collection set
+// afterwards)
+// 7) add survivors to this collection set
+//
+// ----- gc ends
+//
+// goto 1)
+//
+// Examples of how the collection set might look over time:
+//
+// Legend:
+// S = survivor, E = eden, O = old.
+// |xxxx| = increment (with increment markers), containing four regions
+//
+// |SSSS| ... after step 0), with four survivor regions
+// |SSSSEE| ... at step 1), after retiring two eden regions
+// |SSSSEEEE| ... after step 1), after retiring four eden regions
+// |EEEEEEEE| ... after step 2)
+//
+// iff this is a young-only collection
+//
+// EEEEEEEE|| ... after step a3), after initial evacuation phase
+// || ... after step 6)
+// |SS| ... after step 7), with two survivor regions
+//
+// iff this is a mixed collection
+//
+// |EEEEEEEEOOOO| ... after step b3), added four regions to be
+// evacuated in the "initial evacuation" phase
+// EEEEEEEEOOOO|| ... after step b4), incremental part is empty
+// after evacuation
+// EEEEEEEEOOOO|OO| ... after step b5.1), added two regions to be
+// evacuated in the first round of the
+// "optional evacuation" phase
+// EEEEEEEEOOOOOO|O| ... after step b5.1), added one region to be
+// evacuated in the second round of the
+// "optional evacuation" phase
+// EEEEEEEEOOOOOOO|| ... after step b5), the complete collection set.
+// || ... after step b6)
+// |SSS| ... after step 7), with three survivor regions
+//
class G1CollectionSet {
G1CollectedHeap* _g1h;
G1Policy* _policy;
- // All old gen collection set candidate regions for the current mixed gc phase.
+ // All old gen collection set candidate regions for the current mixed phase.
G1CollectionSetCandidates* _candidates;
uint _eden_region_length;
@@ -51,7 +141,7 @@
// The actual collection set as a set of region indices.
// All entries in _collection_set_regions below _collection_set_cur_length are
- // assumed to be valid entries.
+ // assumed to be part of the collection set.
// We assume that at any time there is at most only one writer and (one or more)
// concurrent readers. This means we are good with using storestore and loadload
// barriers on the writer and reader respectively only.
@@ -59,31 +149,33 @@
volatile size_t _collection_set_cur_length;
size_t _collection_set_max_length;
- // When doing mixed collections we can add old regions to the collection, which
- // can be collected if there is enough time. We call these optional regions and
- // the pointer to these regions are stored in the array below.
- HeapRegion** _optional_regions;
- uint _optional_region_length;
- uint _optional_region_max_length;
+ // When doing mixed collections we can add old regions to the collection set, which
+ // will be collected only if there is enough time. We call these optional regions.
+ // This member records the current number of regions that are of that type that
+ // correspond to the first x entries in the collection set candidates.
+ uint _num_optional_regions;
// The number of bytes in the collection set before the pause. Set from
// the incrementally built collection set at the start of an evacuation
- // pause, and incremented in finalize_old_part() when adding old regions
- // (if any) to the collection set.
+ // pause, and updated as more regions are added to the collection set.
size_t _bytes_used_before;
+ // The number of cards in the remembered set in the collection set. Set from
+ // the incrementally built collection set at the start of an evacuation
+ // pause, and updated as more regions are added to the collection set.
size_t _recorded_rs_lengths;
- // The associated information that is maintained while the incremental
- // collection set is being built with young regions. Used to populate
- // the recorded info for the evacuation pause.
-
enum CSetBuildType {
Active, // We are actively building the collection set
Inactive // We are not actively building the collection set
};
CSetBuildType _inc_build_state;
+ size_t _inc_part_start;
+
+ // The associated information that is maintained while the incremental
+ // collection set is being built with *young* regions. Used to populate
+ // the recorded info for the evacuation pause.
// The number of bytes in the incrementally built collection set.
// Used to set _collection_set_bytes_used_before at the start of
@@ -113,22 +205,44 @@
// See the comment for _inc_recorded_rs_lengths_diffs.
double _inc_predicted_elapsed_time_ms_diffs;
+ void set_recorded_rs_lengths(size_t rs_lengths);
+
G1CollectorState* collector_state();
G1GCPhaseTimes* phase_times();
void verify_young_cset_indices() const NOT_DEBUG_RETURN;
- void add_as_optional(HeapRegion* hr);
- void add_as_old(HeapRegion* hr);
- bool optional_is_full();
+
+ double predict_region_elapsed_time_ms(HeapRegion* hr);
+
+ // Update the incremental collection set information when adding a region.
+ void add_young_region_common(HeapRegion* hr);
+
+ // Add old region "hr" to the collection set.
+ void add_old_region(HeapRegion* hr);
+ void free_optional_regions();
+
+ // Add old region "hr" to optional collection set.
+ void add_optional_region(HeapRegion* hr);
+ void move_candidates_to_collection_set(uint num_regions);
+
+ // Finalize the young part of the initial collection set. Relabel survivor regions
+ // as Eden and calculate a prediction on how long the evacuation of all young regions
+ // will take.
+ double finalize_young_part(double target_pause_time_ms, G1SurvivorRegions* survivors);
+ // Perform any final calculations on the incremental collection set fields before we
+ // can use them.
+ void finalize_incremental_building();
+
+ // Select the old regions of the initial collection set and determine how many optional
+ // regions we might be able to evacuate in this pause.
+ void finalize_old_part(double time_remaining_ms);
public:
G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy);
~G1CollectionSet();
// Initializes the collection set giving the maximum possible length of the collection set.
void initialize(uint max_region_length);
- void initialize_optional(uint max_length);
- void free_optional_regions();
void clear_candidates();
@@ -141,8 +255,6 @@
void init_region_lengths(uint eden_cset_region_length,
uint survivor_cset_region_length);
- void set_recorded_rs_lengths(size_t rs_lengths);
-
uint region_length() const { return young_region_length() +
old_region_length(); }
uint young_region_length() const { return eden_region_length() +
@@ -151,32 +263,29 @@
uint eden_region_length() const { return _eden_region_length; }
uint survivor_region_length() const { return _survivor_region_length; }
uint old_region_length() const { return _old_region_length; }
- uint optional_region_length() const { return _optional_region_length; }
+ uint optional_region_length() const { return _num_optional_regions; }
+
+ // Reset the contents of the collection set.
+ void clear();
// Incremental collection set support
// Initialize incremental collection set info.
void start_incremental_building();
-
- // Perform any final calculations on the incremental collection set fields
- // before we can use them.
- void finalize_incremental_building();
+ // Start a new collection set increment.
+ void update_incremental_marker() { _inc_build_state = Active; _inc_part_start = _collection_set_cur_length; }
+ // Stop adding regions to the current collection set increment.
+ void stop_incremental_building() { _inc_build_state = Inactive; }
- // Reset the contents of the collection set.
- void clear();
+ // Iterate over the current collection set increment applying the given HeapRegionClosure
+ // from a starting position determined by the given worker id.
+ void iterate_incremental_part_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const;
- // Iterate over the collection set, applying the given HeapRegionClosure on all of them.
- // If may_be_aborted is true, iteration may be aborted using the return value of the
- // called closure method.
+ // Iterate over the entire collection set (all increments calculated so far), applying
+ // the given HeapRegionClosure on all of them.
void iterate(HeapRegionClosure* cl) const;
- // Iterate over the collection set, applying the given HeapRegionClosure on all of them,
- // trying to optimally spread out starting position of total_workers workers given the
- // caller's worker_id.
- void iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const;
-
- // Stop adding regions to the incremental collection set.
- void stop_incremental_building() { _inc_build_state = Inactive; }
+ void iterate_optional(HeapRegionClosure* cl) const;
size_t recorded_rs_lengths() { return _recorded_rs_lengths; }
@@ -188,16 +297,14 @@
_bytes_used_before = 0;
}
- // Choose a new collection set. Marks the chosen regions as being
- // "in_collection_set".
- double finalize_young_part(double target_pause_time_ms, G1SurvivorRegions* survivors);
- void finalize_old_part(double time_remaining_ms);
-
- // Add old region "hr" to the collection set.
- void add_old_region(HeapRegion* hr);
-
- // Add old region "hr" to optional collection set.
- void add_optional_region(HeapRegion* hr);
+ // Finalize the initial collection set consisting of all young regions potentially a
+ // few old gen regions.
+ void finalize_initial_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
+ // Finalize the next collection set from the set of available optional old gen regions.
+ bool finalize_optional_for_evacuation(double remaining_pause_time);
+ // Abandon (clean up) optional collection set regions that were not evacuated in this
+ // pause.
+ void abandon_optional_collection_set(G1ParScanThreadStateSet* pss);
// Update information about hr in the aggregated information for
// the incrementally built collection set.
@@ -214,73 +321,6 @@
void print(outputStream* st);
#endif // !PRODUCT
-
- double predict_region_elapsed_time_ms(HeapRegion* hr);
-
- void clear_optional_region(const HeapRegion* hr);
-
- HeapRegion* optional_region_at(uint i) const {
- assert(_optional_regions != NULL, "Not yet initialized");
- assert(i < _optional_region_length, "index %u out of bounds (%u)", i, _optional_region_length);
- return _optional_regions[i];
- }
-
- HeapRegion* remove_last_optional_region() {
- assert(_optional_regions != NULL, "Not yet initialized");
- assert(_optional_region_length != 0, "No region to remove");
- _optional_region_length--;
- HeapRegion* removed = _optional_regions[_optional_region_length];
- _optional_regions[_optional_region_length] = NULL;
- return removed;
- }
-
-private:
- // Update the incremental collection set information when adding a region.
- void add_young_region_common(HeapRegion* hr);
-};
-
-// Helper class to manage the optional regions in a Mixed collection.
-class G1OptionalCSet : public StackObj {
-private:
- G1CollectionSet* _cset;
- G1ParScanThreadStateSet* _pset;
- uint _current_index;
- uint _current_limit;
- bool _prepare_failed;
- bool _evacuation_failed;
-
- void prepare_to_evacuate_optional_region(HeapRegion* hr);
-
-public:
- static const uint InvalidCSetIndex = UINT_MAX;
-
- G1OptionalCSet(G1CollectionSet* cset, G1ParScanThreadStateSet* pset) :
- _cset(cset),
- _pset(pset),
- _current_index(0),
- _current_limit(0),
- _prepare_failed(false),
- _evacuation_failed(false) { }
- // The destructor returns regions to the collection set candidates set and
- // frees the optional structure in the collection set.
- ~G1OptionalCSet();
-
- uint current_index() { return _current_index; }
- uint current_limit() { return _current_limit; }
-
- uint size();
- bool is_empty();
-
- HeapRegion* region_at(uint index);
-
- // Prepare a set of regions for optional evacuation.
- void prepare_evacuation(double time_left_ms);
- bool prepare_failed();
-
- // Complete the evacuation of the previously prepared
- // regions by updating their state and check for failures.
- void complete_evacuation();
- bool evacuation_failed();
};
#endif // SHARE_GC_G1_G1COLLECTIONSET_HPP
--- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -27,26 +27,12 @@
#include "gc/g1/g1CollectionSetChooser.hpp"
#include "gc/g1/heapRegion.inline.hpp"
-HeapRegion* G1CollectionSetCandidates::pop_front() {
- assert(_front_idx < _num_regions, "pre-condition");
- HeapRegion* hr = _regions[_front_idx];
- assert(hr != NULL, "pre-condition");
- _regions[_front_idx] = NULL;
- assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
- "Remaining reclaimable bytes inconsistent "
- "from region: " SIZE_FORMAT " remaining: " SIZE_FORMAT,
- hr->reclaimable_bytes(), _remaining_reclaimable_bytes);
- _remaining_reclaimable_bytes -= hr->reclaimable_bytes();
- _front_idx++;
- return hr;
-}
-
-void G1CollectionSetCandidates::push_front(HeapRegion* hr) {
- assert(hr != NULL, "Can't put back a NULL region");
- assert(_front_idx >= 1, "Too many regions have been put back.");
- _front_idx--;
- _regions[_front_idx] = hr;
- _remaining_reclaimable_bytes += hr->reclaimable_bytes();
+void G1CollectionSetCandidates::remove(uint num_regions) {
+ assert(num_regions <= num_remaining(), "Trying to remove more regions (%u) than available (%u)", num_regions, num_remaining());
+ for (uint i = 0; i < num_regions; i++) {
+ _remaining_reclaimable_bytes -= at(_front_idx)->reclaimable_bytes();
+ _front_idx++;
+ }
}
void G1CollectionSetCandidates::iterate(HeapRegionClosure* cl) {
@@ -62,13 +48,8 @@
#ifndef PRODUCT
void G1CollectionSetCandidates::verify() const {
guarantee(_front_idx <= _num_regions, "Index: %u Num_regions: %u", _front_idx, _num_regions);
- uint idx = 0;
+ uint idx = _front_idx;
size_t sum_of_reclaimable_bytes = 0;
- while (idx < _front_idx) {
- guarantee(_regions[idx] == NULL, "All entries before _front_idx %u should be NULL, but %u is not",
- _front_idx, idx);
- idx++;
- }
HeapRegion *prev = NULL;
for (; idx < _num_regions; idx++) {
HeapRegion *cur = _regions[idx];
--- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -63,22 +63,18 @@
// Returns the total number of collection set candidate old regions added.
uint num_regions() { return _num_regions; }
- // Return the candidate region at the cursor position to be considered for collection without
- // removing it.
- HeapRegion* peek_front() {
+ uint cur_idx() const { return _front_idx; }
+
+ HeapRegion* at(uint idx) const {
HeapRegion* res = NULL;
- if (_front_idx < _num_regions) {
- res = _regions[_front_idx];
- assert(res != NULL, "Unexpected NULL HeapRegion at index %u", _front_idx);
+ if (idx < _num_regions) {
+ res = _regions[idx];
+ assert(res != NULL, "Unexpected NULL HeapRegion at index %u", idx);
}
return res;
}
- // Remove the given region from the candidates set and move the cursor to the next one.
- HeapRegion* pop_front();
-
- // Add the given HeapRegion to the front of the collection set candidate set again.
- void push_front(HeapRegion* hr);
+ void remove(uint num_regions);
// Iterate over all remaining collection set candidate regions.
void iterate(HeapRegionClosure* cl);
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1940,9 +1940,10 @@
guarantee(oopDesc::is_oop(task_entry.obj()),
"Non-oop " PTR_FORMAT ", phase: %s, info: %d",
p2i(task_entry.obj()), _phase, _info);
- guarantee(!_g1h->is_in_cset(task_entry.obj()),
- "obj: " PTR_FORMAT " in CSet, phase: %s, info: %d",
- p2i(task_entry.obj()), _phase, _info);
+ HeapRegion* r = _g1h->heap_region_containing(task_entry.obj());
+ guarantee(!(r->in_collection_set() || r->has_index_in_opt_cset()),
+ "obj " PTR_FORMAT " from %s (%d) in region %u in (optional) collection set",
+ p2i(task_entry.obj()), _phase, _info, r->hrm_index());
}
};
@@ -1979,11 +1980,11 @@
HeapWord* task_finger = task->finger();
if (task_finger != NULL && task_finger < _heap.end()) {
// See above note on the global finger verification.
- HeapRegion* task_hr = _g1h->heap_region_containing(task_finger);
- guarantee(task_hr == NULL || task_finger == task_hr->bottom() ||
- !task_hr->in_collection_set(),
+ HeapRegion* r = _g1h->heap_region_containing(task_finger);
+ guarantee(r == NULL || task_finger == r->bottom() ||
+ !r->in_collection_set() || !r->has_index_in_opt_cset(),
"task finger: " PTR_FORMAT " region: " HR_FORMAT,
- p2i(task_finger), HR_FORMAT_PARAMS(task_hr));
+ p2i(task_finger), HR_FORMAT_PARAMS(r));
}
}
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -127,7 +127,7 @@
}
void G1ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) {
- if (g1_policy->adaptive_young_list_length()) {
+ if (g1_policy->use_adaptive_young_list_length()) {
jlong sleep_time_ms = mmu_sleep_time(g1_policy, remark);
if (!_cm->has_aborted() && sleep_time_ms > 0) {
os::sleep(this, sleep_time_ms, false);
--- a/src/hotspot/share/gc/g1/g1EdenRegions.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1EdenRegions.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -31,19 +31,28 @@
class G1EdenRegions {
private:
- int _length;
+ int _length;
+ // Sum of used bytes from all retired eden regions.
+ // I.e. updated when mutator regions are retired.
+ volatile size_t _used_bytes;
public:
- G1EdenRegions() : _length(0) {}
+ G1EdenRegions() : _length(0), _used_bytes(0) { }
void add(HeapRegion* hr) {
assert(!hr->is_eden(), "should not already be set");
_length++;
}
- void clear() { _length = 0; }
+ void clear() { _length = 0; _used_bytes = 0; }
uint length() const { return _length; }
+
+ size_t used_bytes() const { return _used_bytes; }
+
+ void add_used_bytes(size_t used_bytes) {
+ _used_bytes += used_bytes;
+ }
};
#endif // SHARE_GC_G1_G1EDENREGIONS_HPP
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -228,6 +228,8 @@
if (_hrclaimer->claim_region(hr->hrm_index())) {
if (hr->evacuation_failed()) {
+ hr->clear_index_in_opt_cset();
+
bool during_initial_mark = _g1h->collector_state()->in_initial_mark_gc();
bool during_conc_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
@@ -257,5 +259,5 @@
void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_hrclaimer);
- _g1h->collection_set_iterate_from(&rsfp_cl, worker_id);
+ _g1h->collection_set_iterate_increment_from(&rsfp_cl, worker_id);
}
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -76,10 +76,12 @@
}
_gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms):");
_gc_par_phases[OptScanRS] = new WorkerDataArray<double>(max_gc_threads, "Optional Scan RS (ms):");
- _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms):");
+ _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scan (ms):");
+ _gc_par_phases[OptCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Optional Code Root Scan (ms):");
_gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms):");
_gc_par_phases[OptObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Optional Object Copy (ms):");
_gc_par_phases[Termination] = new WorkerDataArray<double>(max_gc_threads, "Termination (ms):");
+ _gc_par_phases[OptTermination] = new WorkerDataArray<double>(max_gc_threads, "Optional Termination (ms):");
_gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Total (ms):");
_gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>(max_gc_threads, "GC Worker End (ms):");
_gc_par_phases[Other] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Other (ms):");
@@ -91,14 +93,16 @@
_scan_rs_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
_gc_par_phases[ScanRS]->link_thread_work_items(_scan_rs_skipped_cards, ScanRSSkippedCards);
- _opt_cset_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_cset_scanned_cards, OptCSetScannedCards);
- _opt_cset_claimed_cards = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_cset_claimed_cards, OptCSetClaimedCards);
- _opt_cset_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_cset_skipped_cards, OptCSetSkippedCards);
- _opt_cset_used_memory = new WorkerDataArray<size_t>(max_gc_threads, "Used Memory:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_cset_used_memory, OptCSetUsedMemory);
+ _opt_scan_rs_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
+ _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_scanned_cards, ScanRSScannedCards);
+ _opt_scan_rs_claimed_cards = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Cards:");
+ _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_claimed_cards, ScanRSClaimedCards);
+ _opt_scan_rs_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
+ _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_skipped_cards, ScanRSSkippedCards);
+ _opt_scan_rs_scanned_opt_refs = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Refs:");
+ _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_scanned_opt_refs, ScanRSScannedOptRefs);
+ _opt_scan_rs_used_memory = new WorkerDataArray<size_t>(max_gc_threads, "Used Memory:");
+ _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_used_memory, ScanRSUsedMemory);
_update_rs_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers:");
_gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers, UpdateRSProcessedBuffers);
@@ -112,9 +116,17 @@
_obj_copy_lab_undo_waste = new WorkerDataArray<size_t>(max_gc_threads, "LAB Undo Waste");
_gc_par_phases[ObjCopy]->link_thread_work_items(_obj_copy_lab_undo_waste, ObjCopyLABUndoWaste);
+ _opt_obj_copy_lab_waste = new WorkerDataArray<size_t>(max_gc_threads, "LAB Waste");
+ _gc_par_phases[OptObjCopy]->link_thread_work_items(_obj_copy_lab_waste, ObjCopyLABWaste);
+ _opt_obj_copy_lab_undo_waste = new WorkerDataArray<size_t>(max_gc_threads, "LAB Undo Waste");
+ _gc_par_phases[OptObjCopy]->link_thread_work_items(_obj_copy_lab_undo_waste, ObjCopyLABUndoWaste);
+
_termination_attempts = new WorkerDataArray<size_t>(max_gc_threads, "Termination Attempts:");
_gc_par_phases[Termination]->link_thread_work_items(_termination_attempts);
+ _opt_termination_attempts = new WorkerDataArray<size_t>(max_gc_threads, "Optional Termination Attempts:");
+ _gc_par_phases[OptTermination]->link_thread_work_items(_opt_termination_attempts);
+
if (UseStringDeduplication) {
_gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray<double>(max_gc_threads, "Queue Fixup (ms):");
_gc_par_phases[StringDedupTableFixup] = new WorkerDataArray<double>(max_gc_threads, "Table Fixup (ms):");
@@ -134,7 +146,7 @@
}
void G1GCPhaseTimes::reset() {
- _cur_collection_par_time_ms = 0.0;
+ _cur_collection_initial_evac_time_ms = 0.0;
_cur_optional_evac_ms = 0.0;
_cur_collection_code_root_fixup_time_ms = 0.0;
_cur_strong_code_root_purge_time_ms = 0.0;
@@ -251,6 +263,10 @@
}
}
+double G1GCPhaseTimes::get_time_secs(GCParPhases phase, uint worker_i) {
+ return _gc_par_phases[phase]->get(worker_i);
+}
+
void G1GCPhaseTimes::record_thread_work_item(GCParPhases phase, uint worker_i, size_t count, uint index) {
_gc_par_phases[phase]->set_thread_work_item(worker_i, count, index);
}
@@ -259,6 +275,10 @@
_gc_par_phases[phase]->set_or_add_thread_work_item(worker_i, count, index);
}
+size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i, uint index) {
+ return _gc_par_phases[phase]->get_thread_work_item(worker_i, index);
+}
+
// return the average time for a phase in milliseconds
double G1GCPhaseTimes::average_time_ms(GCParPhases phase) {
return _gc_par_phases[phase]->average() * 1000.0;
@@ -374,12 +394,14 @@
info_time("Evacuate Optional Collection Set", sum_ms);
debug_phase(_gc_par_phases[OptScanRS]);
debug_phase(_gc_par_phases[OptObjCopy]);
+ debug_phase(_gc_par_phases[OptCodeRoots]);
+ debug_phase(_gc_par_phases[OptTermination]);
}
return sum_ms;
}
double G1GCPhaseTimes::print_evacuate_collection_set() const {
- const double sum_ms = _cur_collection_par_time_ms;
+ const double sum_ms = _cur_collection_initial_evac_time_ms;
info_time("Evacuate Collection Set", sum_ms);
@@ -517,9 +539,11 @@
"ScanRS",
"OptScanRS",
"CodeRoots",
+ "OptCodeRoots",
"ObjCopy",
"OptObjCopy",
"Termination",
+ "OptTermination",
"Other",
"GCWorkerTotal",
"GCWorkerEnd",
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -67,9 +67,11 @@
ScanRS,
OptScanRS,
CodeRoots,
+ OptCodeRoots,
ObjCopy,
OptObjCopy,
Termination,
+ OptTermination,
Other,
GCWorkerTotal,
GCWorkerEnd,
@@ -87,7 +89,9 @@
enum GCScanRSWorkItems {
ScanRSScannedCards,
ScanRSClaimedCards,
- ScanRSSkippedCards
+ ScanRSSkippedCards,
+ ScanRSScannedOptRefs,
+ ScanRSUsedMemory
};
enum GCUpdateRSWorkItems {
@@ -101,13 +105,6 @@
ObjCopyLABUndoWaste
};
- enum GCOptCSetWorkItems {
- OptCSetScannedCards,
- OptCSetClaimedCards,
- OptCSetSkippedCards,
- OptCSetUsedMemory
- };
-
private:
// Markers for grouping the phases in the GCPhases enum above
static const int GCMainParPhasesLast = GCWorkerEnd;
@@ -122,19 +119,25 @@
WorkerDataArray<size_t>* _scan_rs_claimed_cards;
WorkerDataArray<size_t>* _scan_rs_skipped_cards;
+ WorkerDataArray<size_t>* _opt_scan_rs_scanned_cards;
+ WorkerDataArray<size_t>* _opt_scan_rs_claimed_cards;
+ WorkerDataArray<size_t>* _opt_scan_rs_skipped_cards;
+ WorkerDataArray<size_t>* _opt_scan_rs_scanned_opt_refs;
+ WorkerDataArray<size_t>* _opt_scan_rs_used_memory;
+
WorkerDataArray<size_t>* _obj_copy_lab_waste;
WorkerDataArray<size_t>* _obj_copy_lab_undo_waste;
- WorkerDataArray<size_t>* _opt_cset_scanned_cards;
- WorkerDataArray<size_t>* _opt_cset_claimed_cards;
- WorkerDataArray<size_t>* _opt_cset_skipped_cards;
- WorkerDataArray<size_t>* _opt_cset_used_memory;
+ WorkerDataArray<size_t>* _opt_obj_copy_lab_waste;
+ WorkerDataArray<size_t>* _opt_obj_copy_lab_undo_waste;
WorkerDataArray<size_t>* _termination_attempts;
+ WorkerDataArray<size_t>* _opt_termination_attempts;
+
WorkerDataArray<size_t>* _redirtied_cards;
- double _cur_collection_par_time_ms;
+ double _cur_collection_initial_evac_time_ms;
double _cur_optional_evac_ms;
double _cur_collection_code_root_fixup_time_ms;
double _cur_strong_code_root_purge_time_ms;
@@ -225,10 +228,14 @@
void record_or_add_time_secs(GCParPhases phase, uint worker_i, double secs);
+ double get_time_secs(GCParPhases phase, uint worker_i);
+
void record_thread_work_item(GCParPhases phase, uint worker_i, size_t count, uint index = 0);
void record_or_add_thread_work_item(GCParPhases phase, uint worker_i, size_t count, uint index = 0);
+ size_t get_thread_work_item(GCParPhases phase, uint worker_i, uint index = 0);
+
// return the average time for a phase in milliseconds
double average_time_ms(GCParPhases phase);
@@ -256,16 +263,16 @@
_cur_expand_heap_time_ms = ms;
}
- void record_par_time(double ms) {
- _cur_collection_par_time_ms = ms;
+ void record_initial_evac_time(double ms) {
+ _cur_collection_initial_evac_time_ms = ms;
}
- void record_optional_evacuation(double ms) {
- _cur_optional_evac_ms = ms;
+ void record_or_add_optional_evac_time(double ms) {
+ _cur_optional_evac_ms += ms;
}
- void record_code_root_fixup_time(double ms) {
- _cur_collection_code_root_fixup_time_ms = ms;
+ void record_or_add_code_root_fixup_time(double ms) {
+ _cur_collection_code_root_fixup_time_ms += ms;
}
void record_strong_code_root_purge_time(double ms) {
@@ -360,7 +367,7 @@
}
double cur_collection_par_time_ms() {
- return _cur_collection_par_time_ms;
+ return _cur_collection_initial_evac_time_ms;
}
double cur_clear_ct_time_ms() {
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -371,6 +371,7 @@
}
bool do_heap_region(HeapRegion* r) {
+ guarantee(!r->has_index_in_opt_cset(), "Region %u still has opt collection set index %u", r->hrm_index(), r->index_in_opt_cset());
guarantee(!r->is_young() || r->rem_set()->is_complete(), "Remembered set for Young region %u must be complete, is %s", r->hrm_index(), r->rem_set()->get_state_str());
// Humongous and old regions regions might be of any state, so can't check here.
guarantee(!r->is_free() || !r->rem_set()->is_tracked(), "Remembered set for free region %u must be untracked, is %s", r->hrm_index(), r->rem_set()->get_state_str());
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -228,23 +228,25 @@
MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
// Recalculate all the sizes from scratch.
- uint young_list_length = _g1h->young_regions_count();
+ // This never includes used bytes of current allocating heap region.
+ _overall_used = _g1h->used_unlocked();
+ _eden_space_used = _g1h->eden_regions_used_bytes();
+ _survivor_space_used = _g1h->survivor_regions_used_bytes();
+
+ // _overall_used and _eden_space_used are obtained concurrently so
+ // may be inconsistent with each other. To prevent _old_gen_used going negative,
+ // use smaller value to substract.
+ _old_gen_used = _overall_used - MIN2(_overall_used, _eden_space_used + _survivor_space_used);
+
uint survivor_list_length = _g1h->survivor_regions_count();
- assert(young_list_length >= survivor_list_length, "invariant");
- uint eden_list_length = young_list_length - survivor_list_length;
// Max length includes any potential extensions to the young gen
// we'll do when the GC locker is active.
uint young_list_max_length = _g1h->policy()->young_list_max_length();
assert(young_list_max_length >= survivor_list_length, "invariant");
uint eden_list_max_length = young_list_max_length - survivor_list_length;
- _overall_used = _g1h->used_unlocked();
- _eden_space_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
- _survivor_space_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
- _old_gen_used = subtract_up_to_zero(_overall_used, _eden_space_used + _survivor_space_used);
-
// First calculate the committed sizes that can be calculated independently.
- _survivor_space_committed = _survivor_space_used;
+ _survivor_space_committed = survivor_list_length * HeapRegion::GrainBytes;
_old_gen_committed = HeapRegion::align_up_to_region_byte_size(_old_gen_used);
// Next, start with the overall committed size.
@@ -274,11 +276,15 @@
// Somewhat defensive: cap the eden used size to make sure it
// never exceeds the committed size.
_eden_space_used = MIN2(_eden_space_used, _eden_space_committed);
- // _survivor_committed and _old_committed are calculated in terms of
- // the corresponding _*_used value, so the next two conditions
- // should hold.
- assert(_survivor_space_used <= _survivor_space_committed, "post-condition");
- assert(_old_gen_used <= _old_gen_committed, "post-condition");
+ // _survivor_space_used is calculated during a safepoint and _survivor_space_committed
+ // is calculated from survivor region count * heap region size.
+ assert(_survivor_space_used <= _survivor_space_committed, "Survivor used bytes(" SIZE_FORMAT
+ ") should be less than or equal to survivor committed(" SIZE_FORMAT ")",
+ _survivor_space_used, _survivor_space_committed);
+ // _old_gen_committed is calculated in terms of _old_gen_used value.
+ assert(_old_gen_used <= _old_gen_committed, "Old gen used bytes(" SIZE_FORMAT
+ ") should be less than or equal to old gen committed(" SIZE_FORMAT ")",
+ _old_gen_used, _old_gen_committed);
}
void G1MonitoringSupport::update_sizes() {
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -174,21 +174,6 @@
size_t _old_gen_used;
- // It returns x - y if x > y, 0 otherwise.
- // As described in the comment above, some of the inputs to the
- // calculations we have to do are obtained concurrently and hence
- // may be inconsistent with each other. So, this provides a
- // defensive way of performing the subtraction and avoids the value
- // going negative (which would mean a very large result, given that
- // the parameter are size_t).
- static size_t subtract_up_to_zero(size_t x, size_t y) {
- if (x > y) {
- return x - y;
- } else {
- return 0;
- }
- }
-
// Recalculate all the sizes.
void recalculate_sizes();
--- a/src/hotspot/share/gc/g1/g1OopStarChunkedList.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1OopStarChunkedList.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -32,9 +32,11 @@
delete_list(_coops);
}
-void G1OopStarChunkedList::oops_do(OopClosure* obj_cl, OopClosure* root_cl) {
- chunks_do(_roots, root_cl);
- chunks_do(_croots, root_cl);
- chunks_do(_oops, obj_cl);
- chunks_do(_coops, obj_cl);
+size_t G1OopStarChunkedList::oops_do(OopClosure* obj_cl, OopClosure* root_cl) {
+ size_t result = 0;
+ result += chunks_do(_roots, root_cl);
+ result += chunks_do(_croots, root_cl);
+ result += chunks_do(_oops, obj_cl);
+ result += chunks_do(_coops, obj_cl);
+ return result;
}
--- a/src/hotspot/share/gc/g1/g1OopStarChunkedList.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1OopStarChunkedList.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -41,8 +41,8 @@
template <typename T> void delete_list(ChunkedList<T*, mtGC>* c);
template <typename T>
- void chunks_do(ChunkedList<T*, mtGC>* head,
- OopClosure* cl);
+ size_t chunks_do(ChunkedList<T*, mtGC>* head,
+ OopClosure* cl);
template <typename T>
inline void push(ChunkedList<T*, mtGC>** field, T* p);
@@ -53,7 +53,7 @@
size_t used_memory() { return _used_memory; }
- void oops_do(OopClosure* obj_cl, OopClosure* root_cl);
+ size_t oops_do(OopClosure* obj_cl, OopClosure* root_cl);
inline void push_oop(oop* p);
inline void push_oop(narrowOop* p);
--- a/src/hotspot/share/gc/g1/g1OopStarChunkedList.inline.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1OopStarChunkedList.inline.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -72,13 +72,16 @@
}
template <typename T>
-void G1OopStarChunkedList::chunks_do(ChunkedList<T*, mtGC>* head, OopClosure* cl) {
+size_t G1OopStarChunkedList::chunks_do(ChunkedList<T*, mtGC>* head, OopClosure* cl) {
+ size_t result = 0;
for (ChunkedList<T*, mtGC>* c = head; c != NULL; c = c->next_used()) {
+ result += c->size();
for (size_t i = 0; i < c->size(); i++) {
T* p = c->at(i);
cl->do_oop(p);
}
}
+ return result;
}
#endif // SHARE_GC_G1_G1OOPSTARCHUNKEDLIST_INLINE_HPP
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -372,7 +372,7 @@
}
size_t used_memory = pss->oops_into_optional_region(hr)->used_memory();
- _g1h->phase_times()->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_index, used_memory, G1GCPhaseTimes::OptCSetUsedMemory);
+ _g1h->phase_times()->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_index, used_memory, G1GCPhaseTimes::ScanRSUsedMemory);
}
}
--- a/src/hotspot/share/gc/g1/g1Policy.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -105,7 +105,7 @@
assert(Heap_lock->owned_by_self(), "Locking discipline.");
- if (!adaptive_young_list_length()) {
+ if (!use_adaptive_young_list_length()) {
_young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
}
_young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions());
@@ -195,7 +195,7 @@
uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) const {
uint desired_min_length = 0;
- if (adaptive_young_list_length()) {
+ if (use_adaptive_young_list_length()) {
if (_analytics->num_alloc_rate_ms() > 3) {
double now_sec = os::elapsedTime();
double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
@@ -252,7 +252,7 @@
uint desired_max_length = calculate_young_list_desired_max_length();
uint young_list_target_length = 0;
- if (adaptive_young_list_length()) {
+ if (use_adaptive_young_list_length()) {
if (collector_state()->in_young_only_phase()) {
young_list_target_length =
calculate_young_list_target_length(rs_lengths,
@@ -304,7 +304,7 @@
uint base_min_length,
uint desired_min_length,
uint desired_max_length) const {
- assert(adaptive_young_list_length(), "pre-condition");
+ assert(use_adaptive_young_list_length(), "pre-condition");
assert(collector_state()->in_young_only_phase(), "only call this for young GCs");
// In case some edge-condition makes the desired max length too small...
@@ -414,7 +414,7 @@
}
void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_lengths) {
- guarantee( adaptive_young_list_length(), "should not call this otherwise" );
+ guarantee(use_adaptive_young_list_length(), "should not call this otherwise" );
if (rs_lengths > _rs_lengths_prediction) {
// add 10% to avoid having to recalculate often
@@ -430,7 +430,7 @@
}
void G1Policy::update_rs_lengths_prediction(size_t prediction) {
- if (collector_state()->in_young_only_phase() && adaptive_young_list_length()) {
+ if (collector_state()->in_young_only_phase() && use_adaptive_young_list_length()) {
_rs_lengths_prediction = prediction;
}
}
@@ -659,7 +659,11 @@
double cost_per_entry_ms = 0.0;
if (cards_scanned > 10) {
- cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
+ double avg_time_scan_rs = average_time_ms(G1GCPhaseTimes::ScanRS);
+ if (this_pause_was_young_only) {
+ avg_time_scan_rs += average_time_ms(G1GCPhaseTimes::OptScanRS);
+ }
+ cost_per_entry_ms = avg_time_scan_rs / cards_scanned;
_analytics->report_cost_per_entry_ms(cost_per_entry_ms, this_pause_was_young_only);
}
@@ -694,7 +698,7 @@
double cost_per_byte_ms = 0.0;
if (copied_bytes > 0) {
- cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
+ cost_per_byte_ms = (average_time_ms(G1GCPhaseTimes::ObjCopy) + average_time_ms(G1GCPhaseTimes::OptObjCopy)) / (double) copied_bytes;
_analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->mark_or_rebuild_in_progress());
}
@@ -906,8 +910,8 @@
return young_list_length < young_list_max_length;
}
-bool G1Policy::adaptive_young_list_length() const {
- return _young_gen_sizer->adaptive_young_list_length();
+bool G1Policy::use_adaptive_young_list_length() const {
+ return _young_gen_sizer->use_adaptive_young_list_length();
}
size_t G1Policy::desired_survivor_size(uint max_regions) const {
@@ -1188,11 +1192,135 @@
return (uint) result;
}
-uint G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
- double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms, survivor);
- _collection_set->finalize_old_part(time_remaining_ms);
+void G1Policy::calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates,
+ double time_remaining_ms,
+ uint& num_initial_regions,
+ uint& num_optional_regions) {
+ assert(candidates != NULL, "Must be");
+
+ num_initial_regions = 0;
+ num_optional_regions = 0;
+ uint num_expensive_regions = 0;
+
+ double predicted_old_time_ms = 0.0;
+ double predicted_initial_time_ms = 0.0;
+ double predicted_optional_time_ms = 0.0;
+
+ double optional_threshold_ms = time_remaining_ms * optional_prediction_fraction();
+
+ const uint min_old_cset_length = calc_min_old_cset_length();
+ const uint max_old_cset_length = MAX2(min_old_cset_length, calc_max_old_cset_length());
+ const uint max_optional_regions = max_old_cset_length - min_old_cset_length;
+ bool check_time_remaining = use_adaptive_young_list_length();
+
+ uint candidate_idx = candidates->cur_idx();
+
+ log_debug(gc, ergo, cset)("Start adding old regions to collection set. Min %u regions, max %u regions, "
+ "time remaining %1.2fms, optional threshold %1.2fms",
+ min_old_cset_length, max_old_cset_length, time_remaining_ms, optional_threshold_ms);
+
+ HeapRegion* hr = candidates->at(candidate_idx);
+ while (hr != NULL) {
+ if (num_initial_regions + num_optional_regions >= max_old_cset_length) {
+ // Added maximum number of old regions to the CSet.
+ log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Maximum number of regions). "
+ "Initial %u regions, optional %u regions",
+ num_initial_regions, num_optional_regions);
+ break;
+ }
+
+ // Stop adding regions if the remaining reclaimable space is
+ // not above G1HeapWastePercent.
+ size_t reclaimable_bytes = candidates->remaining_reclaimable_bytes();
+ double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes);
+ double threshold = (double) G1HeapWastePercent;
+ if (reclaimable_percent <= threshold) {
+ // We've added enough old regions that the amount of uncollected
+ // reclaimable space is at or below the waste threshold. Stop
+ // adding old regions to the CSet.
+ log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Reclaimable percentage below threshold). "
+ "Reclaimable: " SIZE_FORMAT "%s (%1.2f%%) threshold: " UINTX_FORMAT "%%",
+ byte_size_in_proper_unit(reclaimable_bytes), proper_unit_for_byte_size(reclaimable_bytes),
+ reclaimable_percent, G1HeapWastePercent);
+ break;
+ }
- return _collection_set->region_length();
+ double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
+ time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
+ // Add regions to old set until we reach the minimum amount
+ if (num_initial_regions < min_old_cset_length) {
+ predicted_old_time_ms += predicted_time_ms;
+ num_initial_regions++;
+ // Record the number of regions added with no time remaining
+ if (time_remaining_ms == 0.0) {
+ num_expensive_regions++;
+ }
+ } else if (!check_time_remaining) {
+ // In the non-auto-tuning case, we'll finish adding regions
+ // to the CSet if we reach the minimum.
+ log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Region amount reached min).");
+ break;
+ } else {
+ // Keep adding regions to old set until we reach the optional threshold
+ if (time_remaining_ms > optional_threshold_ms) {
+ predicted_old_time_ms += predicted_time_ms;
+ num_initial_regions++;
+ } else if (time_remaining_ms > 0) {
+ // Keep adding optional regions until time is up.
+ assert(num_optional_regions < max_optional_regions, "Should not be possible.");
+ predicted_optional_time_ms += predicted_time_ms;
+ num_optional_regions++;
+ } else {
+ log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Predicted time too high).");
+ break;
+ }
+ }
+ hr = candidates->at(++candidate_idx);
+ }
+ if (hr == NULL) {
+ log_debug(gc, ergo, cset)("Old candidate collection set empty.");
+ }
+
+ if (num_expensive_regions > 0) {
+ log_debug(gc, ergo, cset)("Added %u initial old regions to collection set although the predicted time was too high.",
+ num_expensive_regions);
+ }
+
+ log_debug(gc, ergo, cset)("Finish choosing collection set old regions. Initial: %u, optional: %u, "
+ "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f",
+ num_initial_regions, num_optional_regions,
+ predicted_initial_time_ms, predicted_optional_time_ms, time_remaining_ms);
+}
+
+void G1Policy::calculate_optional_collection_set_regions(G1CollectionSetCandidates* candidates,
+ uint const max_optional_regions,
+ double time_remaining_ms,
+ uint& num_optional_regions) {
+ assert(_g1h->collector_state()->in_mixed_phase(), "Should only be called in mixed phase");
+
+ num_optional_regions = 0;
+ double prediction_ms = 0;
+ uint candidate_idx = candidates->cur_idx();
+
+ HeapRegion* r = candidates->at(candidate_idx);
+ while (num_optional_regions < max_optional_regions) {
+ assert(r != NULL, "Region must exist");
+ prediction_ms += predict_region_elapsed_time_ms(r, false);
+
+ if (prediction_ms > time_remaining_ms) {
+ log_debug(gc, ergo, cset)("Prediction %.3fms for region %u does not fit remaining time: %.3fms.",
+ prediction_ms, r->hrm_index(), time_remaining_ms);
+ break;
+ }
+ // This region will be included in the next optional evacuation.
+
+ time_remaining_ms -= prediction_ms;
+ num_optional_regions++;
+ r = candidates->at(++candidate_idx);
+ }
+
+ log_debug(gc, ergo, cset)("Prepared %u regions out of %u for optional evacuation. Predicted time: %.3fms",
+ num_optional_regions, max_optional_regions, prediction_ms);
}
void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
--- a/src/hotspot/share/gc/g1/g1Policy.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -44,6 +44,7 @@
class HeapRegion;
class G1CollectionSet;
+class G1CollectionSetCandidates;
class G1CollectionSetChooser;
class G1IHOPControl;
class G1Analytics;
@@ -344,7 +345,21 @@
bool next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) const;
- uint finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
+ // Calculate and return the number of initial and optional old gen regions from
+ // the given collection set candidates and the remaining time.
+ void calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates,
+ double time_remaining_ms,
+ uint& num_initial_regions,
+ uint& num_optional_regions);
+
+ // Calculate the number of optional regions from the given collection set candidates,
+ // the remaining time and the maximum number of these regions and return the number
+ // of actually selected regions in num_optional_regions.
+ void calculate_optional_collection_set_regions(G1CollectionSetCandidates* candidates,
+ uint const max_optional_regions,
+ double time_remaining_ms,
+ uint& num_optional_regions);
+
private:
// Set the state to start a concurrent marking cycle and clear
// _initiate_conc_mark_if_possible because it has now been
@@ -384,7 +399,7 @@
return _young_list_max_length;
}
- bool adaptive_young_list_length() const;
+ bool use_adaptive_young_list_length() const;
void transfer_survivors_to_cset(const G1SurvivorRegions* survivors);
@@ -403,11 +418,13 @@
AgeTable _survivors_age_table;
size_t desired_survivor_size(uint max_regions) const;
-public:
+
// Fraction used when predicting how many optional regions to include in
// the CSet. This fraction of the available time is used for optional regions,
// the rest is used to add old regions to the normal CSet.
double optional_prediction_fraction() { return 0.2; }
+
+public:
// Fraction used when evacuating the optional regions. This fraction of the
// remaining time is used to choose what regions to include in the evacuation.
double optional_evacuation_fraction() { return 0.75; }
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -316,6 +316,8 @@
_scan_state(scan_state),
_phase(phase),
_worker_i(worker_i),
+ _opt_refs_scanned(0),
+ _opt_refs_memory_used(0),
_cards_scanned(0),
_cards_claimed(0),
_cards_skipped(0),
@@ -338,6 +340,19 @@
_cards_scanned++;
}
+void G1ScanRSForRegionClosure::scan_opt_rem_set_roots(HeapRegion* r) {
+ EventGCPhaseParallel event;
+
+ G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+
+ G1ScanObjsDuringScanRSClosure scan_cl(_g1h, _pss);
+ G1ScanRSForOptionalClosure cl(&scan_cl);
+ _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->raw_strong_oops());
+ _opt_refs_memory_used += opt_rem_set_list->used_memory();
+
+ event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
+}
+
void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
EventGCPhaseParallel event;
uint const region_idx = r->hrm_index();
@@ -414,11 +429,16 @@
}
bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
- assert(r->in_collection_set(),
- "Should only be called on elements of the collection set but region %u is not.",
- r->hrm_index());
+ assert(r->in_collection_set(), "Region %u is not in the collection set.", r->hrm_index());
uint const region_idx = r->hrm_index();
+ // The individual references for the optional remembered set are per-worker, so we
+ // always need to scan them.
+ if (r->has_index_in_opt_cset()) {
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
+ scan_opt_rem_set_roots(r);
+ }
+
// Do an early out if we know we are complete.
if (_scan_state->iter_is_complete(region_idx)) {
return false;
@@ -437,22 +457,33 @@
return false;
}
-void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
+void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
+ uint worker_i,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase,
+ G1GCPhaseTimes::GCParPhases coderoots_phase) {
+ assert(pss->trim_ticks().value() == 0, "Queues must have been trimmed before entering.");
+
G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
- G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, G1GCPhaseTimes::ScanRS, worker_i);
- _g1h->collection_set_iterate_from(&cl, worker_i);
+ G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, scan_phase, worker_i);
+ _g1h->collection_set_iterate_increment_from(&cl, worker_i);
G1GCPhaseTimes* p = _g1p->phase_times();
- p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, cl.rem_set_root_scan_time().seconds());
- p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.rem_set_trim_partially_time().seconds());
+ p->record_or_add_time_secs(objcopy_phase, worker_i, cl.rem_set_trim_partially_time().seconds());
- p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
- p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
- p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
+ p->record_or_add_time_secs(scan_phase, worker_i, cl.rem_set_root_scan_time().seconds());
+ p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
+ p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
+ p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
+ // At this time we only record some metrics for the optional remembered set.
+ if (scan_phase == G1GCPhaseTimes::OptScanRS) {
+ p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanRSScannedOptRefs);
+ p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanRSUsedMemory);
+ }
- p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time().seconds());
- p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.strong_code_root_trim_partially_time().seconds());
+ p->record_or_add_time_secs(coderoots_phase, worker_i, cl.strong_code_root_scan_time().seconds());
+ p->add_time_secs(objcopy_phase, worker_i, cl.strong_code_root_trim_partially_time().seconds());
}
// Closure used for updating rem sets. Only called during an evacuation pause.
@@ -514,11 +545,6 @@
}
}
-void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
- update_rem_set(pss, worker_i);
- scan_rem_set(pss, worker_i);;
-}
-
void G1RemSet::prepare_for_oops_into_collection_set_do() {
G1BarrierSet::dirty_card_queue_set().concatenate_logs();
_scan_state->reset();
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -60,14 +60,6 @@
G1RemSetSummary _prev_period_summary;
- // Scan all remembered sets of the collection set for references into the collection
- // set.
- void scan_rem_set(G1ParScanThreadState* pss, uint worker_i);
-
- // Flush remaining refinement buffers for cross-region references to either evacuate references
- // into the collection set or update the remembered set.
- void update_rem_set(G1ParScanThreadState* pss, uint worker_i);
-
G1CollectedHeap* _g1h;
size_t _num_conc_refined_cards; // Number of cards refined concurrently to the mutator.
@@ -93,12 +85,19 @@
G1HotCardCache* hot_card_cache);
~G1RemSet();
- // Process all oops in the collection set from the cards in the refinement buffers and
- // remembered sets using pss.
- //
+ // Scan all remembered sets of the collection set for references into the collection
+ // set.
// Further applies heap_region_codeblobs on the oops of the unmarked nmethods on the strong code
// roots list for each region in the collection set.
- void oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i);
+ void scan_rem_set(G1ParScanThreadState* pss,
+ uint worker_i,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase,
+ G1GCPhaseTimes::GCParPhases coderoots_phase);
+
+ // Flush remaining refinement buffers for cross-region references to either evacuate references
+ // into the collection set or update the remembered set.
+ void update_rem_set(G1ParScanThreadState* pss, uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
@@ -144,6 +143,9 @@
uint _worker_i;
+ size_t _opt_refs_scanned;
+ size_t _opt_refs_memory_used;
+
size_t _cards_scanned;
size_t _cards_claimed;
size_t _cards_skipped;
@@ -157,6 +159,7 @@
void claim_card(size_t card_index, const uint region_idx_for_card);
void scan_card(MemRegion mr, uint region_idx_for_card);
+ void scan_opt_rem_set_roots(HeapRegion* r);
void scan_rem_set_roots(HeapRegion* r);
void scan_strong_code_roots(HeapRegion* r);
public:
@@ -177,6 +180,9 @@
size_t cards_scanned() const { return _cards_scanned; }
size_t cards_claimed() const { return _cards_claimed; }
size_t cards_skipped() const { return _cards_skipped; }
+
+ size_t opt_refs_scanned() const { return _opt_refs_scanned; }
+ size_t opt_refs_memory_used() const { return _opt_refs_memory_used; }
};
#endif // SHARE_GC_G1_G1REMSET_HPP
--- a/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -28,7 +28,9 @@
#include "utilities/growableArray.hpp"
#include "utilities/debug.hpp"
-G1SurvivorRegions::G1SurvivorRegions() : _regions(new (ResourceObj::C_HEAP, mtGC) GrowableArray<HeapRegion*>(8, true, mtGC)) {}
+G1SurvivorRegions::G1SurvivorRegions() :
+ _regions(new (ResourceObj::C_HEAP, mtGC) GrowableArray<HeapRegion*>(8, true, mtGC)),
+ _used_bytes(0) {}
void G1SurvivorRegions::add(HeapRegion* hr) {
assert(hr->is_survivor(), "should be flagged as survivor region");
@@ -51,5 +53,9 @@
void G1SurvivorRegions::clear() {
_regions->clear();
+ _used_bytes = 0;
}
+void G1SurvivorRegions::add_used_bytes(size_t used_bytes) {
+ _used_bytes += used_bytes;
+}
--- a/src/hotspot/share/gc/g1/g1SurvivorRegions.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1SurvivorRegions.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -34,6 +34,7 @@
class G1SurvivorRegions {
private:
GrowableArray<HeapRegion*>* _regions;
+ volatile size_t _used_bytes;
public:
G1SurvivorRegions();
@@ -49,6 +50,11 @@
const GrowableArray<HeapRegion*>* regions() const {
return _regions;
}
+
+ // Used bytes of all survivor regions.
+ size_t used_bytes() const { return _used_bytes; }
+
+ void add_used_bytes(size_t used_bytes);
};
#endif // SHARE_GC_G1_G1SURVIVORREGIONS_HPP
--- a/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -30,14 +30,14 @@
#include "logging/log.hpp"
G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults),
- _adaptive_size(true), _min_desired_young_length(0), _max_desired_young_length(0) {
+ _use_adaptive_sizing(true), _min_desired_young_length(0), _max_desired_young_length(0) {
if (FLAG_IS_CMDLINE(NewRatio)) {
if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
log_warning(gc, ergo)("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
} else {
_sizer_kind = SizerNewRatio;
- _adaptive_size = false;
+ _use_adaptive_sizing = false;
return;
}
}
@@ -59,7 +59,7 @@
MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
1U);
_sizer_kind = SizerMaxAndNewSize;
- _adaptive_size = _min_desired_young_length != _max_desired_young_length;
+ _use_adaptive_sizing = _min_desired_young_length != _max_desired_young_length;
} else {
_sizer_kind = SizerNewSizeOnly;
}
--- a/src/hotspot/share/gc/g1/g1YoungGenSizer.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -77,7 +77,7 @@
// False when using a fixed young generation size due to command-line options,
// true otherwise.
- bool _adaptive_size;
+ bool _use_adaptive_sizing;
uint calculate_default_min_length(uint new_number_of_heap_regions);
uint calculate_default_max_length(uint new_number_of_heap_regions);
@@ -104,8 +104,8 @@
return _max_desired_young_length;
}
- bool adaptive_young_list_length() const {
- return _adaptive_size;
+ bool use_adaptive_young_list_length() const {
+ return _use_adaptive_sizing;
}
static G1YoungGenSizer* create_gen_sizer(G1CollectorPolicy* policy);
--- a/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -165,7 +165,7 @@
G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1Policy* policy = g1h->policy();
- if (policy->adaptive_young_list_length()) {
+ if (policy->use_adaptive_young_list_length()) {
G1YoungRemSetSamplingClosure cl(&sts);
G1CollectionSet* g1cs = g1h->collection_set();
--- a/src/hotspot/share/gc/g1/heapRegion.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -117,6 +117,7 @@
"Should not clear heap region %u in the collection set", hrm_index());
set_young_index_in_cset(-1);
+ clear_index_in_opt_cset();
uninstall_surv_rate_group();
set_free();
reset_pre_dummy_top();
@@ -241,7 +242,7 @@
_containing_set(NULL),
#endif
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
- _index_in_opt_cset(G1OptionalCSet::InvalidCSetIndex), _young_index_in_cset(-1),
+ _index_in_opt_cset(InvalidCSetIndex), _young_index_in_cset(-1),
_surv_rate_group(NULL), _age_index(-1),
_prev_top_at_mark_start(NULL), _next_top_at_mark_start(NULL),
_recorded_rs_length(0), _predicted_elapsed_time_ms(0)
--- a/src/hotspot/share/gc/g1/heapRegion.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -250,6 +250,8 @@
// The calculated GC efficiency of the region.
double _gc_efficiency;
+ static const uint InvalidCSetIndex = UINT_MAX;
+
// The index in the optional regions array, if this region
// is considered optional during a mixed collections.
uint _index_in_opt_cset;
@@ -549,8 +551,13 @@
void calc_gc_efficiency(void);
double gc_efficiency() const { return _gc_efficiency;}
- uint index_in_opt_cset() const { return _index_in_opt_cset; }
+ uint index_in_opt_cset() const {
+ assert(has_index_in_opt_cset(), "Opt cset index not set.");
+ return _index_in_opt_cset;
+ }
+ bool has_index_in_opt_cset() const { return _index_in_opt_cset != InvalidCSetIndex; }
void set_index_in_opt_cset(uint index) { _index_in_opt_cset = index; }
+ void clear_index_in_opt_cset() { _index_in_opt_cset = InvalidCSetIndex; }
int young_index_in_cset() const { return _young_index_in_cset; }
void set_young_index_in_cset(int index) {
--- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -52,8 +52,8 @@
nonstatic_field(HeapRegionManager, _regions, G1HeapRegionTable) \
nonstatic_field(HeapRegionManager, _num_committed, uint) \
\
- nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \
- nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager*) \
+ volatile_nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \
+ nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager*) \
nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \
nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \
nonstatic_field(G1CollectedHeap, _archive_set, HeapRegionSetBase) \
--- a/src/hotspot/share/gc/shared/workerDataArray.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shared/workerDataArray.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -34,7 +34,7 @@
class WorkerDataArray : public CHeapObj<mtGC> {
friend class WDAPrinter;
public:
- static const uint MaxThreadWorkItems = 4;
+ static const uint MaxThreadWorkItems = 5;
private:
T* _data;
uint _length;
@@ -50,6 +50,7 @@
void set_thread_work_item(uint worker_i, size_t value, uint index = 0);
void add_thread_work_item(uint worker_i, size_t value, uint index = 0);
void set_or_add_thread_work_item(uint worker_i, size_t value, uint index = 0);
+ size_t get_thread_work_item(uint worker_i, uint index = 0);
WorkerDataArray<size_t>* thread_work_items(uint index = 0) const {
assert(index < MaxThreadWorkItems, "Tried to access thread work item %u max %u", index, MaxThreadWorkItems);
--- a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -92,6 +92,13 @@
}
template <typename T>
+size_t WorkerDataArray<T>::get_thread_work_item(uint worker_i, uint index) {
+ assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems);
+ assert(_thread_work_items[index] != NULL, "No sub count");
+ return _thread_work_items[index]->get(worker_i);
+}
+
+template <typename T>
void WorkerDataArray<T>::add(uint worker_i, T value) {
assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i);
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -46,9 +46,9 @@
bs->gen_pre_barrier_stub(ce, this);
}
-void ShenandoahWriteBarrierStub::emit_code(LIR_Assembler* ce) {
+void ShenandoahLoadReferenceBarrierStub::emit_code(LIR_Assembler* ce) {
ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
- bs->gen_write_barrier_stub(ce, this);
+ bs->gen_load_reference_barrier_stub(ce, this);
}
void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
@@ -105,40 +105,16 @@
__ branch_destination(slow->continuation());
}
-LIR_Opr ShenandoahBarrierSetC1::read_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
- if (UseShenandoahGC && ShenandoahReadBarrier) {
- return read_barrier_impl(gen, obj, info, need_null_check);
+LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
+ if (ShenandoahLoadRefBarrier) {
+ return load_reference_barrier_impl(gen, obj, info, need_null_check);
} else {
return obj;
}
}
-LIR_Opr ShenandoahBarrierSetC1::read_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier), "Should be enabled");
- LabelObj* done = new LabelObj();
- LIR_Opr result = gen->new_register(T_OBJECT);
- __ move(obj, result);
- if (need_null_check) {
- __ cmp(lir_cond_equal, result, LIR_OprFact::oopConst(NULL));
- __ branch(lir_cond_equal, T_LONG, done->label());
- }
- LIR_Address* brooks_ptr_address = gen->generate_address(result, ShenandoahBrooksPointer::byte_offset(), T_ADDRESS);
- __ load(brooks_ptr_address, result, info ? new CodeEmitInfo(info) : NULL, lir_patch_none);
-
- __ branch_destination(done->label());
- return result;
-}
-
-LIR_Opr ShenandoahBarrierSetC1::write_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
- if (UseShenandoahGC && ShenandoahWriteBarrier) {
- return write_barrier_impl(gen, obj, info, need_null_check);
- } else {
- return obj;
- }
-}
-
-LIR_Opr ShenandoahBarrierSetC1::write_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
- assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
+LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
+ assert(ShenandoahLoadRefBarrier, "Should be enabled");
obj = ensure_in_register(gen, obj);
assert(obj->is_register(), "must be a register at this point");
@@ -168,7 +144,7 @@
}
__ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
- CodeStub* slow = new ShenandoahWriteBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
+ CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
__ branch(lir_cond_notEqual, T_INT, slow);
__ branch_destination(slow->continuation());
@@ -189,58 +165,13 @@
}
LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
- bool need_null_check = (decorators & IS_NOT_NULL) == 0;
if (ShenandoahStoreValEnqueueBarrier) {
- obj = write_barrier_impl(gen, obj, info, need_null_check);
+ obj = ensure_in_register(gen, obj);
pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
}
- if (ShenandoahStoreValReadBarrier) {
- obj = read_barrier_impl(gen, obj, info, true /*need_null_check*/);
- }
return obj;
}
-LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
- DecoratorSet decorators = access.decorators();
- bool is_array = (decorators & IS_ARRAY) != 0;
- bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
-
- bool is_write = (decorators & ACCESS_WRITE) != 0;
- bool needs_null_check = (decorators & IS_NOT_NULL) == 0;
-
- LIR_Opr base = access.base().item().result();
- LIR_Opr offset = access.offset().opr();
- LIRGenerator* gen = access.gen();
-
- if (is_write) {
- base = write_barrier(gen, base, access.access_emit_info(), needs_null_check);
- } else {
- base = read_barrier(gen, base, access.access_emit_info(), needs_null_check);
- }
-
- LIR_Opr addr_opr;
- if (is_array) {
- addr_opr = LIR_OprFact::address(gen->emit_array_address(base, offset, access.type()));
- } else if (needs_patching) {
- // we need to patch the offset in the instruction so don't allow
- // generate_address to try to be smart about emitting the -1.
- // Otherwise the patching code won't know how to find the
- // instruction to patch.
- addr_opr = LIR_OprFact::address(new LIR_Address(base, PATCHED_ADDR, access.type()));
- } else {
- addr_opr = LIR_OprFact::address(gen->generate_address(base, offset, 0, 0, access.type()));
- }
-
- if (resolve_in_register) {
- LIR_Opr resolved_addr = gen->new_pointer_register();
- __ leal(addr_opr, resolved_addr);
- resolved_addr = LIR_OprFact::address(new LIR_Address(resolved_addr, access.type()));
- return resolved_addr;
- } else {
- return addr_opr;
- }
-}
-
void ShenandoahBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
if (access.is_oop()) {
if (ShenandoahSATBBarrier) {
@@ -252,15 +183,28 @@
}
void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
- BarrierSetC1::load_at_resolved(access, result);
+ if (!access.is_oop()) {
+ BarrierSetC1::load_at_resolved(access, result);
+ return;
+ }
+
+ LIRGenerator *gen = access.gen();
+
+ if (ShenandoahLoadRefBarrier) {
+ LIR_Opr tmp = gen->new_register(T_OBJECT);
+ BarrierSetC1::load_at_resolved(access, tmp);
+ tmp = load_reference_barrier(access.gen(), tmp, access.access_emit_info(), true);
+ __ move(tmp, result);
+ } else {
+ BarrierSetC1::load_at_resolved(access, result);
+ }
if (ShenandoahKeepAliveBarrier) {
DecoratorSet decorators = access.decorators();
bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- LIRGenerator *gen = access.gen();
- if (access.is_oop() && (is_weak || is_phantom || is_anonymous)) {
+ if (is_weak || is_phantom || is_anonymous) {
// Register the value in the referent field with the pre-barrier
LabelObj *Lcont_anonymous;
if (is_anonymous) {
@@ -276,19 +220,6 @@
}
}
-LIR_Opr ShenandoahBarrierSetC1::atomic_add_at_resolved(LIRAccess& access, LIRItem& value) {
- return BarrierSetC1::atomic_add_at_resolved(access, value);
-}
-
-LIR_Opr ShenandoahBarrierSetC1::resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj) {
- bool is_write = decorators & ACCESS_WRITE;
- if (is_write) {
- return write_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
- } else {
- return read_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
- }
-}
-
class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
virtual OopMapSet* generate_code(StubAssembler* sasm) {
ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -85,7 +85,7 @@
#endif // PRODUCT
};
-class ShenandoahWriteBarrierStub: public CodeStub {
+class ShenandoahLoadReferenceBarrierStub: public CodeStub {
friend class ShenandoahBarrierSetC1;
private:
LIR_Opr _obj;
@@ -94,7 +94,7 @@
bool _needs_null_check;
public:
- ShenandoahWriteBarrierStub(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info, bool needs_null_check) :
+ ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info, bool needs_null_check) :
_obj(obj), _result(result), _info(info), _needs_null_check(needs_null_check)
{
assert(_obj->is_register(), "should be register");
@@ -113,7 +113,7 @@
visitor->do_temp(_result);
}
#ifndef PRODUCT
- virtual void print_name(outputStream* out) const { out->print("ShenandoahWritePreBarrierStub"); }
+ virtual void print_name(outputStream* out) const { out->print("ShenandoahLoadReferenceBarrierStub"); }
#endif // PRODUCT
};
@@ -181,12 +181,10 @@
void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val);
- LIR_Opr read_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
- LIR_Opr write_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
+ LIR_Opr load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
LIR_Opr storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators);
- LIR_Opr read_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
- LIR_Opr write_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
+ LIR_Opr load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check);
LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj);
@@ -194,7 +192,6 @@
CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; }
protected:
- virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register);
virtual void store_at_resolved(LIRAccess& access, LIR_Opr value);
virtual void load_at_resolved(LIRAccess& access, LIR_Opr result);
@@ -202,10 +199,8 @@
virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value);
- virtual LIR_Opr atomic_add_at_resolved(LIRAccess& access, LIRItem& value);
public:
- virtual LIR_Opr resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj);
virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob);
};
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -43,121 +43,56 @@
}
ShenandoahBarrierSetC2State::ShenandoahBarrierSetC2State(Arena* comp_arena)
- : _shenandoah_barriers(new (comp_arena) GrowableArray<ShenandoahWriteBarrierNode*>(comp_arena, 8, 0, NULL)) {
+ : _enqueue_barriers(new (comp_arena) GrowableArray<ShenandoahEnqueueBarrierNode*>(comp_arena, 8, 0, NULL)),
+ _load_reference_barriers(new (comp_arena) GrowableArray<ShenandoahLoadReferenceBarrierNode*>(comp_arena, 8, 0, NULL)) {
}
-int ShenandoahBarrierSetC2State::shenandoah_barriers_count() const {
- return _shenandoah_barriers->length();
+int ShenandoahBarrierSetC2State::enqueue_barriers_count() const {
+ return _enqueue_barriers->length();
}
-ShenandoahWriteBarrierNode* ShenandoahBarrierSetC2State::shenandoah_barrier(int idx) const {
- return _shenandoah_barriers->at(idx);
+ShenandoahEnqueueBarrierNode* ShenandoahBarrierSetC2State::enqueue_barrier(int idx) const {
+ return _enqueue_barriers->at(idx);
}
-void ShenandoahBarrierSetC2State::add_shenandoah_barrier(ShenandoahWriteBarrierNode * n) {
- assert(!_shenandoah_barriers->contains(n), "duplicate entry in barrier list");
- _shenandoah_barriers->append(n);
+void ShenandoahBarrierSetC2State::add_enqueue_barrier(ShenandoahEnqueueBarrierNode * n) {
+ assert(!_enqueue_barriers->contains(n), "duplicate entry in barrier list");
+ _enqueue_barriers->append(n);
}
-void ShenandoahBarrierSetC2State::remove_shenandoah_barrier(ShenandoahWriteBarrierNode * n) {
- if (_shenandoah_barriers->contains(n)) {
- _shenandoah_barriers->remove(n);
+void ShenandoahBarrierSetC2State::remove_enqueue_barrier(ShenandoahEnqueueBarrierNode * n) {
+ if (_enqueue_barriers->contains(n)) {
+ _enqueue_barriers->remove(n);
}
}
-#define __ kit->
+int ShenandoahBarrierSetC2State::load_reference_barriers_count() const {
+ return _load_reference_barriers->length();
+}
+
+ShenandoahLoadReferenceBarrierNode* ShenandoahBarrierSetC2State::load_reference_barrier(int idx) const {
+ return _load_reference_barriers->at(idx);
+}
-Node* ShenandoahBarrierSetC2::shenandoah_read_barrier(GraphKit* kit, Node* obj) const {
- if (ShenandoahReadBarrier) {
- obj = shenandoah_read_barrier_impl(kit, obj, false, true, true);
+void ShenandoahBarrierSetC2State::add_load_reference_barrier(ShenandoahLoadReferenceBarrierNode * n) {
+ assert(!_load_reference_barriers->contains(n), "duplicate entry in barrier list");
+ _load_reference_barriers->append(n);
+}
+
+void ShenandoahBarrierSetC2State::remove_load_reference_barrier(ShenandoahLoadReferenceBarrierNode * n) {
+ if (_load_reference_barriers->contains(n)) {
+ _load_reference_barriers->remove(n);
}
- return obj;
}
Node* ShenandoahBarrierSetC2::shenandoah_storeval_barrier(GraphKit* kit, Node* obj) const {
if (ShenandoahStoreValEnqueueBarrier) {
- obj = shenandoah_write_barrier(kit, obj);
obj = shenandoah_enqueue_barrier(kit, obj);
}
- if (ShenandoahStoreValReadBarrier) {
- obj = shenandoah_read_barrier_impl(kit, obj, true, false, false);
- }
return obj;
}
-Node* ShenandoahBarrierSetC2::shenandoah_read_barrier_impl(GraphKit* kit, Node* obj, bool use_ctrl, bool use_mem, bool allow_fromspace) const {
- const Type* obj_type = obj->bottom_type();
- if (obj_type->higher_equal(TypePtr::NULL_PTR)) {
- return obj;
- }
- const TypePtr* adr_type = ShenandoahBarrierNode::brooks_pointer_type(obj_type);
- Node* mem = use_mem ? __ memory(adr_type) : __ immutable_memory();
-
- if (! ShenandoahBarrierNode::needs_barrier(&__ gvn(), NULL, obj, mem, allow_fromspace)) {
- // We know it is null, no barrier needed.
- return obj;
- }
-
- if (obj_type->meet(TypePtr::NULL_PTR) == obj_type->remove_speculative()) {
-
- // We don't know if it's null or not. Need null-check.
- enum { _not_null_path = 1, _null_path, PATH_LIMIT };
- RegionNode* region = new RegionNode(PATH_LIMIT);
- Node* phi = new PhiNode(region, obj_type);
- Node* null_ctrl = __ top();
- Node* not_null_obj = __ null_check_oop(obj, &null_ctrl);
-
- region->init_req(_null_path, null_ctrl);
- phi ->init_req(_null_path, __ zerocon(T_OBJECT));
-
- Node* ctrl = use_ctrl ? __ control() : NULL;
- ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, mem, not_null_obj, allow_fromspace);
- Node* n = __ gvn().transform(rb);
-
- region->init_req(_not_null_path, __ control());
- phi ->init_req(_not_null_path, n);
-
- __ set_control(__ gvn().transform(region));
- __ record_for_igvn(region);
- return __ gvn().transform(phi);
-
- } else {
- // We know it is not null. Simple barrier is sufficient.
- Node* ctrl = use_ctrl ? __ control() : NULL;
- ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, mem, obj, allow_fromspace);
- Node* n = __ gvn().transform(rb);
- __ record_for_igvn(n);
- return n;
- }
-}
-
-Node* ShenandoahBarrierSetC2::shenandoah_write_barrier_helper(GraphKit* kit, Node* obj, const TypePtr* adr_type) const {
- ShenandoahWriteBarrierNode* wb = new ShenandoahWriteBarrierNode(kit->C, kit->control(), kit->memory(adr_type), obj);
- Node* n = __ gvn().transform(wb);
- if (n == wb) { // New barrier needs memory projection.
- Node* proj = __ gvn().transform(new ShenandoahWBMemProjNode(n));
- __ set_memory(proj, adr_type);
- }
- return n;
-}
-
-Node* ShenandoahBarrierSetC2::shenandoah_write_barrier(GraphKit* kit, Node* obj) const {
- if (ShenandoahWriteBarrier) {
- obj = shenandoah_write_barrier_impl(kit, obj);
- }
- return obj;
-}
-
-Node* ShenandoahBarrierSetC2::shenandoah_write_barrier_impl(GraphKit* kit, Node* obj) const {
- if (! ShenandoahBarrierNode::needs_barrier(&__ gvn(), NULL, obj, NULL, true)) {
- return obj;
- }
- const Type* obj_type = obj->bottom_type();
- const TypePtr* adr_type = ShenandoahBarrierNode::brooks_pointer_type(obj_type);
- Node* n = shenandoah_write_barrier_helper(kit, obj, adr_type);
- __ record_for_igvn(n);
- return n;
-}
+#define __ kit->
bool ShenandoahBarrierSetC2::satb_can_remove_pre_barrier(GraphKit* kit, PhaseTransform* phase, Node* adr,
BasicType bt, uint adr_idx) const {
@@ -304,7 +239,7 @@
Node* gc_state = __ AddP(no_base, tls, __ ConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset())));
Node* ld = __ load(__ ctrl(), gc_state, TypeInt::BYTE, T_BYTE, Compile::AliasIdxRaw);
marking = __ AndI(ld, __ ConI(ShenandoahHeap::MARKING));
- assert(ShenandoahWriteBarrierNode::is_gc_state_load(ld), "Should match the shape");
+ assert(ShenandoahBarrierC2Support::is_gc_state_load(ld), "Should match the shape");
// if (!marking)
__ if_then(marking, BoolTest::ne, zero, unlikely); {
@@ -361,7 +296,7 @@
bool ShenandoahBarrierSetC2::is_shenandoah_wb_call(Node* call) {
return call->is_CallLeaf() &&
- call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT);
+ call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_JRT);
}
bool ShenandoahBarrierSetC2::is_shenandoah_marking_if(PhaseTransform *phase, Node* n) {
@@ -549,88 +484,6 @@
return TypeFunc::make(domain, range);
}
-void ShenandoahBarrierSetC2::resolve_address(C2Access& access) const {
- const TypePtr* adr_type = access.addr().type();
-
- if ((access.decorators() & IN_NATIVE) == 0 && (adr_type->isa_instptr() || adr_type->isa_aryptr())) {
- int off = adr_type->is_ptr()->offset();
- int base_off = adr_type->isa_instptr() ? instanceOopDesc::base_offset_in_bytes() :
- arrayOopDesc::base_offset_in_bytes(adr_type->is_aryptr()->elem()->array_element_basic_type());
- assert(off != Type::OffsetTop, "unexpected offset");
- if (off == Type::OffsetBot || off >= base_off) {
- DecoratorSet decorators = access.decorators();
- bool is_write = (decorators & C2_WRITE_ACCESS) != 0;
- GraphKit* kit = NULL;
- if (access.is_parse_access()) {
- C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
- kit = parse_access.kit();
- }
- Node* adr = access.addr().node();
- assert(adr->is_AddP(), "unexpected address shape");
- Node* base = adr->in(AddPNode::Base);
-
- if (is_write) {
- if (kit != NULL) {
- base = shenandoah_write_barrier(kit, base);
- } else {
- assert(access.is_opt_access(), "either parse or opt access");
- assert((access.decorators() & C2_ARRAY_COPY) != 0, "can be skipped for clone");
- }
- } else {
- if (adr_type->isa_instptr()) {
- Compile* C = access.gvn().C;
- ciField* field = C->alias_type(adr_type)->field();
-
- // Insert read barrier for Shenandoah.
- if (field != NULL &&
- ((ShenandoahOptimizeStaticFinals && field->is_static() && field->is_final()) ||
- (ShenandoahOptimizeInstanceFinals && !field->is_static() && field->is_final()) ||
- (ShenandoahOptimizeStableFinals && field->is_stable()))) {
- // Skip the barrier for special fields
- } else {
- if (kit != NULL) {
- base = shenandoah_read_barrier(kit, base);
- } else {
- assert(access.is_opt_access(), "either parse or opt access");
- assert((access.decorators() & C2_ARRAY_COPY) != 0, "can be skipped for arraycopy");
- }
- }
- } else {
- if (kit != NULL) {
- base = shenandoah_read_barrier(kit, base);
- } else {
- assert(access.is_opt_access(), "either parse or opt access");
- assert((access.decorators() & C2_ARRAY_COPY) != 0, "can be skipped for arraycopy");
- }
- }
- }
- if (base != adr->in(AddPNode::Base)) {
- assert(kit != NULL, "no barrier should have been added");
-
- Node* address = adr->in(AddPNode::Address);
-
- if (address->is_AddP()) {
- assert(address->in(AddPNode::Base) == adr->in(AddPNode::Base), "unexpected address shape");
- assert(!address->in(AddPNode::Address)->is_AddP(), "unexpected address shape");
- assert(address->in(AddPNode::Address) == adr->in(AddPNode::Base), "unexpected address shape");
- address = address->clone();
- address->set_req(AddPNode::Base, base);
- address->set_req(AddPNode::Address, base);
- address = kit->gvn().transform(address);
- } else {
- assert(address == adr->in(AddPNode::Base), "unexpected address shape");
- address = base;
- }
- adr = adr->clone();
- adr->set_req(AddPNode::Base, base);
- adr->set_req(AddPNode::Address, address);
- adr = kit->gvn().transform(adr);
- access.addr().set_node(adr);
- }
- }
- }
-}
-
Node* ShenandoahBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
DecoratorSet decorators = access.decorators();
@@ -662,44 +515,8 @@
PhaseGVN& gvn = opt_access.gvn();
MergeMemNode* mm = opt_access.mem();
- if (ShenandoahStoreValReadBarrier) {
- RegionNode* region = new RegionNode(3);
- const Type* v_t = gvn.type(val.node());
- Node* phi = new PhiNode(region, v_t->isa_oopptr() ? v_t->is_oopptr()->cast_to_nonconst() : v_t);
- Node* cmp = gvn.transform(new CmpPNode(val.node(), gvn.zerocon(T_OBJECT)));
- Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::ne));
- IfNode* iff = new IfNode(opt_access.ctl(), bol, PROB_LIKELY_MAG(3), COUNT_UNKNOWN);
-
- gvn.transform(iff);
- if (gvn.is_IterGVN()) {
- gvn.is_IterGVN()->_worklist.push(iff);
- } else {
- gvn.record_for_igvn(iff);
- }
-
- Node* null_true = gvn.transform(new IfFalseNode(iff));
- Node* null_false = gvn.transform(new IfTrueNode(iff));
- region->init_req(1, null_true);
- region->init_req(2, null_false);
- phi->init_req(1, gvn.zerocon(T_OBJECT));
- Node* cast = new CastPPNode(val.node(), gvn.type(val.node())->join_speculative(TypePtr::NOTNULL));
- cast->set_req(0, null_false);
- cast = gvn.transform(cast);
- Node* rb = gvn.transform(new ShenandoahReadBarrierNode(null_false, gvn.C->immutable_memory(), cast, false));
- phi->init_req(2, rb);
- opt_access.set_ctl(gvn.transform(region));
- val.set_node(gvn.transform(phi));
- }
if (ShenandoahStoreValEnqueueBarrier) {
- const TypePtr* adr_type = ShenandoahBarrierNode::brooks_pointer_type(gvn.type(val.node()));
- int alias = gvn.C->get_alias_index(adr_type);
- Node* wb = new ShenandoahWriteBarrierNode(gvn.C, opt_access.ctl(), mm->memory_at(alias), val.node());
- Node* wb_transformed = gvn.transform(wb);
- Node* enqueue = gvn.transform(new ShenandoahEnqueueBarrierNode(wb_transformed));
- if (wb_transformed == wb) {
- Node* proj = gvn.transform(new ShenandoahWBMemProjNode(wb));
- mm->set_memory_at(alias, proj);
- }
+ Node* enqueue = gvn.transform(new ShenandoahEnqueueBarrierNode(val.node()));
val.set_node(enqueue);
}
}
@@ -724,6 +541,17 @@
Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top;
Node* load = BarrierSetC2::load_at_resolved(access, val_type);
+ if (access.is_oop()) {
+ if (ShenandoahLoadRefBarrier) {
+ load = new ShenandoahLoadReferenceBarrierNode(NULL, load);
+ if (access.is_parse_access()) {
+ load = static_cast<C2ParseAccess &>(access).kit()->gvn().transform(load);
+ } else {
+ load = static_cast<C2OptAccess &>(access).gvn().transform(load);
+ }
+ }
+ }
+
// If we are reading the value of the referent field of a Reference
// object (either by using Unsafe directly or through reflection)
// then, if SATB is enabled, we need to record the referent in an
@@ -797,9 +625,10 @@
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
- return kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
+ load_store = kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
}
#endif
+ load_store = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, load_store));
return load_store;
}
return BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, value_type);
@@ -867,6 +696,7 @@
}
Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, val, value_type);
if (access.is_oop()) {
+ result = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, result));
shenandoah_write_barrier_pre(kit, false /* do_load */,
NULL, NULL, max_juint, NULL, NULL,
result /* pre_val */, T_OBJECT);
@@ -876,19 +706,9 @@
void ShenandoahBarrierSetC2::clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const {
assert(!src->is_AddP(), "unexpected input");
- src = shenandoah_read_barrier(kit, src);
BarrierSetC2::clone(kit, src, dst, size, is_array);
}
-Node* ShenandoahBarrierSetC2::resolve(GraphKit* kit, Node* n, DecoratorSet decorators) const {
- bool is_write = decorators & ACCESS_WRITE;
- if (is_write) {
- return shenandoah_write_barrier(kit, n);
- } else {
- return shenandoah_read_barrier(kit, n);
- }
-}
-
Node* ShenandoahBarrierSetC2::obj_allocate(PhaseMacroExpand* macro, Node* ctrl, Node* mem, Node* toobig_false, Node* size_in_bytes,
Node*& i_o, Node*& needgc_ctrl,
Node*& fast_oop_ctrl, Node*& fast_oop_rawmem,
@@ -915,6 +735,7 @@
// Support for GC barriers emitted during parsing
bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const {
+ if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) return true;
if (node->Opcode() != Op_CallLeaf && node->Opcode() != Op_CallLeafNoFP) {
return false;
}
@@ -929,26 +750,30 @@
}
Node* ShenandoahBarrierSetC2::step_over_gc_barrier(Node* c) const {
- return ShenandoahBarrierNode::skip_through_barrier(c);
+ if (c->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
+ return c->in(ShenandoahLoadReferenceBarrierNode::ValueIn);
+ }
+ if (c->Opcode() == Op_ShenandoahEnqueueBarrier) {
+ c = c->in(1);
+ }
+ return c;
}
bool ShenandoahBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const {
- return !ShenandoahWriteBarrierNode::expand(C, igvn);
+ return !ShenandoahBarrierC2Support::expand(C, igvn);
}
bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const {
if (mode == LoopOptsShenandoahExpand) {
assert(UseShenandoahGC, "only for shenandoah");
- ShenandoahWriteBarrierNode::pin_and_expand(phase);
+ ShenandoahBarrierC2Support::pin_and_expand(phase);
return true;
} else if (mode == LoopOptsShenandoahPostExpand) {
assert(UseShenandoahGC, "only for shenandoah");
visited.Clear();
- ShenandoahWriteBarrierNode::optimize_after_expansion(visited, nstack, worklist, phase);
+ ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase);
return true;
}
- GrowableArray<MemoryGraphFixer*> memory_graph_fixers;
- ShenandoahWriteBarrierNode::optimize_before_expansion(phase, memory_graph_fixers, false);
return false;
}
@@ -957,7 +782,6 @@
if (!is_oop) {
return false;
}
-
if (tightly_coupled_alloc) {
if (phase == Optimization) {
return false;
@@ -985,7 +809,7 @@
}
} else {
return true;
- }
+ }
} else if (src_type->isa_aryptr()) {
BasicType src_elem = src_type->klass()->as_array_klass()->element_type()->basic_type();
if (src_elem == T_OBJECT || src_elem == T_ARRAY) {
@@ -1038,14 +862,20 @@
// Support for macro expanded GC barriers
void ShenandoahBarrierSetC2::register_potential_barrier_node(Node* node) const {
- if (node->Opcode() == Op_ShenandoahWriteBarrier) {
- state()->add_shenandoah_barrier((ShenandoahWriteBarrierNode*) node);
+ if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
+ state()->add_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);
+ }
+ if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
+ state()->add_load_reference_barrier((ShenandoahLoadReferenceBarrierNode*) node);
}
}
void ShenandoahBarrierSetC2::unregister_potential_barrier_node(Node* node) const {
- if (node->Opcode() == Op_ShenandoahWriteBarrier) {
- state()->remove_shenandoah_barrier((ShenandoahWriteBarrierNode*) node);
+ if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
+ state()->remove_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);
+ }
+ if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
+ state()->remove_load_reference_barrier((ShenandoahLoadReferenceBarrierNode*) node);
}
}
@@ -1091,19 +921,18 @@
}
}
}
- for (int i = state()->shenandoah_barriers_count()-1; i >= 0; i--) {
- ShenandoahWriteBarrierNode* n = state()->shenandoah_barrier(i);
+ for (int i = state()->enqueue_barriers_count() - 1; i >= 0; i--) {
+ ShenandoahEnqueueBarrierNode* n = state()->enqueue_barrier(i);
if (!useful.member(n)) {
- state()->remove_shenandoah_barrier(n);
+ state()->remove_enqueue_barrier(n);
}
}
-
-}
-
-bool ShenandoahBarrierSetC2::has_special_unique_user(const Node* node) const {
- assert(node->outcnt() == 1, "match only for unique out");
- Node* n = node->unique_out();
- return node->Opcode() == Op_ShenandoahWriteBarrier && n->Opcode() == Op_ShenandoahWBMemProj;
+ for (int i = state()->load_reference_barriers_count() - 1; i >= 0; i--) {
+ ShenandoahLoadReferenceBarrierNode* n = state()->load_reference_barrier(i);
+ if (!useful.member(n)) {
+ state()->remove_load_reference_barrier(n);
+ }
+ }
}
void ShenandoahBarrierSetC2::add_users_to_worklist(Unique_Node_List* worklist) const {}
@@ -1123,7 +952,7 @@
#ifdef ASSERT
void ShenandoahBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) const {
if (ShenandoahVerifyOptoBarriers && phase == BarrierSetC2::BeforeExpand) {
- ShenandoahBarrierNode::verify(Compile::current()->root());
+ ShenandoahBarrierC2Support::verify(Compile::current()->root());
} else if (phase == BarrierSetC2::BeforeCodeGen) {
// Verify G1 pre-barriers
const int marking_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset());
@@ -1229,7 +1058,7 @@
}
} else if (can_reshape &&
n->Opcode() == Op_If &&
- ShenandoahWriteBarrierNode::is_heap_stable_test(n) &&
+ ShenandoahBarrierC2Support::is_heap_stable_test(n) &&
n->in(0) != NULL) {
Node* dom = n->in(0);
Node* prev_dom = n;
@@ -1237,7 +1066,7 @@
int dist = 16;
// Search up the dominator tree for another heap stable test
while (dom->Opcode() != op || // Not same opcode?
- !ShenandoahWriteBarrierNode::is_heap_stable_test(dom) || // Not same input 1?
+ !ShenandoahBarrierC2Support::is_heap_stable_test(dom) || // Not same input 1?
prev_dom->in(0) != dom) { // One path of test does not dominate?
if (dist < 0) return NULL;
@@ -1258,46 +1087,6 @@
return NULL;
}
-Node* ShenandoahBarrierSetC2::identity_node(PhaseGVN* phase, Node* n) const {
- if (n->is_Load()) {
- Node *mem = n->in(MemNode::Memory);
- Node *value = n->as_Load()->can_see_stored_value(mem, phase);
- if (value) {
- PhaseIterGVN *igvn = phase->is_IterGVN();
- if (igvn != NULL &&
- value->is_Phi() &&
- value->req() > 2 &&
- value->in(1) != NULL &&
- value->in(1)->is_ShenandoahBarrier()) {
- if (igvn->_worklist.member(value) ||
- igvn->_worklist.member(value->in(0)) ||
- (value->in(0)->in(1) != NULL &&
- value->in(0)->in(1)->is_IfProj() &&
- (igvn->_worklist.member(value->in(0)->in(1)) ||
- (value->in(0)->in(1)->in(0) != NULL &&
- igvn->_worklist.member(value->in(0)->in(1)->in(0)))))) {
- igvn->_worklist.push(n);
- return n;
- }
- }
- // (This works even when value is a Con, but LoadNode::Value
- // usually runs first, producing the singleton type of the Con.)
- Node *value_no_barrier = step_over_gc_barrier(value->Opcode() == Op_EncodeP ? value->in(1) : value);
- if (value->Opcode() == Op_EncodeP) {
- if (value_no_barrier != value->in(1)) {
- Node *encode = value->clone();
- encode->set_req(1, value_no_barrier);
- encode = phase->transform(encode);
- return encode;
- }
- } else {
- return value_no_barrier;
- }
- }
- }
- return n;
-}
-
bool ShenandoahBarrierSetC2::has_only_shenandoah_wb_pre_uses(Node* n) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* u = n->fast_out(i);
@@ -1308,20 +1097,6 @@
return n->outcnt() > 0;
}
-bool ShenandoahBarrierSetC2::flatten_gc_alias_type(const TypePtr*& adr_type) const {
- int offset = adr_type->offset();
- if (offset == ShenandoahBrooksPointer::byte_offset()) {
- if (adr_type->isa_aryptr()) {
- adr_type = TypeAryPtr::make(adr_type->ptr(), adr_type->isa_aryptr()->ary(), adr_type->isa_aryptr()->klass(), false, offset);
- } else if (adr_type->isa_instptr()) {
- adr_type = TypeInstPtr::make(adr_type->ptr(), ciEnv::current()->Object_klass(), false, NULL, offset);
- }
- return true;
- } else {
- return false;
- }
-}
-
bool ShenandoahBarrierSetC2::final_graph_reshaping(Compile* compile, Node* n, uint opcode) const {
switch (opcode) {
case Op_CallLeaf:
@@ -1356,9 +1131,7 @@
}
#endif
return true;
- case Op_ShenandoahReadBarrier:
- return true;
- case Op_ShenandoahWriteBarrier:
+ case Op_ShenandoahLoadReferenceBarrier:
assert(false, "should have been expanded already");
return true;
default:
@@ -1366,17 +1139,6 @@
}
}
-#ifdef ASSERT
-bool ShenandoahBarrierSetC2::verify_gc_alias_type(const TypePtr* adr_type, int offset) const {
- if (offset == ShenandoahBrooksPointer::byte_offset() &&
- (adr_type->base() == Type::AryPtr || adr_type->base() == Type::OopPtr)) {
- return true;
- } else {
- return false;
- }
-}
-#endif
-
bool ShenandoahBarrierSetC2::escape_add_to_con_graph(ConnectionGraph* conn_graph, PhaseGVN* gvn, Unique_Node_List* delayed_worklist, Node* n, uint opcode) const {
switch (opcode) {
case Op_ShenandoahCompareAndExchangeP:
@@ -1412,15 +1174,12 @@
}
return false;
}
- case Op_ShenandoahReadBarrier:
- case Op_ShenandoahWriteBarrier:
- // Barriers 'pass through' its arguments. I.e. what goes in, comes out.
- // It doesn't escape.
- conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahBarrierNode::ValueIn), delayed_worklist);
- break;
case Op_ShenandoahEnqueueBarrier:
conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), delayed_worklist);
break;
+ case Op_ShenandoahLoadReferenceBarrier:
+ conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), delayed_worklist);
+ return true;
default:
// Nothing
break;
@@ -1441,15 +1200,12 @@
case Op_ShenandoahWeakCompareAndSwapP:
case Op_ShenandoahWeakCompareAndSwapN:
return conn_graph->add_final_edges_unsafe_access(n, opcode);
- case Op_ShenandoahReadBarrier:
- case Op_ShenandoahWriteBarrier:
- // Barriers 'pass through' its arguments. I.e. what goes in, comes out.
- // It doesn't escape.
- conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahBarrierNode::ValueIn), NULL);
- return true;
case Op_ShenandoahEnqueueBarrier:
conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), NULL);
return true;
+ case Op_ShenandoahLoadReferenceBarrier:
+ conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), NULL);
+ return true;
default:
// Nothing
break;
@@ -1464,21 +1220,7 @@
}
bool ShenandoahBarrierSetC2::escape_is_barrier_node(Node* n) const {
- return n->is_ShenandoahBarrier();
-}
-
-bool ShenandoahBarrierSetC2::matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const {
- switch (opcode) {
- case Op_ShenandoahReadBarrier:
- if (n->in(ShenandoahBarrierNode::ValueIn)->is_DecodeNarrowPtr()) {
- matcher->set_shared(n->in(ShenandoahBarrierNode::ValueIn)->in(1));
- }
- matcher->set_shared(n);
- return true;
- default:
- break;
- }
- return false;
+ return n->Opcode() == Op_ShenandoahLoadReferenceBarrier;
}
bool ShenandoahBarrierSetC2::matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const {
@@ -1510,62 +1252,3 @@
xop == Op_ShenandoahCompareAndSwapN ||
xop == Op_ShenandoahCompareAndSwapP;
}
-
-void ShenandoahBarrierSetC2::igvn_add_users_to_worklist(PhaseIterGVN* igvn, Node* use) const {
- if (use->is_ShenandoahBarrier()) {
- for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
- Node* u = use->fast_out(i2);
- Node* cmp = use->find_out_with(Op_CmpP);
- if (u->Opcode() == Op_CmpP) {
- igvn->_worklist.push(cmp);
- }
- }
- }
-}
-
-void ShenandoahBarrierSetC2::ccp_analyze(PhaseCCP* ccp, Unique_Node_List& worklist, Node* use) const {
- if (use->is_ShenandoahBarrier()) {
- for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
- Node* p = use->fast_out(i2);
- if (p->Opcode() == Op_AddP) {
- for (DUIterator_Fast i3max, i3 = p->fast_outs(i3max); i3 < i3max; i3++) {
- Node* q = p->fast_out(i3);
- if (q->is_Load()) {
- if(q->bottom_type() != ccp->type(q)) {
- worklist.push(q);
- }
- }
- }
- }
- }
- }
-}
-
-Node* ShenandoahBarrierSetC2::split_if_pre(PhaseIdealLoop* phase, Node* n) const {
- if (n->Opcode() == Op_ShenandoahReadBarrier) {
- ((ShenandoahReadBarrierNode*)n)->try_move(phase);
- } else if (n->Opcode() == Op_ShenandoahWriteBarrier) {
- return ((ShenandoahWriteBarrierNode*)n)->try_split_thru_phi(phase);
- }
-
- return NULL;
-}
-
-bool ShenandoahBarrierSetC2::build_loop_late_post(PhaseIdealLoop* phase, Node* n) const {
- return ShenandoahBarrierNode::build_loop_late_post(phase, n);
-}
-
-bool ShenandoahBarrierSetC2::sink_node(PhaseIdealLoop* phase, Node* n, Node* x, Node* x_ctrl, Node* n_ctrl) const {
- if (n->is_ShenandoahBarrier()) {
- return x->as_ShenandoahBarrier()->sink_node(phase, x_ctrl, n_ctrl);
- }
- if (n->is_MergeMem()) {
- // PhaseIdealLoop::split_if_with_blocks_post() would:
- // _igvn._worklist.yank(x);
- // which sometimes causes chains of MergeMem which some of
- // shenandoah specific code doesn't support
- phase->register_new_node(x, x_ctrl);
- return true;
- }
- return false;
-}
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -30,14 +30,21 @@
class ShenandoahBarrierSetC2State : public ResourceObj {
private:
- GrowableArray<ShenandoahWriteBarrierNode*>* _shenandoah_barriers;
+ GrowableArray<ShenandoahEnqueueBarrierNode*>* _enqueue_barriers;
+ GrowableArray<ShenandoahLoadReferenceBarrierNode*>* _load_reference_barriers;
public:
ShenandoahBarrierSetC2State(Arena* comp_arena);
- int shenandoah_barriers_count() const;
- ShenandoahWriteBarrierNode* shenandoah_barrier(int idx) const;
- void add_shenandoah_barrier(ShenandoahWriteBarrierNode * n);
- void remove_shenandoah_barrier(ShenandoahWriteBarrierNode * n);
+
+ int enqueue_barriers_count() const;
+ ShenandoahEnqueueBarrierNode* enqueue_barrier(int idx) const;
+ void add_enqueue_barrier(ShenandoahEnqueueBarrierNode* n);
+ void remove_enqueue_barrier(ShenandoahEnqueueBarrierNode * n);
+
+ int load_reference_barriers_count() const;
+ ShenandoahLoadReferenceBarrierNode* load_reference_barrier(int idx) const;
+ void add_load_reference_barrier(ShenandoahLoadReferenceBarrierNode* n);
+ void remove_load_reference_barrier(ShenandoahLoadReferenceBarrierNode * n);
};
class ShenandoahBarrierSetC2 : public BarrierSetC2 {
@@ -66,12 +73,7 @@
BasicType bt) const;
Node* shenandoah_enqueue_barrier(GraphKit* kit, Node* val) const;
- Node* shenandoah_read_barrier(GraphKit* kit, Node* obj) const;
Node* shenandoah_storeval_barrier(GraphKit* kit, Node* obj) const;
- Node* shenandoah_write_barrier(GraphKit* kit, Node* obj) const;
- Node* shenandoah_read_barrier_impl(GraphKit* kit, Node* obj, bool use_ctrl, bool use_mem, bool allow_fromspace) const;
- Node* shenandoah_write_barrier_impl(GraphKit* kit, Node* obj) const;
- Node* shenandoah_write_barrier_helper(GraphKit* kit, Node* obj, const TypePtr* adr_type) const;
void insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* offset,
Node* pre_val, bool need_mem_bar) const;
@@ -79,7 +81,6 @@
static bool clone_needs_postbarrier(ArrayCopyNode *ac, PhaseIterGVN& igvn);
protected:
- virtual void resolve_address(C2Access& access) const;
virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const;
virtual Node* store_at_resolved(C2Access& access, C2AccessValue& val) const;
virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
@@ -102,12 +103,11 @@
static const TypeFunc* write_ref_field_pre_entry_Type();
static const TypeFunc* shenandoah_clone_barrier_Type();
static const TypeFunc* shenandoah_write_barrier_Type();
+ virtual bool has_load_barriers() const { return true; }
// This is the entry-point for the backend to perform accesses through the Access API.
virtual void clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const;
- virtual Node* resolve(GraphKit* kit, Node* n, DecoratorSet decorators) const;
-
virtual Node* obj_allocate(PhaseMacroExpand* macro, Node* ctrl, Node* mem, Node* toobig_false, Node* size_in_bytes,
Node*& i_o, Node*& needgc_ctrl,
Node*& fast_oop_ctrl, Node*& fast_oop_rawmem,
@@ -144,13 +144,7 @@
virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const;
#endif
- virtual bool flatten_gc_alias_type(const TypePtr*& adr_type) const;
-#ifdef ASSERT
- virtual bool verify_gc_alias_type(const TypePtr* adr_type, int offset) const;
-#endif
-
virtual Node* ideal_node(PhaseGVN* phase, Node* n, bool can_reshape) const;
- virtual Node* identity_node(PhaseGVN* phase, Node* n) const;
virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode) const;
virtual bool escape_add_to_con_graph(ConnectionGraph* conn_graph, PhaseGVN* gvn, Unique_Node_List* delayed_worklist, Node* n, uint opcode) const;
@@ -158,17 +152,8 @@
virtual bool escape_has_out_with_unsafe_object(Node* n) const;
virtual bool escape_is_barrier_node(Node* n) const;
- virtual bool matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const;
virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const;
virtual bool matcher_is_store_load_barrier(Node* x, uint xop) const;
-
- virtual void igvn_add_users_to_worklist(PhaseIterGVN* igvn, Node* use) const;
- virtual void ccp_analyze(PhaseCCP* ccp, Unique_Node_List& worklist, Node* use) const;
-
- virtual bool has_special_unique_user(const Node* node) const;
- virtual Node* split_if_pre(PhaseIdealLoop* phase, Node* n) const;
- virtual bool build_loop_late_post(PhaseIdealLoop* phase, Node* n) const;
- virtual bool sink_node(PhaseIdealLoop* phase, Node* n, Node* x, Node* x_ctrl, Node* n_ctrl) const;
};
#endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHBARRIERSETC2_HPP
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -41,383 +41,28 @@
#include "opto/runtime.hpp"
#include "opto/subnode.hpp"
-Node* ShenandoahBarrierNode::skip_through_barrier(Node* n) {
- if (n == NULL) {
- return NULL;
- }
- if (n->Opcode() == Op_ShenandoahEnqueueBarrier) {
- n = n->in(1);
- }
-
- if (n->is_ShenandoahBarrier()) {
- return n->in(ValueIn);
- } else if (n->is_Phi() &&
- n->req() == 3 &&
- n->in(1) != NULL &&
- n->in(1)->is_ShenandoahBarrier() &&
- n->in(2) != NULL &&
- n->in(2)->bottom_type() == TypePtr::NULL_PTR &&
- n->in(0) != NULL &&
- n->in(0)->in(1) != NULL &&
- n->in(0)->in(1)->is_IfProj() &&
- n->in(0)->in(2) != NULL &&
- n->in(0)->in(2)->is_IfProj() &&
- n->in(0)->in(1)->in(0) != NULL &&
- n->in(0)->in(1)->in(0) == n->in(0)->in(2)->in(0) &&
- n->in(1)->in(ValueIn)->Opcode() == Op_CastPP) {
- Node* iff = n->in(0)->in(1)->in(0);
- Node* res = n->in(1)->in(ValueIn)->in(1);
- if (iff->is_If() &&
- iff->in(1) != NULL &&
- iff->in(1)->is_Bool() &&
- iff->in(1)->as_Bool()->_test._test == BoolTest::ne &&
- iff->in(1)->in(1) != NULL &&
- iff->in(1)->in(1)->Opcode() == Op_CmpP &&
- iff->in(1)->in(1)->in(1) != NULL &&
- iff->in(1)->in(1)->in(1) == res &&
- iff->in(1)->in(1)->in(2) != NULL &&
- iff->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) {
- return res;
- }
- }
- return n;
-}
-
-bool ShenandoahBarrierNode::needs_barrier(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace) {
- Unique_Node_List visited;
- return needs_barrier_impl(phase, orig, n, rb_mem, allow_fromspace, visited);
-}
-
-bool ShenandoahBarrierNode::needs_barrier_impl(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace, Unique_Node_List &visited) {
- if (visited.member(n)) {
- return false; // Been there.
- }
- visited.push(n);
-
- if (n->is_Allocate()) {
- return false;
- }
-
- if (n->is_Call()) {
- return true;
- }
-
- const Type* type = phase->type(n);
- if (type == Type::TOP) {
- return false;
- }
- if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) {
- return false;
- }
- if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL) {
- return false;
- }
-
- if (ShenandoahOptimizeStableFinals) {
- const TypeAryPtr* ary = type->isa_aryptr();
- if (ary && ary->is_stable() && allow_fromspace) {
- return false;
- }
- }
-
- if (n->is_CheckCastPP() || n->is_ConstraintCast() || n->Opcode() == Op_ShenandoahEnqueueBarrier) {
- return needs_barrier_impl(phase, orig, n->in(1), rb_mem, allow_fromspace, visited);
- }
- if (n->is_Parm()) {
- return true;
- }
- if (n->is_Proj()) {
- return needs_barrier_impl(phase, orig, n->in(0), rb_mem, allow_fromspace, visited);
- }
-
- if (n->Opcode() == Op_ShenandoahWBMemProj) {
- return needs_barrier_impl(phase, orig, n->in(ShenandoahWBMemProjNode::WriteBarrier), rb_mem, allow_fromspace, visited);
- }
- if (n->is_Phi()) {
- bool need_barrier = false;
- for (uint i = 1; i < n->req() && ! need_barrier; i++) {
- Node* input = n->in(i);
- if (input == NULL) {
- need_barrier = true; // Phi not complete yet?
- } else if (needs_barrier_impl(phase, orig, input, rb_mem, allow_fromspace, visited)) {
- need_barrier = true;
- }
- }
- return need_barrier;
- }
- if (n->is_CMove()) {
- return needs_barrier_impl(phase, orig, n->in(CMoveNode::IfFalse), rb_mem, allow_fromspace, visited) ||
- needs_barrier_impl(phase, orig, n->in(CMoveNode::IfTrue ), rb_mem, allow_fromspace, visited);
- }
- if (n->Opcode() == Op_CreateEx) {
- return true;
- }
- if (n->Opcode() == Op_ShenandoahWriteBarrier) {
- return false;
- }
- if (n->Opcode() == Op_ShenandoahReadBarrier) {
- if (rb_mem == n->in(Memory)) {
- return false;
- } else {
- return true;
- }
- }
-
- if (n->Opcode() == Op_LoadP ||
- n->Opcode() == Op_LoadN ||
- n->Opcode() == Op_GetAndSetP ||
- n->Opcode() == Op_CompareAndExchangeP ||
- n->Opcode() == Op_ShenandoahCompareAndExchangeP ||
- n->Opcode() == Op_GetAndSetN ||
- n->Opcode() == Op_CompareAndExchangeN ||
- n->Opcode() == Op_ShenandoahCompareAndExchangeN) {
- return true;
- }
- if (n->Opcode() == Op_DecodeN ||
- n->Opcode() == Op_EncodeP) {
- return needs_barrier_impl(phase, orig, n->in(1), rb_mem, allow_fromspace, visited);
- }
-
-#ifdef ASSERT
- tty->print("need barrier on?: "); n->dump();
- ShouldNotReachHere();
-#endif
- return true;
-}
-
-bool ShenandoahReadBarrierNode::dominates_memory_rb_impl(PhaseGVN* phase,
- Node* b1,
- Node* b2,
- Node* current,
- bool linear) {
- ResourceMark rm;
- VectorSet visited(Thread::current()->resource_area());
- Node_Stack phis(0);
-
- for(int i = 0; i < 10; i++) {
- if (current == NULL) {
- return false;
- } else if (visited.test_set(current->_idx) || current->is_top() || current == b1) {
- current = NULL;
- while (phis.is_nonempty() && current == NULL) {
- uint idx = phis.index();
- Node* phi = phis.node();
- if (idx >= phi->req()) {
- phis.pop();
- } else {
- current = phi->in(idx);
- phis.set_index(idx+1);
- }
- }
- if (current == NULL) {
- return true;
- }
- } else if (current == phase->C->immutable_memory()) {
- return false;
- } else if (current->isa_Phi()) {
- if (!linear) {
+bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) {
+ ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state();
+ if ((state->enqueue_barriers_count() +
+ state->load_reference_barriers_count()) > 0) {
+ bool attempt_more_loopopts = ShenandoahLoopOptsAfterExpansion;
+ C->clear_major_progress();
+ PhaseIdealLoop ideal_loop(igvn, LoopOptsShenandoahExpand);
+ if (C->failing()) return false;
+ PhaseIdealLoop::verify(igvn);
+ DEBUG_ONLY(verify_raw_mem(C->root());)
+ if (attempt_more_loopopts) {
+ C->set_major_progress();
+ if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) {
return false;
}
- phis.push(current, 2);
- current = current->in(1);
- } else if (current->Opcode() == Op_ShenandoahWriteBarrier) {
- const Type* in_type = current->bottom_type();
- const Type* this_type = b2->bottom_type();
- if (is_independent(in_type, this_type)) {
- current = current->in(Memory);
- } else {
- return false;
- }
- } else if (current->Opcode() == Op_ShenandoahWBMemProj) {
- current = current->in(ShenandoahWBMemProjNode::WriteBarrier);
- } else if (current->is_Proj()) {
- current = current->in(0);
- } else if (current->is_Call()) {
- return false; // TODO: Maybe improve by looking at the call's memory effects?
- } else if (current->is_MemBar()) {
- return false; // TODO: Do we need to stop at *any* membar?
- } else if (current->is_MergeMem()) {
- const TypePtr* adr_type = brooks_pointer_type(phase->type(b2));
- uint alias_idx = phase->C->get_alias_index(adr_type);
- current = current->as_MergeMem()->memory_at(alias_idx);
- } else {
-#ifdef ASSERT
- current->dump();
-#endif
- ShouldNotReachHere();
- return false;
- }
- }
- return false;
-}
-
-bool ShenandoahReadBarrierNode::is_independent(Node* mem) {
- if (mem->is_Phi() || mem->is_Proj() || mem->is_MergeMem()) {
- return true;
- } else if (mem->Opcode() == Op_ShenandoahWBMemProj) {
- return true;
- } else if (mem->Opcode() == Op_ShenandoahWriteBarrier) {
- const Type* mem_type = mem->bottom_type();
- const Type* this_type = bottom_type();
- if (is_independent(mem_type, this_type)) {
- return true;
- } else {
- return false;
- }
- } else if (mem->is_Call() || mem->is_MemBar()) {
- return false;
- }
-#ifdef ASSERT
- mem->dump();
-#endif
- ShouldNotReachHere();
- return true;
-}
-
-bool ShenandoahReadBarrierNode::dominates_memory_rb(PhaseGVN* phase, Node* b1, Node* b2, bool linear) {
- return dominates_memory_rb_impl(phase, b1->in(Memory), b2, b2->in(Memory), linear);
-}
-
-bool ShenandoahReadBarrierNode::is_independent(const Type* in_type, const Type* this_type) {
- assert(in_type->isa_oopptr(), "expect oop ptr");
- assert(this_type->isa_oopptr(), "expect oop ptr");
-
- ciKlass* in_kls = in_type->is_oopptr()->klass();
- ciKlass* this_kls = this_type->is_oopptr()->klass();
- if (in_kls != NULL && this_kls != NULL &&
- in_kls->is_loaded() && this_kls->is_loaded() &&
- (!in_kls->is_subclass_of(this_kls)) &&
- (!this_kls->is_subclass_of(in_kls))) {
- return true;
- }
- return false;
-}
-
-Node* ShenandoahReadBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) {
- if (! can_reshape) {
- return NULL;
- }
-
- if (in(Memory) == phase->C->immutable_memory()) return NULL;
-
- // If memory input is a MergeMem, take the appropriate slice out of it.
- Node* mem_in = in(Memory);
- if (mem_in->isa_MergeMem()) {
- const TypePtr* adr_type = brooks_pointer_type(bottom_type());
- uint alias_idx = phase->C->get_alias_index(adr_type);
- mem_in = mem_in->as_MergeMem()->memory_at(alias_idx);
- set_req(Memory, mem_in);
- return this;
- }
-
- Node* input = in(Memory);
- if (input->Opcode() == Op_ShenandoahWBMemProj) {
- ResourceMark rm;
- VectorSet seen(Thread::current()->resource_area());
- Node* n = in(Memory);
- while (n->Opcode() == Op_ShenandoahWBMemProj &&
- n->in(ShenandoahWBMemProjNode::WriteBarrier) != NULL &&
- n->in(ShenandoahWBMemProjNode::WriteBarrier)->Opcode() == Op_ShenandoahWriteBarrier &&
- n->in(ShenandoahWBMemProjNode::WriteBarrier)->in(Memory) != NULL) {
- if (seen.test_set(n->_idx)) {
- return NULL; // loop
- }
- n = n->in(ShenandoahWBMemProjNode::WriteBarrier)->in(Memory);
- }
-
- Node* wb = input->in(ShenandoahWBMemProjNode::WriteBarrier);
- const Type* in_type = phase->type(wb);
- // is_top() test not sufficient here: we can come here after CCP
- // in a dead branch of the graph that has not yet been removed.
- if (in_type == Type::TOP) return NULL; // Dead path.
- assert(wb->Opcode() == Op_ShenandoahWriteBarrier, "expect write barrier");
- if (is_independent(in_type, _type)) {
- phase->igvn_rehash_node_delayed(wb);
- set_req(Memory, wb->in(Memory));
- if (can_reshape && input->outcnt() == 0) {
- phase->is_IterGVN()->_worklist.push(input);
- }
- return this;
- }
- }
- return NULL;
-}
-
-ShenandoahWriteBarrierNode::ShenandoahWriteBarrierNode(Compile* C, Node* ctrl, Node* mem, Node* obj)
- : ShenandoahBarrierNode(ctrl, mem, obj, false) {
- assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
- ShenandoahBarrierSetC2::bsc2()->state()->add_shenandoah_barrier(this);
-}
-
-Node* ShenandoahWriteBarrierNode::Identity(PhaseGVN* phase) {
- assert(in(0) != NULL, "should have control");
- PhaseIterGVN* igvn = phase->is_IterGVN();
- Node* mem_in = in(Memory);
- Node* mem_proj = NULL;
-
- if (igvn != NULL) {
- mem_proj = find_out_with(Op_ShenandoahWBMemProj);
- if (mem_in == mem_proj) {
- return this;
- }
- }
-
- Node* replacement = Identity_impl(phase);
- if (igvn != NULL) {
- if (replacement != NULL && replacement != this && mem_proj != NULL) {
- igvn->replace_node(mem_proj, mem_in);
- }
- }
- return replacement;
-}
-
-Node* ShenandoahWriteBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) {
- assert(in(0) != NULL, "should have control");
- if (!can_reshape) {
- return NULL;
- }
-
- Node* mem_in = in(Memory);
-
- if (mem_in->isa_MergeMem()) {
- const TypePtr* adr_type = brooks_pointer_type(bottom_type());
- uint alias_idx = phase->C->get_alias_index(adr_type);
- mem_in = mem_in->as_MergeMem()->memory_at(alias_idx);
- set_req(Memory, mem_in);
- return this;
- }
-
- Node* val = in(ValueIn);
- if (val->is_ShenandoahBarrier()) {
- set_req(ValueIn, val->in(ValueIn));
- return this;
- }
-
- return NULL;
-}
-
-bool ShenandoahWriteBarrierNode::expand(Compile* C, PhaseIterGVN& igvn) {
- if (UseShenandoahGC) {
- if (ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count() > 0 || (!ShenandoahWriteBarrier && ShenandoahStoreValEnqueueBarrier)) {
- bool attempt_more_loopopts = ShenandoahLoopOptsAfterExpansion;
C->clear_major_progress();
- PhaseIdealLoop ideal_loop(igvn, LoopOptsShenandoahExpand);
- if (C->failing()) return false;
- PhaseIdealLoop::verify(igvn);
- DEBUG_ONLY(ShenandoahBarrierNode::verify_raw_mem(C->root());)
- if (attempt_more_loopopts) {
- C->set_major_progress();
- if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) {
- return false;
- }
- C->clear_major_progress();
- }
}
}
return true;
}
-bool ShenandoahWriteBarrierNode::is_heap_state_test(Node* iff, int mask) {
+bool ShenandoahBarrierC2Support::is_heap_state_test(Node* iff, int mask) {
if (!UseShenandoahGC) {
return false;
}
@@ -450,11 +95,11 @@
return is_gc_state_load(in1);
}
-bool ShenandoahWriteBarrierNode::is_heap_stable_test(Node* iff) {
+bool ShenandoahBarrierC2Support::is_heap_stable_test(Node* iff) {
return is_heap_state_test(iff, ShenandoahHeap::HAS_FORWARDED);
}
-bool ShenandoahWriteBarrierNode::is_gc_state_load(Node *n) {
+bool ShenandoahBarrierC2Support::is_gc_state_load(Node *n) {
if (!UseShenandoahGC) {
return false;
}
@@ -476,7 +121,7 @@
return true;
}
-bool ShenandoahWriteBarrierNode::has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase) {
+bool ShenandoahBarrierC2Support::has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase) {
assert(phase->is_dominator(stop, start), "bad inputs");
ResourceMark rm;
Unique_Node_List wq;
@@ -500,7 +145,7 @@
return false;
}
-bool ShenandoahWriteBarrierNode::try_common_gc_state_load(Node *n, PhaseIdealLoop *phase) {
+bool ShenandoahBarrierC2Support::try_common_gc_state_load(Node *n, PhaseIdealLoop *phase) {
assert(is_gc_state_load(n), "inconsistent");
Node* addp = n->in(MemNode::Address);
Node* dominator = NULL;
@@ -525,193 +170,8 @@
return true;
}
-bool ShenandoahBarrierNode::dominates_memory_impl(PhaseGVN* phase,
- Node* b1,
- Node* b2,
- Node* current,
- bool linear) {
- ResourceMark rm;
- VectorSet visited(Thread::current()->resource_area());
- Node_Stack phis(0);
-
- for(int i = 0; i < 10; i++) {
- if (current == NULL) {
- return false;
- } else if (visited.test_set(current->_idx) || current->is_top() || current == b1) {
- current = NULL;
- while (phis.is_nonempty() && current == NULL) {
- uint idx = phis.index();
- Node* phi = phis.node();
- if (idx >= phi->req()) {
- phis.pop();
- } else {
- current = phi->in(idx);
- phis.set_index(idx+1);
- }
- }
- if (current == NULL) {
- return true;
- }
- } else if (current == b2) {
- return false;
- } else if (current == phase->C->immutable_memory()) {
- return false;
- } else if (current->isa_Phi()) {
- if (!linear) {
- return false;
- }
- phis.push(current, 2);
- current = current->in(1);
- } else if (current->Opcode() == Op_ShenandoahWriteBarrier) {
- current = current->in(Memory);
- } else if (current->Opcode() == Op_ShenandoahWBMemProj) {
- current = current->in(ShenandoahWBMemProjNode::WriteBarrier);
- } else if (current->is_Proj()) {
- current = current->in(0);
- } else if (current->is_Call()) {
- current = current->in(TypeFunc::Memory);
- } else if (current->is_MemBar()) {
- current = current->in(TypeFunc::Memory);
- } else if (current->is_MergeMem()) {
- const TypePtr* adr_type = brooks_pointer_type(phase->type(b2));
- uint alias_idx = phase->C->get_alias_index(adr_type);
- current = current->as_MergeMem()->memory_at(alias_idx);
- } else {
#ifdef ASSERT
- current->dump();
-#endif
- ShouldNotReachHere();
- return false;
- }
- }
- return false;
-}
-
-/**
- * Determines if b1 dominates b2 through memory inputs. It returns true if:
- * - b1 can be reached by following each branch in b2's memory input (through phis, etc)
- * - or we get back to b2 (i.e. through a loop) without seeing b1
- * In all other cases, (in particular, if we reach immutable_memory without having seen b1)
- * we return false.
- */
-bool ShenandoahBarrierNode::dominates_memory(PhaseGVN* phase, Node* b1, Node* b2, bool linear) {
- return dominates_memory_impl(phase, b1, b2, b2->in(Memory), linear);
-}
-
-Node* ShenandoahBarrierNode::Identity_impl(PhaseGVN* phase) {
- Node* n = in(ValueIn);
-
- Node* rb_mem = Opcode() == Op_ShenandoahReadBarrier ? in(Memory) : NULL;
- if (! needs_barrier(phase, this, n, rb_mem, _allow_fromspace)) {
- return n;
- }
-
- // Try to find a write barrier sibling with identical inputs that we can fold into.
- for (DUIterator i = n->outs(); n->has_out(i); i++) {
- Node* sibling = n->out(i);
- if (sibling == this) {
- continue;
- }
- if (sibling->Opcode() != Op_ShenandoahWriteBarrier) {
- continue;
- }
-
- assert(sibling->in(ValueIn) == in(ValueIn), "sanity");
- assert(sibling->Opcode() == Op_ShenandoahWriteBarrier, "sanity");
-
- if (dominates_memory(phase, sibling, this, phase->is_IterGVN() == NULL)) {
- return sibling;
- }
- }
- return this;
-}
-
-#ifndef PRODUCT
-void ShenandoahBarrierNode::dump_spec(outputStream *st) const {
- const TypePtr* adr = adr_type();
- if (adr == NULL) {
- return;
- }
- st->print(" @");
- adr->dump_on(st);
- st->print(" (");
- Compile::current()->alias_type(adr)->adr_type()->dump_on(st);
- st->print(") ");
-}
-#endif
-
-Node* ShenandoahReadBarrierNode::Identity(PhaseGVN* phase) {
- Node* id = Identity_impl(phase);
-
- if (id == this && phase->is_IterGVN()) {
- Node* n = in(ValueIn);
- // No success in super call. Try to combine identical read barriers.
- for (DUIterator i = n->outs(); n->has_out(i); i++) {
- Node* sibling = n->out(i);
- if (sibling == this || sibling->Opcode() != Op_ShenandoahReadBarrier) {
- continue;
- }
- assert(sibling->in(ValueIn) == in(ValueIn), "sanity");
- if (phase->is_IterGVN()->hash_find(sibling) &&
- sibling->bottom_type() == bottom_type() &&
- sibling->in(Control) == in(Control) &&
- dominates_memory_rb(phase, sibling, this, phase->is_IterGVN() == NULL)) {
- return sibling;
- }
- }
- }
- return id;
-}
-
-const Type* ShenandoahBarrierNode::Value(PhaseGVN* phase) const {
- // Either input is TOP ==> the result is TOP
- const Type *t1 = phase->type(in(Memory));
- if (t1 == Type::TOP) return Type::TOP;
- const Type *t2 = phase->type(in(ValueIn));
- if( t2 == Type::TOP ) return Type::TOP;
-
- if (t2 == TypePtr::NULL_PTR) {
- return _type;
- }
-
- const Type* type = t2->is_oopptr()->cast_to_nonconst();
- return type;
-}
-
-uint ShenandoahBarrierNode::hash() const {
- return TypeNode::hash() + _allow_fromspace;
-}
-
-bool ShenandoahBarrierNode::cmp(const Node& n) const {
- return _allow_fromspace == ((ShenandoahBarrierNode&) n)._allow_fromspace
- && TypeNode::cmp(n);
-}
-
-uint ShenandoahBarrierNode::size_of() const {
- return sizeof(*this);
-}
-
-Node* ShenandoahWBMemProjNode::Identity(PhaseGVN* phase) {
- Node* wb = in(WriteBarrier);
- if (wb->is_top()) return phase->C->top(); // Dead path.
-
- assert(wb->Opcode() == Op_ShenandoahWriteBarrier, "expect write barrier");
- PhaseIterGVN* igvn = phase->is_IterGVN();
- // We can't do the below unless the graph is fully constructed.
- if (igvn == NULL) {
- return this;
- }
-
- // If the mem projection has no barrier users, it's not needed anymore.
- if (wb->outcnt() == 1) {
- return wb->in(ShenandoahBarrierNode::Memory);
- }
-
- return this;
-}
-
-#ifdef ASSERT
-bool ShenandoahBarrierNode::verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used) {
+bool ShenandoahBarrierC2Support::verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used) {
assert(phis.size() == 0, "");
while (true) {
@@ -732,12 +192,24 @@
in = in->in(AddPNode::Address);
continue;
} else if (in->is_Con()) {
- if (trace) {tty->print("Found constant"); in->dump();}
- } else if (in->is_ShenandoahBarrier()) {
+ if (trace) {
+ tty->print("Found constant");
+ in->dump();
+ }
+ } else if (in->Opcode() == Op_Parm) {
+ if (trace) {
+ tty->print("Found argument");
+ }
+ } else if (in->Opcode() == Op_CreateEx) {
+ if (trace) {
+ tty->print("Found create-exception");
+ }
+ } else if (in->Opcode() == Op_LoadP && in->adr_type() == TypeRawPtr::BOTTOM) {
+ if (trace) {
+ tty->print("Found raw LoadP (OSR argument?)");
+ }
+ } else if (in->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
if (t == ShenandoahOopStore) {
- if (in->Opcode() != Op_ShenandoahWriteBarrier) {
- return false;
- }
uint i = 0;
for (; i < phis.size(); i++) {
Node* n = phis.node_at(i);
@@ -748,8 +220,6 @@
if (i == phis.size()) {
return false;
}
- } else if (t == ShenandoahStore && in->Opcode() != Op_ShenandoahWriteBarrier) {
- return false;
}
barriers_used.push(in);
if (trace) {tty->print("Found barrier"); in->dump();}
@@ -763,7 +233,14 @@
in = in->in(1);
continue;
} else if (in->is_Proj() && in->in(0)->is_Allocate()) {
- if (trace) {tty->print("Found alloc"); in->in(0)->dump();}
+ if (trace) {
+ tty->print("Found alloc");
+ in->in(0)->dump();
+ }
+ } else if (in->is_Proj() && (in->in(0)->Opcode() == Op_CallStaticJava || in->in(0)->Opcode() == Op_CallDynamicJava)) {
+ if (trace) {
+ tty->print("Found Java call");
+ }
} else if (in->is_Phi()) {
if (!visited.test_set(in->_idx)) {
if (trace) {tty->print("Pushed phi:"); in->dump();}
@@ -809,7 +286,7 @@
return true;
}
-void ShenandoahBarrierNode::report_verify_failure(const char *msg, Node *n1, Node *n2) {
+void ShenandoahBarrierC2Support::report_verify_failure(const char* msg, Node* n1, Node* n2) {
if (n1 != NULL) {
n1->dump(+10);
}
@@ -819,7 +296,7 @@
fatal("%s", msg);
}
-void ShenandoahBarrierNode::verify(RootNode* root) {
+void ShenandoahBarrierC2Support::verify(RootNode* root) {
ResourceMark rm;
Unique_Node_List wq;
GrowableArray<Node*> barriers;
@@ -871,7 +348,7 @@
}
}
- if (verify && !ShenandoahBarrierNode::verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
+ if (verify && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: Load should have barriers", n);
}
}
@@ -899,11 +376,11 @@
}
}
- if (verify && !ShenandoahBarrierNode::verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahStoreValEnqueueBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {
+ if (verify && !verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahStoreValEnqueueBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: Store should have barriers", n);
}
}
- if (!ShenandoahBarrierNode::verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {
+ if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: Store (address) should have barriers", n);
}
} else if (n->Opcode() == Op_CmpP) {
@@ -926,26 +403,26 @@
} else {
assert(in2->bottom_type()->isa_oopptr(), "");
- if (!ShenandoahBarrierNode::verify_helper(in1, phis, visited, ShenandoahStore, trace, barriers_used) ||
- !ShenandoahBarrierNode::verify_helper(in2, phis, visited, ShenandoahStore, trace, barriers_used)) {
+ if (!verify_helper(in1, phis, visited, ShenandoahStore, trace, barriers_used) ||
+ !verify_helper(in2, phis, visited, ShenandoahStore, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: Cmp should have barriers", n);
}
}
if (verify_no_useless_barrier &&
mark_inputs &&
- (!ShenandoahBarrierNode::verify_helper(in1, phis, visited, ShenandoahValue, trace, barriers_used) ||
- !ShenandoahBarrierNode::verify_helper(in2, phis, visited, ShenandoahValue, trace, barriers_used))) {
+ (!verify_helper(in1, phis, visited, ShenandoahValue, trace, barriers_used) ||
+ !verify_helper(in2, phis, visited, ShenandoahValue, trace, barriers_used))) {
phis.clear();
visited.Reset();
}
}
} else if (n->is_LoadStore()) {
if (n->in(MemNode::ValueIn)->bottom_type()->make_ptr() &&
- !ShenandoahBarrierNode::verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahStoreValEnqueueBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {
+ !verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahStoreValEnqueueBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: LoadStore (value) should have barriers", n);
}
- if (n->in(MemNode::Address)->bottom_type()->make_oopptr() && !ShenandoahBarrierNode::verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {
+ if (n->in(MemNode::Address)->bottom_type()->make_oopptr() && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: LoadStore (address) should have barriers", n);
}
} else if (n->Opcode() == Op_CallLeafNoFP || n->Opcode() == Op_CallLeaf) {
@@ -1041,13 +518,13 @@
}
}
}
- if (!ShenandoahBarrierNode::verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahLoad, trace, barriers_used) ||
- !ShenandoahBarrierNode::verify_helper(dest, phis, visited, ShenandoahStore, trace, barriers_used)) {
+ if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahLoad, trace, barriers_used) ||
+ !verify_helper(dest, phis, visited, ShenandoahStore, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: ArrayCopy should have barriers", n);
}
} else if (strlen(call->_name) > 5 &&
!strcmp(call->_name + strlen(call->_name) - 5, "_fill")) {
- if (!ShenandoahBarrierNode::verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahStore, trace, barriers_used)) {
+ if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahStore, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: _fill should have barriers", n);
}
} else if (!strcmp(call->_name, "shenandoah_wb_pre")) {
@@ -1067,7 +544,7 @@
if (pos == -1) {
break;
}
- if (!ShenandoahBarrierNode::verify_helper(call->in(pos), phis, visited, calls[i].args[j].t, trace, barriers_used)) {
+ if (!verify_helper(call->in(pos), phis, visited, calls[i].args[j].t, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n);
}
}
@@ -1090,15 +567,8 @@
}
}
}
- } else if (n->is_ShenandoahBarrier()) {
- assert(!barriers.contains(n), "");
- assert(n->Opcode() != Op_ShenandoahWriteBarrier || n->find_out_with(Op_ShenandoahWBMemProj) != NULL, "bad shenandoah write barrier");
- assert(n->Opcode() != Op_ShenandoahWriteBarrier || n->outcnt() > 1, "bad shenandoah write barrier");
- barriers.push(n);
- } else if (n->Opcode() == Op_ShenandoahEnqueueBarrier) {
+ } else if (n->Opcode() == Op_ShenandoahEnqueueBarrier || n->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
// skip
- } else if (n->Opcode() == Op_ShenandoahWBMemProj) {
- assert(n->in(0) == NULL && n->in(ShenandoahWBMemProjNode::WriteBarrier)->Opcode() == Op_ShenandoahWriteBarrier, "strange ShenandoahWBMemProj");
} else if (n->is_AddP()
|| n->is_Phi()
|| n->is_ConstraintCast()
@@ -1165,7 +635,7 @@
if (pos == -1) {
break;
}
- if (!ShenandoahBarrierNode::verify_helper(n->in(pos), phis, visited, others[i].inputs[j].t, trace, barriers_used)) {
+ if (!verify_helper(n->in(pos), phis, visited, others[i].inputs[j].t, trace, barriers_used)) {
report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n);
}
}
@@ -1193,7 +663,7 @@
SafePointNode* sfpt = n->as_SafePoint();
if (verify_no_useless_barrier && sfpt->jvms() != NULL) {
for (uint i = sfpt->jvms()->scloff(); i < sfpt->jvms()->endoff(); i++) {
- if (!ShenandoahBarrierNode::verify_helper(sfpt->in(i), phis, visited, ShenandoahLoad, trace, barriers_used)) {
+ if (!verify_helper(sfpt->in(i), phis, visited, ShenandoahLoad, trace, barriers_used)) {
phis.clear();
visited.Reset();
}
@@ -1227,9 +697,8 @@
n->Opcode() == Op_SCMemProj ||
n->Opcode() == Op_EncodeP ||
n->Opcode() == Op_DecodeN ||
- n->Opcode() == Op_ShenandoahWriteBarrier ||
- n->Opcode() == Op_ShenandoahWBMemProj ||
- n->Opcode() == Op_ShenandoahEnqueueBarrier)) {
+ n->Opcode() == Op_ShenandoahEnqueueBarrier ||
+ n->Opcode() == Op_ShenandoahLoadReferenceBarrier)) {
if (m->bottom_type()->make_oopptr() && m->bottom_type()->make_oopptr()->meet(TypePtr::NULL_PTR) == m->bottom_type()) {
report_verify_failure("Shenandoah verification: null input", n, m);
}
@@ -1251,7 +720,7 @@
}
#endif
-bool ShenandoahBarrierNode::is_dominator_same_ctrl(Node*c, Node* d, Node* n, PhaseIdealLoop* phase) {
+bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) {
// That both nodes have the same control is not sufficient to prove
// domination, verify that there's no path from d to n
ResourceMark rm;
@@ -1275,7 +744,7 @@
return true;
}
-bool ShenandoahBarrierNode::is_dominator(Node *d_c, Node *n_c, Node* d, Node* n, PhaseIdealLoop* phase) {
+bool ShenandoahBarrierC2Support::is_dominator(Node* d_c, Node* n_c, Node* d, Node* n, PhaseIdealLoop* phase) {
if (d_c != n_c) {
return phase->is_dominator(d_c, n_c);
}
@@ -1290,15 +759,11 @@
res = mem->in(TypeFunc::Memory);
} else if (mem->is_Phi()) {
res = mem->in(1);
- } else if (mem->is_ShenandoahBarrier()) {
- res = mem->in(ShenandoahBarrierNode::Memory);
} else if (mem->is_MergeMem()) {
res = mem->as_MergeMem()->memory_at(alias);
} else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) {
assert(alias = Compile::AliasIdxRaw, "following raw memory can't lead to a barrier");
res = mem->in(MemNode::Memory);
- } else if (mem->Opcode() == Op_ShenandoahWBMemProj) {
- res = mem->in(ShenandoahWBMemProjNode::WriteBarrier);
} else {
#ifdef ASSERT
mem->dump();
@@ -1308,7 +773,7 @@
return res;
}
-Node* ShenandoahBarrierNode::no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase) {
+Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase) {
Node* iffproj = NULL;
while (c != dom) {
Node* next = phase->idom(c);
@@ -1373,270 +838,7 @@
return iffproj;
}
-bool ShenandoahBarrierNode::build_loop_late_post(PhaseIdealLoop* phase, Node* n) {
- if (n->Opcode() == Op_ShenandoahReadBarrier ||
- n->Opcode() == Op_ShenandoahWriteBarrier ||
- n->Opcode() == Op_ShenandoahWBMemProj) {
-
- phase->build_loop_late_post_work(n, false);
-
- if (n->Opcode() == Op_ShenandoahWriteBarrier) {
- // The write barrier and its memory proj must have the same
- // control otherwise some loop opts could put nodes (Phis) between
- // them
- Node* proj = n->find_out_with(Op_ShenandoahWBMemProj);
- if (proj != NULL) {
- phase->set_ctrl_and_loop(proj, phase->get_ctrl(n));
- }
- }
- return true;
- }
- return false;
-}
-
-bool ShenandoahBarrierNode::sink_node(PhaseIdealLoop* phase, Node* ctrl, Node* n_ctrl) {
- ctrl = phase->find_non_split_ctrl(ctrl);
- assert(phase->dom_depth(n_ctrl) <= phase->dom_depth(ctrl), "n is later than its clone");
- set_req(0, ctrl);
- phase->register_new_node(this, ctrl);
- return true;
-}
-
-#ifdef ASSERT
-void ShenandoahWriteBarrierNode::memory_dominates_all_paths_helper(Node* c, Node* rep_ctrl, Unique_Node_List& controls, PhaseIdealLoop* phase) {
- const bool trace = false;
- if (trace) { tty->print("X control is"); c->dump(); }
-
- uint start = controls.size();
- controls.push(c);
- for (uint i = start; i < controls.size(); i++) {
- Node *n = controls.at(i);
-
- if (trace) { tty->print("X from"); n->dump(); }
-
- if (n == rep_ctrl) {
- continue;
- }
-
- if (n->is_Proj()) {
- Node* n_dom = n->in(0);
- IdealLoopTree* n_dom_loop = phase->get_loop(n_dom);
- if (n->is_IfProj() && n_dom->outcnt() == 2) {
- n_dom_loop = phase->get_loop(n_dom->as_If()->proj_out(n->as_Proj()->_con == 0 ? 1 : 0));
- }
- if (n_dom_loop != phase->ltree_root()) {
- Node* tail = n_dom_loop->tail();
- if (tail->is_Region()) {
- for (uint j = 1; j < tail->req(); j++) {
- if (phase->is_dominator(n_dom, tail->in(j)) && !phase->is_dominator(n, tail->in(j))) {
- assert(phase->is_dominator(rep_ctrl, tail->in(j)), "why are we here?");
- // entering loop from below, mark backedge
- if (trace) { tty->print("X pushing backedge"); tail->in(j)->dump(); }
- controls.push(tail->in(j));
- //assert(n->in(0) == n_dom, "strange flow control");
- }
- }
- } else if (phase->get_loop(n) != n_dom_loop && phase->is_dominator(n_dom, tail)) {
- // entering loop from below, mark backedge
- if (trace) { tty->print("X pushing backedge"); tail->dump(); }
- controls.push(tail);
- //assert(n->in(0) == n_dom, "strange flow control");
- }
- }
- }
-
- if (n->is_Loop()) {
- Node* c = n->in(LoopNode::EntryControl);
- if (trace) { tty->print("X pushing"); c->dump(); }
- controls.push(c);
- } else if (n->is_Region()) {
- for (uint i = 1; i < n->req(); i++) {
- Node* c = n->in(i);
- if (trace) { tty->print("X pushing"); c->dump(); }
- controls.push(c);
- }
- } else {
- Node* c = n->in(0);
- if (trace) { tty->print("X pushing"); c->dump(); }
- controls.push(c);
- }
- }
-}
-
-bool ShenandoahWriteBarrierNode::memory_dominates_all_paths(Node* mem, Node* rep_ctrl, int alias, PhaseIdealLoop* phase) {
- const bool trace = false;
- if (trace) {
- tty->print("XXX mem is"); mem->dump();
- tty->print("XXX rep ctrl is"); rep_ctrl->dump();
- tty->print_cr("XXX alias is %d", alias);
- }
- ResourceMark rm;
- Unique_Node_List wq;
- Unique_Node_List controls;
- wq.push(mem);
- for (uint next = 0; next < wq.size(); next++) {
- Node *nn = wq.at(next);
- if (trace) { tty->print("XX from mem"); nn->dump(); }
- assert(nn->bottom_type() == Type::MEMORY, "memory only");
-
- if (nn->is_Phi()) {
- Node* r = nn->in(0);
- for (DUIterator_Fast jmax, j = r->fast_outs(jmax); j < jmax; j++) {
- Node* u = r->fast_out(j);
- if (u->is_Phi() && u->bottom_type() == Type::MEMORY && u != nn &&
- (u->adr_type() == TypePtr::BOTTOM || phase->C->get_alias_index(u->adr_type()) == alias)) {
- if (trace) { tty->print("XX Next mem (other phi)"); u->dump(); }
- wq.push(u);
- }
- }
- }
-
- for (DUIterator_Fast imax, i = nn->fast_outs(imax); i < imax; i++) {
- Node* use = nn->fast_out(i);
-
- if (trace) { tty->print("XX use %p", use->adr_type()); use->dump(); }
- if (use->is_CFG() && use->in(TypeFunc::Memory) == nn) {
- Node* c = use->in(0);
- if (phase->is_dominator(rep_ctrl, c)) {
- memory_dominates_all_paths_helper(c, rep_ctrl, controls, phase);
- } else if (use->is_CallStaticJava() && use->as_CallStaticJava()->uncommon_trap_request() != 0 && c->is_Region()) {
- Node* region = c;
- if (trace) { tty->print("XX unc region"); region->dump(); }
- for (uint j = 1; j < region->req(); j++) {
- if (phase->is_dominator(rep_ctrl, region->in(j))) {
- if (trace) { tty->print("XX unc follows"); region->in(j)->dump(); }
- memory_dominates_all_paths_helper(region->in(j), rep_ctrl, controls, phase);
- }
- }
- }
- //continue;
- } else if (use->is_Phi()) {
- assert(use->bottom_type() == Type::MEMORY, "bad phi");
- if ((use->adr_type() == TypePtr::BOTTOM) ||
- phase->C->get_alias_index(use->adr_type()) == alias) {
- for (uint j = 1; j < use->req(); j++) {
- if (use->in(j) == nn) {
- Node* c = use->in(0)->in(j);
- if (phase->is_dominator(rep_ctrl, c)) {
- memory_dominates_all_paths_helper(c, rep_ctrl, controls, phase);
- }
- }
- }
- }
- // continue;
- }
-
- if (use->is_MergeMem()) {
- if (use->as_MergeMem()->memory_at(alias) == nn) {
- if (trace) { tty->print("XX Next mem"); use->dump(); }
- // follow the memory edges
- wq.push(use);
- }
- } else if (use->is_Phi()) {
- assert(use->bottom_type() == Type::MEMORY, "bad phi");
- if ((use->adr_type() == TypePtr::BOTTOM) ||
- phase->C->get_alias_index(use->adr_type()) == alias) {
- if (trace) { tty->print("XX Next mem"); use->dump(); }
- // follow the memory edges
- wq.push(use);
- }
- } else if (use->bottom_type() == Type::MEMORY &&
- (use->adr_type() == TypePtr::BOTTOM || phase->C->get_alias_index(use->adr_type()) == alias)) {
- if (trace) { tty->print("XX Next mem"); use->dump(); }
- // follow the memory edges
- wq.push(use);
- } else if ((use->is_SafePoint() || use->is_MemBar()) &&
- (use->adr_type() == TypePtr::BOTTOM || phase->C->get_alias_index(use->adr_type()) == alias)) {
- for (DUIterator_Fast jmax, j = use->fast_outs(jmax); j < jmax; j++) {
- Node* u = use->fast_out(j);
- if (u->bottom_type() == Type::MEMORY) {
- if (trace) { tty->print("XX Next mem"); u->dump(); }
- // follow the memory edges
- wq.push(u);
- }
- }
- } else if (use->Opcode() == Op_ShenandoahWriteBarrier && phase->C->get_alias_index(use->adr_type()) == alias) {
- Node* m = use->find_out_with(Op_ShenandoahWBMemProj);
- if (m != NULL) {
- if (trace) { tty->print("XX Next mem"); m->dump(); }
- // follow the memory edges
- wq.push(m);
- }
- }
- }
- }
-
- if (controls.size() == 0) {
- return false;
- }
-
- for (uint i = 0; i < controls.size(); i++) {
- Node *n = controls.at(i);
-
- if (trace) { tty->print("X checking"); n->dump(); }
-
- if (n->unique_ctrl_out() != NULL) {
- continue;
- }
-
- if (n->Opcode() == Op_NeverBranch) {
- Node* taken = n->as_Multi()->proj_out(0);
- if (!controls.member(taken)) {
- if (trace) { tty->print("X not seen"); taken->dump(); }
- return false;
- }
- continue;
- }
-
- for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
- Node* u = n->fast_out(j);
-
- if (u->is_CFG()) {
- if (!controls.member(u)) {
- if (u->is_Proj() && u->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) {
- if (trace) { tty->print("X not seen but unc"); u->dump(); }
- } else {
- Node* c = u;
- do {
- c = c->unique_ctrl_out();
- } while (c != NULL && c->is_Region());
- if (c != NULL && c->Opcode() == Op_Halt) {
- if (trace) { tty->print("X not seen but halt"); c->dump(); }
- } else {
- if (trace) { tty->print("X not seen"); u->dump(); }
- return false;
- }
- }
- } else {
- if (trace) { tty->print("X seen"); u->dump(); }
- }
- }
- }
- }
- return true;
-}
-#endif
-
-Node* ShenandoahBarrierNode::dom_mem(Node* mem, Node*& mem_ctrl, Node* n, Node* rep_ctrl, int alias, PhaseIdealLoop* phase) {
- ResourceMark rm;
- VectorSet wq(Thread::current()->resource_area());
- wq.set(mem->_idx);
- mem_ctrl = phase->get_ctrl(mem);
- while (!is_dominator(mem_ctrl, rep_ctrl, mem, n, phase)) {
- mem = next_mem(mem, alias);
- if (wq.test_set(mem->_idx)) {
- return NULL; // hit an unexpected loop
- }
- mem_ctrl = phase->ctrl_or_self(mem);
- }
- if (mem->is_MergeMem()) {
- mem = mem->as_MergeMem()->memory_at(alias);
- mem_ctrl = phase->ctrl_or_self(mem);
- }
- return mem;
-}
-
-Node* ShenandoahBarrierNode::dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase) {
+Node* ShenandoahBarrierC2Support::dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase) {
ResourceMark rm;
VectorSet wq(Thread::current()->resource_area());
wq.set(mem->_idx);
@@ -1655,650 +857,7 @@
return mem;
}
-static void disconnect_barrier_mem(Node* wb, PhaseIterGVN& igvn) {
- Node* mem_in = wb->in(ShenandoahBarrierNode::Memory);
- Node* proj = wb->find_out_with(Op_ShenandoahWBMemProj);
-
- for (DUIterator_Last imin, i = proj->last_outs(imin); i >= imin; ) {
- Node* u = proj->last_out(i);
- igvn.rehash_node_delayed(u);
- int nb = u->replace_edge(proj, mem_in);
- assert(nb > 0, "no replacement?");
- i -= nb;
- }
-}
-
-Node* ShenandoahWriteBarrierNode::move_above_predicates(LoopNode* cl, Node* val_ctrl, PhaseIdealLoop* phase) {
- Node* entry = cl->skip_strip_mined(-1)->in(LoopNode::EntryControl);
- Node* above_pred = phase->skip_all_loop_predicates(entry);
- Node* ctrl = entry;
- while (ctrl != above_pred) {
- Node* next = ctrl->in(0);
- if (!phase->is_dominator(val_ctrl, next)) {
- break;
- }
- ctrl = next;
- }
- return ctrl;
-}
-
-static MemoryGraphFixer* find_fixer(GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, int alias) {
- for (int i = 0; i < memory_graph_fixers.length(); i++) {
- if (memory_graph_fixers.at(i)->alias() == alias) {
- return memory_graph_fixers.at(i);
- }
- }
- return NULL;
-}
-
-static MemoryGraphFixer* create_fixer(GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, int alias, PhaseIdealLoop* phase, bool include_lsm) {
- assert(find_fixer(memory_graph_fixers, alias) == NULL, "none should exist yet");
- MemoryGraphFixer* fixer = new MemoryGraphFixer(alias, include_lsm, phase);
- memory_graph_fixers.push(fixer);
- return fixer;
-}
-
-void ShenandoahWriteBarrierNode::try_move_before_loop_helper(LoopNode* cl, Node* val_ctrl, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses) {
- assert(cl->is_Loop(), "bad control");
- Node* ctrl = move_above_predicates(cl, val_ctrl, phase);
- Node* mem_ctrl = NULL;
- int alias = phase->C->get_alias_index(adr_type());
-
- MemoryGraphFixer* fixer = find_fixer(memory_graph_fixers, alias);
- if (fixer == NULL) {
- fixer = create_fixer(memory_graph_fixers, alias, phase, include_lsm);
- }
-
- Node* proj = find_out_with(Op_ShenandoahWBMemProj);
-
- fixer->remove(proj);
- Node* mem = fixer->find_mem(ctrl, NULL);
-
- assert(!ShenandoahVerifyOptoBarriers || memory_dominates_all_paths(mem, ctrl, alias, phase), "can't fix the memory graph");
-
- phase->set_ctrl_and_loop(this, ctrl);
- phase->igvn().replace_input_of(this, Control, ctrl);
-
- disconnect_barrier_mem(this, phase->igvn());
-
- phase->igvn().replace_input_of(this, Memory, mem);
- phase->set_ctrl_and_loop(proj, ctrl);
-
- fixer->fix_mem(ctrl, ctrl, mem, mem, proj, uses);
- assert(proj->outcnt() > 0, "disconnected write barrier");
-}
-
-LoopNode* ShenandoahWriteBarrierNode::try_move_before_pre_loop(Node* c, Node* val_ctrl, PhaseIdealLoop* phase) {
- // A write barrier between a pre and main loop can get in the way of
- // vectorization. Move it above the pre loop if possible
- CountedLoopNode* cl = NULL;
- if (c->is_IfFalse() &&
- c->in(0)->is_CountedLoopEnd()) {
- cl = c->in(0)->as_CountedLoopEnd()->loopnode();
- } else if (c->is_IfProj() &&
- c->in(0)->is_If() &&
- c->in(0)->in(0)->is_IfFalse() &&
- c->in(0)->in(0)->in(0)->is_CountedLoopEnd()) {
- cl = c->in(0)->in(0)->in(0)->as_CountedLoopEnd()->loopnode();
- }
- if (cl != NULL &&
- cl->is_pre_loop() &&
- val_ctrl != cl &&
- phase->is_dominator(val_ctrl, cl)) {
- return cl;
- }
- return NULL;
-}
-
-void ShenandoahWriteBarrierNode::try_move_before_loop(GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses) {
- Node *n_ctrl = phase->get_ctrl(this);
- IdealLoopTree *n_loop = phase->get_loop(n_ctrl);
- Node* val = in(ValueIn);
- Node* val_ctrl = phase->get_ctrl(val);
- if (n_loop != phase->ltree_root() && !n_loop->_irreducible) {
- IdealLoopTree *val_loop = phase->get_loop(val_ctrl);
- Node* mem = in(Memory);
- IdealLoopTree *mem_loop = phase->get_loop(phase->get_ctrl(mem));
- if (!n_loop->is_member(val_loop) &&
- n_loop->is_member(mem_loop)) {
- Node* n_loop_head = n_loop->_head;
-
- if (n_loop_head->is_Loop()) {
- LoopNode* loop = n_loop_head->as_Loop();
- if (n_loop_head->is_CountedLoop() && n_loop_head->as_CountedLoop()->is_main_loop()) {
- LoopNode* res = try_move_before_pre_loop(n_loop_head->in(LoopNode::EntryControl), val_ctrl, phase);
- if (res != NULL) {
- loop = res;
- }
- }
-
- try_move_before_loop_helper(loop, val_ctrl, memory_graph_fixers, phase, include_lsm, uses);
- }
- }
- }
- LoopNode* ctrl = try_move_before_pre_loop(in(0), val_ctrl, phase);
- if (ctrl != NULL) {
- try_move_before_loop_helper(ctrl, val_ctrl, memory_graph_fixers, phase, include_lsm, uses);
- }
-}
-
-Node* ShenandoahWriteBarrierNode::would_subsume(ShenandoahBarrierNode* other, PhaseIdealLoop* phase) {
- Node* val = in(ValueIn);
- Node* val_ctrl = phase->get_ctrl(val);
- Node* other_mem = other->in(Memory);
- Node* other_ctrl = phase->get_ctrl(other);
- Node* this_ctrl = phase->get_ctrl(this);
- IdealLoopTree* this_loop = phase->get_loop(this_ctrl);
- IdealLoopTree* other_loop = phase->get_loop(other_ctrl);
-
- Node* ctrl = phase->dom_lca(other_ctrl, this_ctrl);
-
- if (ctrl->is_Proj() &&
- ctrl->in(0)->is_Call() &&
- ctrl->unique_ctrl_out() != NULL &&
- ctrl->unique_ctrl_out()->Opcode() == Op_Catch &&
- !phase->is_dominator(val_ctrl, ctrl->in(0)->in(0))) {
- return NULL;
- }
-
- IdealLoopTree* loop = phase->get_loop(ctrl);
-
- // We don't want to move a write barrier in a loop
- // If the LCA is in a inner loop, try a control out of loop if possible
- while (!loop->is_member(this_loop) && (other->Opcode() != Op_ShenandoahWriteBarrier || !loop->is_member(other_loop))) {
- ctrl = phase->idom(ctrl);
- if (ctrl->is_MultiBranch()) {
- ctrl = ctrl->in(0);
- }
- if (ctrl != val_ctrl && phase->is_dominator(ctrl, val_ctrl)) {
- return NULL;
- }
- loop = phase->get_loop(ctrl);
- }
-
- if (ShenandoahDontIncreaseWBFreq) {
- Node* this_iffproj = no_branches(this_ctrl, ctrl, true, phase);
- if (other->Opcode() == Op_ShenandoahWriteBarrier) {
- Node* other_iffproj = no_branches(other_ctrl, ctrl, true, phase);
- if (other_iffproj == NULL || this_iffproj == NULL) {
- return ctrl;
- } else if (other_iffproj != NodeSentinel && this_iffproj != NodeSentinel &&
- other_iffproj->in(0) == this_iffproj->in(0)) {
- return ctrl;
- }
- } else if (this_iffproj == NULL) {
- return ctrl;
- }
- return NULL;
- }
-
- return ctrl;
-}
-
-void ShenandoahWriteBarrierNode::optimize_before_expansion(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*> memory_graph_fixers, bool include_lsm) {
- bool progress = false;
- Unique_Node_List uses;
- do {
- progress = false;
- for (int i = 0; i < ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count(); i++) {
- ShenandoahWriteBarrierNode* wb = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barrier(i);
-
- wb->try_move_before_loop(memory_graph_fixers, phase, include_lsm, uses);
-
- Node* val = wb->in(ValueIn);
-
- for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) {
- Node* u = val->fast_out(j);
- if (u != wb && u->is_ShenandoahBarrier()) {
- Node* rep_ctrl = wb->would_subsume(u->as_ShenandoahBarrier(), phase);
-
- if (rep_ctrl != NULL) {
- Node* other = u;
- Node* val_ctrl = phase->get_ctrl(val);
- if (rep_ctrl->is_Proj() &&
- rep_ctrl->in(0)->is_Call() &&
- rep_ctrl->unique_ctrl_out() != NULL &&
- rep_ctrl->unique_ctrl_out()->Opcode() == Op_Catch) {
- rep_ctrl = rep_ctrl->in(0)->in(0);
-
- assert(phase->is_dominator(val_ctrl, rep_ctrl), "bad control");
- } else {
- LoopNode* c = ShenandoahWriteBarrierNode::try_move_before_pre_loop(rep_ctrl, val_ctrl, phase);
- if (c != NULL) {
- rep_ctrl = ShenandoahWriteBarrierNode::move_above_predicates(c, val_ctrl, phase);
- } else {
- while (rep_ctrl->is_IfProj()) {
- CallStaticJavaNode* unc = rep_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
- if (unc != NULL) {
- int req = unc->uncommon_trap_request();
- Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
- if ((trap_reason == Deoptimization::Reason_loop_limit_check ||
- trap_reason == Deoptimization::Reason_predicate ||
- trap_reason == Deoptimization::Reason_profile_predicate) &&
- phase->is_dominator(val_ctrl, rep_ctrl->in(0)->in(0))) {
- rep_ctrl = rep_ctrl->in(0)->in(0);
- continue;
- }
- }
- break;
- }
- }
- }
-
- Node* wb_ctrl = phase->get_ctrl(wb);
- Node* other_ctrl = phase->get_ctrl(other);
- int alias = phase->C->get_alias_index(wb->adr_type());
- MemoryGraphFixer* fixer = find_fixer(memory_graph_fixers, alias);;
- if (!is_dominator(wb_ctrl, other_ctrl, wb, other, phase)) {
- if (fixer == NULL) {
- fixer = create_fixer(memory_graph_fixers, alias, phase, include_lsm);
- }
- Node* mem = fixer->find_mem(rep_ctrl, phase->get_ctrl(other) == rep_ctrl ? other : NULL);
-
- if (mem->has_out_with(Op_Lock) || mem->has_out_with(Op_Unlock)) {
- continue;
- }
-
- Node* wb_proj = wb->find_out_with(Op_ShenandoahWBMemProj);
- fixer->remove(wb_proj);
- Node* mem_for_ctrl = fixer->find_mem(rep_ctrl, NULL);
-
- if (wb->in(Memory) != mem) {
- disconnect_barrier_mem(wb, phase->igvn());
- phase->igvn().replace_input_of(wb, Memory, mem);
- }
- if (rep_ctrl != wb_ctrl) {
- phase->set_ctrl_and_loop(wb, rep_ctrl);
- phase->igvn().replace_input_of(wb, Control, rep_ctrl);
- phase->set_ctrl_and_loop(wb_proj, rep_ctrl);
- progress = true;
- }
-
- fixer->fix_mem(rep_ctrl, rep_ctrl, mem, mem_for_ctrl, wb_proj, uses);
-
- assert(!ShenandoahVerifyOptoBarriers || ShenandoahWriteBarrierNode::memory_dominates_all_paths(mem, rep_ctrl, alias, phase), "can't fix the memory graph");
- }
-
- if (other->Opcode() == Op_ShenandoahWriteBarrier) {
- Node* other_proj = other->find_out_with(Op_ShenandoahWBMemProj);
- if (fixer != NULL) {
- fixer->remove(other_proj);
- }
- phase->igvn().replace_node(other_proj, other->in(Memory));
- }
- phase->igvn().replace_node(other, wb);
- --j; --jmax;
- }
- }
- }
- }
- } while(progress);
-}
-
-// Some code duplication with PhaseIdealLoop::split_if_with_blocks_pre()
-Node* ShenandoahWriteBarrierNode::try_split_thru_phi(PhaseIdealLoop* phase) {
- Node *ctrl = phase->get_ctrl(this);
- if (ctrl == NULL) {
- return this;
- }
- Node *blk = phase->has_local_phi_input(this);
- if (blk == NULL) {
- return this;
- }
-
- if (in(0) != blk) {
- return this;
- }
-
- int policy = blk->req() >> 2;
-
- if (blk->is_CountedLoop()) {
- IdealLoopTree *lp = phase->get_loop(blk);
- if (lp && lp->_rce_candidate) {
- return this;
- }
- }
-
- if (phase->C->live_nodes() > 35000) {
- return this;
- }
-
- uint unique = phase->C->unique();
- Node *phi = phase->split_thru_phi(this, blk, policy);
- if (phi == NULL) {
- return this;
- }
-
- Node* mem_phi = new PhiNode(blk, Type::MEMORY, phase->C->alias_type(adr_type())->adr_type());
- for (uint i = 1; i < blk->req(); i++) {
- Node* n = phi->in(i);
- if (n->Opcode() == Op_ShenandoahWriteBarrier &&
- n->_idx >= unique) {
- Node* proj = new ShenandoahWBMemProjNode(n);
- phase->register_new_node(proj, phase->get_ctrl(n));
- mem_phi->init_req(i, proj);
- } else {
- Node* mem = in(ShenandoahBarrierNode::Memory);
- if (mem->is_Phi() && mem->in(0) == blk) {
- mem = mem->in(i);
- }
- mem_phi->init_req(i, mem);
- }
- }
- phase->register_new_node(mem_phi, blk);
-
-
- Node* proj = find_out_with(Op_ShenandoahWBMemProj);
- phase->igvn().replace_node(proj, mem_phi);
- phase->igvn().replace_node(this, phi);
-
- return phi;
-}
-
-void ShenandoahReadBarrierNode::try_move(PhaseIdealLoop* phase) {
- Node *n_ctrl = phase->get_ctrl(this);
- if (n_ctrl == NULL) {
- return;
- }
- Node* mem = in(MemNode::Memory);
- int alias = phase->C->get_alias_index(adr_type());
- const bool trace = false;
-
-#ifdef ASSERT
- if (trace) { tty->print("Trying to move mem of"); dump(); }
-#endif
-
- Node* new_mem = mem;
-
- ResourceMark rm;
- VectorSet seen(Thread::current()->resource_area());
- Node_List phis;
-
- for (;;) {
-#ifdef ASSERT
- if (trace) { tty->print("Looking for dominator from"); mem->dump(); }
-#endif
- if (mem->is_Proj() && mem->in(0)->is_Start()) {
- if (new_mem != in(MemNode::Memory)) {
-#ifdef ASSERT
- if (trace) { tty->print("XXX Setting mem to"); new_mem->dump(); tty->print(" for "); dump(); }
-#endif
- phase->igvn().replace_input_of(this, MemNode::Memory, new_mem);
- }
- return;
- }
-
- Node* candidate = mem;
- do {
- if (!is_independent(mem)) {
- if (trace) { tty->print_cr("Not independent"); }
- if (new_mem != in(MemNode::Memory)) {
-#ifdef ASSERT
- if (trace) { tty->print("XXX Setting mem to"); new_mem->dump(); tty->print(" for "); dump(); }
-#endif
- phase->igvn().replace_input_of(this, MemNode::Memory, new_mem);
- }
- return;
- }
- if (seen.test_set(mem->_idx)) {
- if (trace) { tty->print_cr("Already seen"); }
- ShouldNotReachHere();
- // Strange graph
- if (new_mem != in(MemNode::Memory)) {
-#ifdef ASSERT
- if (trace) { tty->print("XXX Setting mem to"); new_mem->dump(); tty->print(" for "); dump(); }
-#endif
- phase->igvn().replace_input_of(this, MemNode::Memory, new_mem);
- }
- return;
- }
- if (mem->is_Phi()) {
- phis.push(mem);
- }
- mem = next_mem(mem, alias);
- if (mem->bottom_type() == Type::MEMORY) {
- candidate = mem;
- }
- assert(is_dominator(phase->ctrl_or_self(mem), n_ctrl, mem, this, phase) == phase->is_dominator(phase->ctrl_or_self(mem), n_ctrl), "strange dominator");
-#ifdef ASSERT
- if (trace) { tty->print("Next mem is"); mem->dump(); }
-#endif
- } while (mem->bottom_type() != Type::MEMORY || !phase->is_dominator(phase->ctrl_or_self(mem), n_ctrl));
-
- assert(mem->bottom_type() == Type::MEMORY, "bad mem");
-
- bool not_dom = false;
- for (uint i = 0; i < phis.size() && !not_dom; i++) {
- Node* nn = phis.at(i);
-
-#ifdef ASSERT
- if (trace) { tty->print("Looking from phi"); nn->dump(); }
-#endif
- assert(nn->is_Phi(), "phis only");
- for (uint j = 2; j < nn->req() && !not_dom; j++) {
- Node* m = nn->in(j);
-#ifdef ASSERT
- if (trace) { tty->print("Input %d is", j); m->dump(); }
-#endif
- while (m != mem && !seen.test_set(m->_idx)) {
- if (is_dominator(phase->ctrl_or_self(m), phase->ctrl_or_self(mem), m, mem, phase)) {
- not_dom = true;
- // Scheduling anomaly
-#ifdef ASSERT
- if (trace) { tty->print("Giving up"); m->dump(); }
-#endif
- break;
- }
- if (!is_independent(m)) {
- if (trace) { tty->print_cr("Not independent"); }
- if (new_mem != in(MemNode::Memory)) {
-#ifdef ASSERT
- if (trace) { tty->print("XXX Setting mem to"); new_mem->dump(); tty->print(" for "); dump(); }
-#endif
- phase->igvn().replace_input_of(this, MemNode::Memory, new_mem);
- }
- return;
- }
- if (m->is_Phi()) {
- phis.push(m);
- }
- m = next_mem(m, alias);
-#ifdef ASSERT
- if (trace) { tty->print("Next mem is"); m->dump(); }
-#endif
- }
- }
- }
- if (!not_dom) {
- new_mem = mem;
- phis.clear();
- } else {
- seen.Clear();
- }
- }
-}
-
-CallStaticJavaNode* ShenandoahWriteBarrierNode::pin_and_expand_null_check(PhaseIterGVN& igvn) {
- Node* val = in(ValueIn);
-
- const Type* val_t = igvn.type(val);
-
- if (val_t->meet(TypePtr::NULL_PTR) != val_t &&
- val->Opcode() == Op_CastPP &&
- val->in(0) != NULL &&
- val->in(0)->Opcode() == Op_IfTrue &&
- val->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&
- val->in(0)->in(0)->is_If() &&
- val->in(0)->in(0)->in(1)->Opcode() == Op_Bool &&
- val->in(0)->in(0)->in(1)->as_Bool()->_test._test == BoolTest::ne &&
- val->in(0)->in(0)->in(1)->in(1)->Opcode() == Op_CmpP &&
- val->in(0)->in(0)->in(1)->in(1)->in(1) == val->in(1) &&
- val->in(0)->in(0)->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) {
- assert(val->in(0)->in(0)->in(1)->in(1)->in(1) == val->in(1), "");
- CallStaticJavaNode* unc = val->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
- return unc;
- }
- return NULL;
-}
-
-void ShenandoahWriteBarrierNode::pin_and_expand_move_barrier(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, Unique_Node_List& uses) {
- Node* unc = pin_and_expand_null_check(phase->igvn());
- Node* val = in(ValueIn);
-
- if (unc != NULL) {
- Node* ctrl = phase->get_ctrl(this);
- Node* unc_ctrl = val->in(0);
-
- // Don't move write barrier in a loop
- IdealLoopTree* loop = phase->get_loop(ctrl);
- IdealLoopTree* unc_loop = phase->get_loop(unc_ctrl);
-
- if (!unc_loop->is_member(loop)) {
- return;
- }
-
- Node* branch = no_branches(ctrl, unc_ctrl, false, phase);
- assert(branch == NULL || branch == NodeSentinel, "was not looking for a branch");
- if (branch == NodeSentinel) {
- return;
- }
-
- RegionNode* r = new RegionNode(3);
- IfNode* iff = unc_ctrl->in(0)->as_If();
-
- Node* ctrl_use = unc_ctrl->unique_ctrl_out();
- Node* unc_ctrl_clone = unc_ctrl->clone();
- phase->register_control(unc_ctrl_clone, loop, iff);
- Node* c = unc_ctrl_clone;
- Node* new_cast = clone_null_check(c, val, unc_ctrl_clone, phase);
- r->init_req(1, new_cast->in(0)->in(0)->as_If()->proj_out(0));
-
- phase->igvn().replace_input_of(unc_ctrl, 0, c->in(0));
- phase->set_idom(unc_ctrl, c->in(0), phase->dom_depth(unc_ctrl));
- phase->lazy_replace(c, unc_ctrl);
- c = NULL;;
- phase->igvn().replace_input_of(val, 0, unc_ctrl_clone);
- phase->set_ctrl(val, unc_ctrl_clone);
-
- IfNode* new_iff = new_cast->in(0)->in(0)->as_If();
- fix_null_check(unc, unc_ctrl_clone, r, uses, phase);
- Node* iff_proj = iff->proj_out(0);
- r->init_req(2, iff_proj);
- phase->register_control(r, phase->ltree_root(), iff);
-
- Node* new_bol = new_iff->in(1)->clone();
- Node* new_cmp = new_bol->in(1)->clone();
- assert(new_cmp->Opcode() == Op_CmpP, "broken");
- assert(new_cmp->in(1) == val->in(1), "broken");
- new_bol->set_req(1, new_cmp);
- new_cmp->set_req(1, this);
- phase->register_new_node(new_bol, new_iff->in(0));
- phase->register_new_node(new_cmp, new_iff->in(0));
- phase->igvn().replace_input_of(new_iff, 1, new_bol);
- phase->igvn().replace_input_of(new_cast, 1, this);
-
- for (DUIterator_Fast imax, i = this->fast_outs(imax); i < imax; i++) {
- Node* u = this->fast_out(i);
- if (u == new_cast || u->Opcode() == Op_ShenandoahWBMemProj || u == new_cmp) {
- continue;
- }
- phase->igvn().rehash_node_delayed(u);
- int nb = u->replace_edge(this, new_cast);
- assert(nb > 0, "no update?");
- --i; imax -= nb;
- }
-
- for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
- Node* u = val->fast_out(i);
- if (u == this) {
- continue;
- }
- phase->igvn().rehash_node_delayed(u);
- int nb = u->replace_edge(val, new_cast);
- assert(nb > 0, "no update?");
- --i; imax -= nb;
- }
-
- Node* new_ctrl = unc_ctrl_clone;
-
- int alias = phase->C->get_alias_index(adr_type());
- MemoryGraphFixer* fixer = find_fixer(memory_graph_fixers, alias);
- if (fixer == NULL) {
- fixer = create_fixer(memory_graph_fixers, alias, phase, true);
- }
-
- Node* proj = find_out_with(Op_ShenandoahWBMemProj);
- fixer->remove(proj);
- Node* mem = fixer->find_mem(new_ctrl, NULL);
-
- if (in(Memory) != mem) {
- disconnect_barrier_mem(this, phase->igvn());
- phase->igvn().replace_input_of(this, Memory, mem);
- }
-
- phase->set_ctrl_and_loop(this, new_ctrl);
- phase->igvn().replace_input_of(this, Control, new_ctrl);
- phase->set_ctrl_and_loop(proj, new_ctrl);
-
- fixer->fix_mem(new_ctrl, new_ctrl, mem, mem, proj, uses);
- }
-}
-
-void ShenandoahWriteBarrierNode::pin_and_expand_helper(PhaseIdealLoop* phase) {
- Node* val = in(ValueIn);
- CallStaticJavaNode* unc = pin_and_expand_null_check(phase->igvn());
- Node* rep = this;
- Node* ctrl = phase->get_ctrl(this);
- if (unc != NULL && val->in(0) == ctrl) {
- Node* unc_ctrl = val->in(0);
- IfNode* other_iff = unc_ctrl->unique_ctrl_out()->as_If();
- ProjNode* other_unc_ctrl = other_iff->proj_out(1);
- Node* cast = NULL;
- for (DUIterator_Fast imax, i = other_unc_ctrl->fast_outs(imax); i < imax && cast == NULL; i++) {
- Node* u = other_unc_ctrl->fast_out(i);
- if (u->Opcode() == Op_CastPP && u->in(1) == this) {
- cast = u;
- }
- }
- assert(other_unc_ctrl->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) == unc, "broken");
- rep = cast;
- }
-
- // Replace all uses of barrier's input that are dominated by ctrl
- // with the value returned by the barrier: no need to keep both
- // live.
- for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
- Node* u = val->fast_out(i);
- if (u != this) {
- if (u->is_Phi()) {
- int nb = 0;
- for (uint j = 1; j < u->req(); j++) {
- if (u->in(j) == val) {
- Node* c = u->in(0)->in(j);
- if (phase->is_dominator(ctrl, c)) {
- phase->igvn().replace_input_of(u, j, rep);
- nb++;
- }
- }
- }
- if (nb > 0) {
- imax -= nb;
- --i;
- }
- } else {
- Node* c = phase->ctrl_or_self(u);
- if (is_dominator(ctrl, c, this, u, phase)) {
- phase->igvn().rehash_node_delayed(u);
- int nb = u->replace_edge(val, rep);
- assert(nb > 0, "no update?");
- --i, imax -= nb;
- }
- }
- }
- }
-}
-
-Node* ShenandoahWriteBarrierNode::find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase) {
+Node* ShenandoahBarrierC2Support::find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase) {
Node* mem = NULL;
Node* c = ctrl;
do {
@@ -2355,7 +914,7 @@
return mem;
}
-void ShenandoahWriteBarrierNode::follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* u = n->fast_out(i);
if (!u->is_CFG() && phase->get_ctrl(u) == ctrl && (!u->is_Phi() || !u->in(0)->is_Loop() || u->in(LoopNode::LoopBackControl) != n)) {
@@ -2375,7 +934,7 @@
inner->clear_strip_mined();
}
-void ShenandoahWriteBarrierNode::test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
+void ShenandoahBarrierC2Support::test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
PhaseIdealLoop* phase) {
IdealLoopTree* loop = phase->get_loop(ctrl);
Node* thread = new ThreadLocalNode();
@@ -2407,7 +966,7 @@
assert(is_heap_stable_test(heap_stable_iff), "Should match the shape");
}
-void ShenandoahWriteBarrierNode::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) {
const Type* val_t = phase->igvn().type(val);
if (val_t->meet(TypePtr::NULL_PTR) == val_t) {
IdealLoopTree* loop = phase->get_loop(ctrl);
@@ -2424,7 +983,7 @@
}
}
-Node* ShenandoahWriteBarrierNode::clone_null_check(Node*& c, Node* val, Node* unc_ctrl, PhaseIdealLoop* phase) {
+Node* ShenandoahBarrierC2Support::clone_null_check(Node*& c, Node* val, Node* unc_ctrl, PhaseIdealLoop* phase) {
IdealLoopTree *loop = phase->get_loop(c);
Node* iff = unc_ctrl->in(0);
assert(iff->is_If(), "broken");
@@ -2445,7 +1004,7 @@
return val;
}
-void ShenandoahWriteBarrierNode::fix_null_check(Node* unc, Node* unc_ctrl, Node* new_unc_ctrl,
+void ShenandoahBarrierC2Support::fix_null_check(Node* unc, Node* unc_ctrl, Node* new_unc_ctrl,
Unique_Node_List& uses, PhaseIdealLoop* phase) {
IfNode* iff = unc_ctrl->in(0)->as_If();
Node* proj = iff->proj_out(0);
@@ -2494,7 +1053,7 @@
assert(nb == 1, "only use expected");
}
-void ShenandoahWriteBarrierNode::in_cset_fast_test(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::in_cset_fast_test(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase) {
IdealLoopTree *loop = phase->get_loop(ctrl);
Node* raw_rbtrue = new CastP2XNode(ctrl, val);
phase->register_new_node(raw_rbtrue, ctrl);
@@ -2523,23 +1082,18 @@
phase->register_control(ctrl, loop, in_cset_fast_test_iff);
}
-void ShenandoahWriteBarrierNode::call_wb_stub(Node*& ctrl, Node*& val, Node*& result_mem,
- Node* raw_mem, Node* wb_mem,
- int alias,
- PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node*& result_mem, Node* raw_mem, PhaseIdealLoop* phase) {
IdealLoopTree*loop = phase->get_loop(ctrl);
const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr()->cast_to_nonconst();
// The slow path stub consumes and produces raw memory in addition
// to the existing memory edges
Node* base = find_bottom_mem(ctrl, phase);
-
MergeMemNode* mm = MergeMemNode::make(base);
- mm->set_memory_at(alias, wb_mem);
mm->set_memory_at(Compile::AliasIdxRaw, raw_mem);
phase->register_new_node(mm, ctrl);
- Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_write_barrier_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT), "shenandoah_write_barrier", TypeRawPtr::BOTTOM);
+ Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_write_barrier_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_JRT), "shenandoah_write_barrier", TypeRawPtr::BOTTOM);
call->init_req(TypeFunc::Control, ctrl);
call->init_req(TypeFunc::I_O, phase->C->top());
call->init_req(TypeFunc::Memory, mm);
@@ -2557,7 +1111,7 @@
phase->register_new_node(val, ctrl);
}
-void ShenandoahWriteBarrierNode::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) {
Node* ctrl = phase->get_ctrl(barrier);
Node* init_raw_mem = fixer.find_mem(ctrl, barrier);
@@ -2610,26 +1164,32 @@
}
}
-void ShenandoahWriteBarrierNode::pin_and_expand(PhaseIdealLoop* phase) {
- Node_List enqueue_barriers;
- if (ShenandoahStoreValEnqueueBarrier) {
- Unique_Node_List wq;
- wq.push(phase->C->root());
- for (uint i = 0; i < wq.size(); i++) {
- Node* n = wq.at(i);
- if (n->Opcode() == Op_ShenandoahEnqueueBarrier) {
- enqueue_barriers.push(n);
- }
- for (uint i = 0; i < n->req(); i++) {
- Node* in = n->in(i);
- if (in != NULL) {
- wq.push(in);
- }
- }
+static Node* create_phis_on_call_return(Node* ctrl, Node* c, Node* n, Node* n_clone, const CallProjections& projs, PhaseIdealLoop* phase) {
+ Node* region = NULL;
+ while (c != ctrl) {
+ if (c->is_Region()) {
+ region = c;
+ }
+ c = phase->idom(c);
+ }
+ assert(region != NULL, "");
+ Node* phi = new PhiNode(region, n->bottom_type());
+ for (uint j = 1; j < region->req(); j++) {
+ Node* in = region->in(j);
+ if (phase->is_dominator(projs.fallthrough_catchproj, in)) {
+ phi->init_req(j, n);
+ } else if (phase->is_dominator(projs.catchall_catchproj, in)) {
+ phi->init_req(j, n_clone);
+ } else {
+ phi->init_req(j, create_phis_on_call_return(ctrl, in, n, n_clone, projs, phase));
}
}
+ phase->register_new_node(phi, region);
+ return phi;
+}
- const bool trace = false;
+void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
+ ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state();
// Collect raw memory state at CFG points in the entire graph and
// record it in memory_nodes. Optimize the raw memory graph in the
@@ -2637,34 +1197,9 @@
// simpler.
GrowableArray<MemoryGraphFixer*> memory_graph_fixers;
- // Let's try to common write barriers again
- optimize_before_expansion(phase, memory_graph_fixers, true);
-
Unique_Node_List uses;
- for (int i = 0; i < ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count(); i++) {
- ShenandoahWriteBarrierNode* wb = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barrier(i);
- Node* ctrl = phase->get_ctrl(wb);
-
- Node* val = wb->in(ValueIn);
- if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) {
- assert(is_dominator(phase->get_ctrl(val), ctrl->in(0)->in(0), val, ctrl->in(0), phase), "can't move");
- phase->set_ctrl(wb, ctrl->in(0)->in(0));
- } else if (ctrl->is_CallRuntime()) {
- assert(is_dominator(phase->get_ctrl(val), ctrl->in(0), val, ctrl, phase), "can't move");
- phase->set_ctrl(wb, ctrl->in(0));
- }
-
- assert(wb->Opcode() == Op_ShenandoahWriteBarrier, "only for write barriers");
- // Look for a null check that dominates this barrier and move the
- // barrier right after the null check to enable implicit null
- // checks
- wb->pin_and_expand_move_barrier(phase, memory_graph_fixers, uses);
-
- wb->pin_and_expand_helper(phase);
- }
-
- for (uint i = 0; i < enqueue_barriers.size(); i++) {
- Node* barrier = enqueue_barriers.at(i);
+ for (int i = 0; i < state->enqueue_barriers_count(); i++) {
+ Node* barrier = state->enqueue_barrier(i);
Node* ctrl = phase->get_ctrl(barrier);
IdealLoopTree* loop = phase->get_loop(ctrl);
if (loop->_head->is_OuterStripMinedLoop()) {
@@ -2676,24 +1211,386 @@
}
}
- for (int i = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count(); i > 0; i--) {
- int cnt = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count();
- ShenandoahWriteBarrierNode* wb = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barrier(i-1);
- Node* ctrl = phase->get_ctrl(wb);
- IdealLoopTree* loop = phase->get_loop(ctrl);
- if (loop->_head->is_OuterStripMinedLoop()) {
- // Expanding a barrier here will break loop strip mining
- // verification. Transform the loop so the loop nest doesn't
- // appear as strip mined.
- OuterStripMinedLoopNode* outer = loop->_head->as_OuterStripMinedLoop();
- hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase);
+ Node_Stack stack(0);
+ Node_List clones;
+ for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {
+ ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);
+ if (lrb->get_barrier_strength() == ShenandoahLoadReferenceBarrierNode::NONE) {
+ continue;
+ }
+
+ Node* ctrl = phase->get_ctrl(lrb);
+ Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn);
+
+ CallStaticJavaNode* unc = NULL;
+ Node* unc_ctrl = NULL;
+ Node* uncasted_val = val;
+
+ for (DUIterator_Fast imax, i = lrb->fast_outs(imax); i < imax; i++) {
+ Node* u = lrb->fast_out(i);
+ if (u->Opcode() == Op_CastPP &&
+ u->in(0) != NULL &&
+ phase->is_dominator(u->in(0), ctrl)) {
+ const Type* u_t = phase->igvn().type(u);
+
+ if (u_t->meet(TypePtr::NULL_PTR) != u_t &&
+ u->in(0)->Opcode() == Op_IfTrue &&
+ u->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&
+ u->in(0)->in(0)->is_If() &&
+ u->in(0)->in(0)->in(1)->Opcode() == Op_Bool &&
+ u->in(0)->in(0)->in(1)->as_Bool()->_test._test == BoolTest::ne &&
+ u->in(0)->in(0)->in(1)->in(1)->Opcode() == Op_CmpP &&
+ u->in(0)->in(0)->in(1)->in(1)->in(1) == val &&
+ u->in(0)->in(0)->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) {
+ IdealLoopTree* loop = phase->get_loop(ctrl);
+ IdealLoopTree* unc_loop = phase->get_loop(u->in(0));
+
+ if (!unc_loop->is_member(loop)) {
+ continue;
+ }
+
+ Node* branch = no_branches(ctrl, u->in(0), false, phase);
+ assert(branch == NULL || branch == NodeSentinel, "was not looking for a branch");
+ if (branch == NodeSentinel) {
+ continue;
+ }
+
+ phase->igvn().replace_input_of(u, 1, val);
+ phase->igvn().replace_input_of(lrb, ShenandoahLoadReferenceBarrierNode::ValueIn, u);
+ phase->set_ctrl(u, u->in(0));
+ phase->set_ctrl(lrb, u->in(0));
+ unc = u->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+ unc_ctrl = u->in(0);
+ val = u;
+
+ for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) {
+ Node* u = val->fast_out(j);
+ if (u == lrb) continue;
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(val, lrb);
+ --j; jmax -= nb;
+ }
+
+ RegionNode* r = new RegionNode(3);
+ IfNode* iff = unc_ctrl->in(0)->as_If();
+
+ Node* ctrl_use = unc_ctrl->unique_ctrl_out();
+ Node* unc_ctrl_clone = unc_ctrl->clone();
+ phase->register_control(unc_ctrl_clone, loop, iff);
+ Node* c = unc_ctrl_clone;
+ Node* new_cast = clone_null_check(c, val, unc_ctrl_clone, phase);
+ r->init_req(1, new_cast->in(0)->in(0)->as_If()->proj_out(0));
+
+ phase->igvn().replace_input_of(unc_ctrl, 0, c->in(0));
+ phase->set_idom(unc_ctrl, c->in(0), phase->dom_depth(unc_ctrl));
+ phase->lazy_replace(c, unc_ctrl);
+ c = NULL;;
+ phase->igvn().replace_input_of(val, 0, unc_ctrl_clone);
+ phase->set_ctrl(val, unc_ctrl_clone);
+
+ IfNode* new_iff = new_cast->in(0)->in(0)->as_If();
+ fix_null_check(unc, unc_ctrl_clone, r, uses, phase);
+ Node* iff_proj = iff->proj_out(0);
+ r->init_req(2, iff_proj);
+ phase->register_control(r, phase->ltree_root(), iff);
+
+ Node* new_bol = new_iff->in(1)->clone();
+ Node* new_cmp = new_bol->in(1)->clone();
+ assert(new_cmp->Opcode() == Op_CmpP, "broken");
+ assert(new_cmp->in(1) == val->in(1), "broken");
+ new_bol->set_req(1, new_cmp);
+ new_cmp->set_req(1, lrb);
+ phase->register_new_node(new_bol, new_iff->in(0));
+ phase->register_new_node(new_cmp, new_iff->in(0));
+ phase->igvn().replace_input_of(new_iff, 1, new_bol);
+ phase->igvn().replace_input_of(new_cast, 1, lrb);
+
+ for (DUIterator_Fast imax, i = lrb->fast_outs(imax); i < imax; i++) {
+ Node* u = lrb->fast_out(i);
+ if (u == new_cast || u == new_cmp) {
+ continue;
+ }
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(lrb, new_cast);
+ assert(nb > 0, "no update?");
+ --i; imax -= nb;
+ }
+
+ for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
+ Node* u = val->fast_out(i);
+ if (u == lrb) {
+ continue;
+ }
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(val, new_cast);
+ assert(nb > 0, "no update?");
+ --i; imax -= nb;
+ }
+
+ ctrl = unc_ctrl_clone;
+ phase->set_ctrl_and_loop(lrb, ctrl);
+ break;
+ }
+ }
+ }
+ if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) {
+ CallNode* call = ctrl->in(0)->as_CallJava();
+ CallProjections projs;
+ call->extract_projections(&projs, false, false);
+
+ Node* lrb_clone = lrb->clone();
+ phase->register_new_node(lrb_clone, projs.catchall_catchproj);
+ phase->set_ctrl(lrb, projs.fallthrough_catchproj);
+
+ stack.push(lrb, 0);
+ clones.push(lrb_clone);
+
+ do {
+ assert(stack.size() == clones.size(), "");
+ Node* n = stack.node();
+#ifdef ASSERT
+ if (n->is_Load()) {
+ Node* mem = n->in(MemNode::Memory);
+ for (DUIterator_Fast jmax, j = mem->fast_outs(jmax); j < jmax; j++) {
+ Node* u = mem->fast_out(j);
+ assert(!u->is_Store() || !u->is_LoadStore() || phase->get_ctrl(u) != ctrl, "anti dependent store?");
+ }
+ }
+#endif
+ uint idx = stack.index();
+ Node* n_clone = clones.at(clones.size()-1);
+ if (idx < n->outcnt()) {
+ Node* u = n->raw_out(idx);
+ Node* c = phase->ctrl_or_self(u);
+ if (c == ctrl) {
+ stack.set_index(idx+1);
+ assert(!u->is_CFG(), "");
+ stack.push(u, 0);
+ Node* u_clone = u->clone();
+ int nb = u_clone->replace_edge(n, n_clone);
+ assert(nb > 0, "should have replaced some uses");
+ phase->register_new_node(u_clone, projs.catchall_catchproj);
+ clones.push(u_clone);
+ phase->set_ctrl(u, projs.fallthrough_catchproj);
+ } else {
+ bool replaced = false;
+ if (u->is_Phi()) {
+ for (uint k = 1; k < u->req(); k++) {
+ if (u->in(k) == n) {
+ if (phase->is_dominator(projs.catchall_catchproj, u->in(0)->in(k))) {
+ phase->igvn().replace_input_of(u, k, n_clone);
+ replaced = true;
+ } else if (!phase->is_dominator(projs.fallthrough_catchproj, u->in(0)->in(k))) {
+ phase->igvn().replace_input_of(u, k, create_phis_on_call_return(ctrl, u->in(0)->in(k), n, n_clone, projs, phase));
+ replaced = true;
+ }
+ }
+ }
+ } else {
+ if (phase->is_dominator(projs.catchall_catchproj, c)) {
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(n, n_clone);
+ assert(nb > 0, "should have replaced some uses");
+ replaced = true;
+ } else if (!phase->is_dominator(projs.fallthrough_catchproj, c)) {
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(n, create_phis_on_call_return(ctrl, c, n, n_clone, projs, phase));
+ assert(nb > 0, "should have replaced some uses");
+ replaced = true;
+ }
+ }
+ if (!replaced) {
+ stack.set_index(idx+1);
+ }
+ }
+ } else {
+ // assert(n_clone->outcnt() > 0, "");
+ // assert(n->outcnt() > 0, "");
+ stack.pop();
+ clones.pop();
+ }
+ } while (stack.size() > 0);
+ assert(stack.size() == 0 && clones.size() == 0, "");
+ ctrl = projs.fallthrough_catchproj;
}
}
+ // Expand load-reference-barriers
MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase);
Unique_Node_List uses_to_ignore;
- for (uint i = 0; i < enqueue_barriers.size(); i++) {
- Node* barrier = enqueue_barriers.at(i);
+ for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {
+ ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);
+ if (lrb->get_barrier_strength() == ShenandoahLoadReferenceBarrierNode::NONE) {
+ phase->igvn().replace_node(lrb, lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn));
+ continue;
+ }
+ uint last = phase->C->unique();
+ Node* ctrl = phase->get_ctrl(lrb);
+ Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn);
+
+
+ Node* orig_ctrl = ctrl;
+
+ Node* raw_mem = fixer.find_mem(ctrl, lrb);
+ Node* init_raw_mem = raw_mem;
+ Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL);
+ // int alias = phase->C->get_alias_index(lrb->adr_type());
+
+ IdealLoopTree *loop = phase->get_loop(ctrl);
+ CallStaticJavaNode* unc = lrb->pin_and_expand_null_check(phase->igvn());
+ Node* unc_ctrl = NULL;
+ if (unc != NULL) {
+ if (val->in(ShenandoahLoadReferenceBarrierNode::Control) != ctrl) {
+ unc = NULL;
+ } else {
+ unc_ctrl = val->in(ShenandoahLoadReferenceBarrierNode::Control);
+ }
+ }
+
+ Node* uncasted_val = val;
+ if (unc != NULL) {
+ uncasted_val = val->in(1);
+ }
+
+ Node* heap_stable_ctrl = NULL;
+ Node* null_ctrl = NULL;
+
+ assert(val->bottom_type()->make_oopptr(), "need oop");
+ assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant");
+
+ enum { _heap_stable = 1, _not_cset, _not_equal, _evac_path, _null_path, PATH_LIMIT };
+ Node* region = new RegionNode(PATH_LIMIT);
+ Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr());
+ Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
+
+ // Stable path.
+ test_heap_stable(ctrl, raw_mem, heap_stable_ctrl, phase);
+ IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If();
+
+ // Heap stable case
+ region->init_req(_heap_stable, heap_stable_ctrl);
+ val_phi->init_req(_heap_stable, uncasted_val);
+ raw_mem_phi->init_req(_heap_stable, raw_mem);
+
+ Node* reg2_ctrl = NULL;
+ // Null case
+ test_null(ctrl, val, null_ctrl, phase);
+ if (null_ctrl != NULL) {
+ reg2_ctrl = null_ctrl->in(0);
+ region->init_req(_null_path, null_ctrl);
+ val_phi->init_req(_null_path, uncasted_val);
+ raw_mem_phi->init_req(_null_path, raw_mem);
+ } else {
+ region->del_req(_null_path);
+ val_phi->del_req(_null_path);
+ raw_mem_phi->del_req(_null_path);
+ }
+
+ // Test for in-cset.
+ // Wires !in_cset(obj) to slot 2 of region and phis
+ Node* not_cset_ctrl = NULL;
+ in_cset_fast_test(ctrl, not_cset_ctrl, uncasted_val, raw_mem, phase);
+ if (not_cset_ctrl != NULL) {
+ if (reg2_ctrl == NULL) reg2_ctrl = not_cset_ctrl->in(0);
+ region->init_req(_not_cset, not_cset_ctrl);
+ val_phi->init_req(_not_cset, uncasted_val);
+ raw_mem_phi->init_req(_not_cset, raw_mem);
+ }
+
+ // Resolve object when orig-value is in cset.
+ // Make the unconditional resolve for fwdptr.
+ Node* new_val = uncasted_val;
+ if (unc_ctrl != NULL) {
+ // Clone the null check in this branch to allow implicit null check
+ new_val = clone_null_check(ctrl, val, unc_ctrl, phase);
+ fix_null_check(unc, unc_ctrl, ctrl->in(0)->as_If()->proj_out(0), uses, phase);
+
+ IfNode* iff = unc_ctrl->in(0)->as_If();
+ phase->igvn().replace_input_of(iff, 1, phase->igvn().intcon(1));
+ }
+ Node* addr = new AddPNode(new_val, uncasted_val, phase->igvn().MakeConX(ShenandoahBrooksPointer::byte_offset()));
+ phase->register_new_node(addr, ctrl);
+ assert(val->bottom_type()->isa_oopptr(), "what else?");
+ const TypePtr* obj_type = val->bottom_type()->is_oopptr();
+ const TypePtr* adr_type = TypeRawPtr::BOTTOM;
+ Node* fwd = new LoadPNode(ctrl, raw_mem, addr, adr_type, obj_type, MemNode::unordered);
+ phase->register_new_node(fwd, ctrl);
+
+ // Only branch to LRB stub if object is not forwarded; otherwise reply with fwd ptr
+ Node* cmp = new CmpPNode(fwd, new_val);
+ phase->register_new_node(cmp, ctrl);
+ Node* bol = new BoolNode(cmp, BoolTest::eq);
+ phase->register_new_node(bol, ctrl);
+
+ IfNode* iff = new IfNode(ctrl, bol, PROB_UNLIKELY(0.999), COUNT_UNKNOWN);
+ if (reg2_ctrl == NULL) reg2_ctrl = iff;
+ phase->register_control(iff, loop, ctrl);
+ Node* if_not_eq = new IfFalseNode(iff);
+ phase->register_control(if_not_eq, loop, iff);
+ Node* if_eq = new IfTrueNode(iff);
+ phase->register_control(if_eq, loop, iff);
+
+ // Wire up not-equal-path in slots 3.
+ region->init_req(_not_equal, if_not_eq);
+ val_phi->init_req(_not_equal, fwd);
+ raw_mem_phi->init_req(_not_equal, raw_mem);
+
+ // Call wb-stub and wire up that path in slots 4
+ Node* result_mem = NULL;
+ ctrl = if_eq;
+ call_lrb_stub(ctrl, fwd, result_mem, raw_mem, phase);
+ region->init_req(_evac_path, ctrl);
+ val_phi->init_req(_evac_path, fwd);
+ raw_mem_phi->init_req(_evac_path, result_mem);
+
+ phase->register_control(region, loop, heap_stable_iff);
+ Node* out_val = val_phi;
+ phase->register_new_node(val_phi, region);
+ phase->register_new_node(raw_mem_phi, region);
+
+ fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase);
+
+ ctrl = orig_ctrl;
+
+ if (unc != NULL) {
+ for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
+ Node* u = val->fast_out(i);
+ Node* c = phase->ctrl_or_self(u);
+ if (u != lrb && (c != ctrl || is_dominator_same_ctrl(c, lrb, u, phase))) {
+ phase->igvn().rehash_node_delayed(u);
+ int nb = u->replace_edge(val, out_val);
+ --i, imax -= nb;
+ }
+ }
+ if (val->outcnt() == 0) {
+ phase->igvn()._worklist.push(val);
+ }
+ }
+ phase->igvn().replace_node(lrb, out_val);
+
+ follow_barrier_uses(out_val, ctrl, uses, phase);
+
+ for(uint next = 0; next < uses.size(); next++ ) {
+ Node *n = uses.at(next);
+ assert(phase->get_ctrl(n) == ctrl, "bad control");
+ assert(n != init_raw_mem, "should leave input raw mem above the barrier");
+ phase->set_ctrl(n, region);
+ follow_barrier_uses(n, ctrl, uses, phase);
+ }
+
+ // The slow path call produces memory: hook the raw memory phi
+ // from the expanded load reference barrier with the rest of the graph
+ // which may require adding memory phis at every post dominated
+ // region and at enclosing loop heads. Use the memory state
+ // collected in memory_nodes to fix the memory graph. Update that
+ // memory state as we go.
+ fixer.fix_mem(ctrl, region, init_raw_mem, raw_mem_for_ctrl, raw_mem_phi, uses);
+ }
+ // Done expanding load-reference-barriers.
+ assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced");
+
+ for (int i = state->enqueue_barriers_count() - 1; i >= 0; i--) {
+ Node* barrier = state->enqueue_barrier(i);
Node* pre_val = barrier->in(1);
if (phase->igvn().type(pre_val)->higher_equal(TypePtr::NULL_PTR)) {
@@ -2840,212 +1737,11 @@
phase->igvn().replace_node(barrier, pre_val);
}
-
- for (int i = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count(); i > 0; i--) {
- int cnt = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count();
- ShenandoahWriteBarrierNode* wb = ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barrier(i-1);
-
- uint last = phase->C->unique();
- Node* ctrl = phase->get_ctrl(wb);
- Node* orig_ctrl = ctrl;
-
- Node* raw_mem = fixer.find_mem(ctrl, wb);
- Node* init_raw_mem = raw_mem;
- Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL);
- int alias = phase->C->get_alias_index(wb->adr_type());
- Node* wb_mem = wb->in(Memory);
- Node* init_wb_mem = wb_mem;
-
- Node* val = wb->in(ValueIn);
- Node* wbproj = wb->find_out_with(Op_ShenandoahWBMemProj);
- IdealLoopTree *loop = phase->get_loop(ctrl);
-
- assert(val->Opcode() != Op_ShenandoahWriteBarrier, "No chain of write barriers");
-
- CallStaticJavaNode* unc = wb->pin_and_expand_null_check(phase->igvn());
- Node* unc_ctrl = NULL;
- if (unc != NULL) {
- if (val->in(0) != ctrl) {
- unc = NULL;
- } else {
- unc_ctrl = val->in(0);
- }
- }
-
- Node* uncasted_val = val;
- if (unc != NULL) {
- uncasted_val = val->in(1);
- }
-
- Node* heap_stable_ctrl = NULL;
- Node* null_ctrl = NULL;
-
- assert(val->bottom_type()->make_oopptr(), "need oop");
- assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant");
-
- enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT };
- Node* region = new RegionNode(PATH_LIMIT);
- Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr());
- Node* mem_phi = PhiNode::make(region, wb_mem, Type::MEMORY, phase->C->alias_type(wb->adr_type())->adr_type());
- Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
-
- enum { _not_cset = 1, _not_equal, _evac_path, _null_path, PATH_LIMIT2 };
- Node* region2 = new RegionNode(PATH_LIMIT2);
- Node* val_phi2 = new PhiNode(region2, uncasted_val->bottom_type()->is_oopptr());
- Node* mem_phi2 = PhiNode::make(region2, wb_mem, Type::MEMORY, phase->C->alias_type(wb->adr_type())->adr_type());
- Node* raw_mem_phi2 = PhiNode::make(region2, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
-
- // Stable path.
- test_heap_stable(ctrl, raw_mem, heap_stable_ctrl, phase);
- IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If();
-
- // Heap stable case
- region->init_req(_heap_stable, heap_stable_ctrl);
- val_phi->init_req(_heap_stable, uncasted_val);
- mem_phi->init_req(_heap_stable, wb_mem);
- raw_mem_phi->init_req(_heap_stable, raw_mem);
-
- Node* reg2_ctrl = NULL;
- // Null case
- test_null(ctrl, val, null_ctrl, phase);
- if (null_ctrl != NULL) {
- reg2_ctrl = null_ctrl->in(0);
- region2->init_req(_null_path, null_ctrl);
- val_phi2->init_req(_null_path, uncasted_val);
- mem_phi2->init_req(_null_path, wb_mem);
- raw_mem_phi2->init_req(_null_path, raw_mem);
- } else {
- region2->del_req(_null_path);
- val_phi2->del_req(_null_path);
- mem_phi2->del_req(_null_path);
- raw_mem_phi2->del_req(_null_path);
- }
-
- // Test for in-cset.
- // Wires !in_cset(obj) to slot 2 of region and phis
- Node* not_cset_ctrl = NULL;
- in_cset_fast_test(ctrl, not_cset_ctrl, uncasted_val, raw_mem, phase);
- if (not_cset_ctrl != NULL) {
- if (reg2_ctrl == NULL) reg2_ctrl = not_cset_ctrl->in(0);
- region2->init_req(_not_cset, not_cset_ctrl);
- val_phi2->init_req(_not_cset, uncasted_val);
- mem_phi2->init_req(_not_cset, wb_mem);
- raw_mem_phi2->init_req(_not_cset, raw_mem);
- }
-
- // Resolve object when orig-value is in cset.
- // Make the unconditional resolve for fwdptr, not the read barrier.
- Node* new_val = uncasted_val;
- if (unc_ctrl != NULL) {
- // Clone the null check in this branch to allow implicit null check
- new_val = clone_null_check(ctrl, val, unc_ctrl, phase);
- fix_null_check(unc, unc_ctrl, ctrl->in(0)->as_If()->proj_out(0), uses, phase);
+ assert(state->enqueue_barriers_count() == 0, "all enqueue barrier nodes should have been replaced");
- IfNode* iff = unc_ctrl->in(0)->as_If();
- phase->igvn().replace_input_of(iff, 1, phase->igvn().intcon(1));
- }
- Node* addr = new AddPNode(new_val, uncasted_val, phase->igvn().MakeConX(ShenandoahBrooksPointer::byte_offset()));
- phase->register_new_node(addr, ctrl);
- assert(val->bottom_type()->isa_oopptr(), "what else?");
- const TypePtr* obj_type = val->bottom_type()->is_oopptr();
- const TypePtr* adr_type = ShenandoahBarrierNode::brooks_pointer_type(obj_type);
- Node* fwd = new LoadPNode(ctrl, wb_mem, addr, adr_type, obj_type, MemNode::unordered);
- phase->register_new_node(fwd, ctrl);
-
- // Only branch to WB stub if object is not forwarded; otherwise reply with fwd ptr
- Node* cmp = new CmpPNode(fwd, new_val);
- phase->register_new_node(cmp, ctrl);
- Node* bol = new BoolNode(cmp, BoolTest::eq);
- phase->register_new_node(bol, ctrl);
-
- IfNode* iff = new IfNode(ctrl, bol, PROB_UNLIKELY(0.999), COUNT_UNKNOWN);
- if (reg2_ctrl == NULL) reg2_ctrl = iff;
- phase->register_control(iff, loop, ctrl);
- Node* if_not_eq = new IfFalseNode(iff);
- phase->register_control(if_not_eq, loop, iff);
- Node* if_eq = new IfTrueNode(iff);
- phase->register_control(if_eq, loop, iff);
-
- // Wire up not-equal-path in slots 3.
- region2->init_req(_not_equal, if_not_eq);
- val_phi2->init_req(_not_equal, fwd);
- mem_phi2->init_req(_not_equal, wb_mem);
- raw_mem_phi2->init_req(_not_equal, raw_mem);
-
- // Call wb-stub and wire up that path in slots 4
- Node* result_mem = NULL;
- ctrl = if_eq;
- call_wb_stub(ctrl, new_val, result_mem,
- raw_mem, wb_mem,
- alias, phase);
- region2->init_req(_evac_path, ctrl);
- val_phi2->init_req(_evac_path, new_val);
- mem_phi2->init_req(_evac_path, result_mem);
- raw_mem_phi2->init_req(_evac_path, result_mem);
-
- phase->register_control(region2, loop, reg2_ctrl);
- phase->register_new_node(val_phi2, region2);
- phase->register_new_node(mem_phi2, region2);
- phase->register_new_node(raw_mem_phi2, region2);
-
- region->init_req(_heap_unstable, region2);
- val_phi->init_req(_heap_unstable, val_phi2);
- mem_phi->init_req(_heap_unstable, mem_phi2);
- raw_mem_phi->init_req(_heap_unstable, raw_mem_phi2);
-
- phase->register_control(region, loop, heap_stable_iff);
- Node* out_val = val_phi;
- phase->register_new_node(val_phi, region);
- phase->register_new_node(mem_phi, region);
- phase->register_new_node(raw_mem_phi, region);
-
- fix_ctrl(wb, region, fixer, uses, uses_to_ignore, last, phase);
-
- ctrl = orig_ctrl;
-
- phase->igvn().replace_input_of(wbproj, ShenandoahWBMemProjNode::WriteBarrier, phase->C->top());
- phase->igvn().replace_node(wbproj, mem_phi);
- if (unc != NULL) {
- for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
- Node* u = val->fast_out(i);
- Node* c = phase->ctrl_or_self(u);
- if (u != wb && (c != ctrl || is_dominator_same_ctrl(c, wb, u, phase))) {
- phase->igvn().rehash_node_delayed(u);
- int nb = u->replace_edge(val, out_val);
- --i, imax -= nb;
- }
- }
- if (val->outcnt() == 0) {
- phase->igvn()._worklist.push(val);
- }
- }
- phase->igvn().replace_node(wb, out_val);
-
- follow_barrier_uses(mem_phi, ctrl, uses, phase);
- follow_barrier_uses(out_val, ctrl, uses, phase);
-
- for(uint next = 0; next < uses.size(); next++ ) {
- Node *n = uses.at(next);
- assert(phase->get_ctrl(n) == ctrl, "bad control");
- assert(n != init_raw_mem, "should leave input raw mem above the barrier");
- phase->set_ctrl(n, region);
- follow_barrier_uses(n, ctrl, uses, phase);
- }
-
- // The slow path call produces memory: hook the raw memory phi
- // from the expanded write barrier with the rest of the graph
- // which may require adding memory phis at every post dominated
- // region and at enclosing loop heads. Use the memory state
- // collected in memory_nodes to fix the memory graph. Update that
- // memory state as we go.
- fixer.fix_mem(ctrl, region, init_raw_mem, raw_mem_for_ctrl, raw_mem_phi, uses);
- assert(ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count() == cnt - 1, "not replaced");
- }
-
- assert(ShenandoahBarrierSetC2::bsc2()->state()->shenandoah_barriers_count() == 0, "all write barrier nodes should have been replaced");
}
-void ShenandoahWriteBarrierNode::move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) {
IdealLoopTree *loop = phase->get_loop(iff);
Node* loop_head = loop->_head;
Node* entry_c = loop_head->in(LoopNode::EntryControl);
@@ -3078,7 +1774,7 @@
}
}
-bool ShenandoahWriteBarrierNode::identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase) {
+bool ShenandoahBarrierC2Support::identical_backtoback_ifs(Node* n, PhaseIdealLoop* phase) {
if (!n->is_If() || n->is_CountedLoopEnd()) {
return false;
}
@@ -3113,7 +1809,7 @@
return true;
}
-void ShenandoahWriteBarrierNode::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) {
assert(is_heap_stable_test(n), "no other tests");
if (identical_backtoback_ifs(n, phase)) {
Node* n_ctrl = n->in(0);
@@ -3149,7 +1845,7 @@
}
}
-IfNode* ShenandoahWriteBarrierNode::find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase) {
+IfNode* ShenandoahBarrierC2Support::find_unswitching_candidate(const IdealLoopTree* loop, PhaseIdealLoop* phase) {
// Find first invariant test that doesn't exit the loop
LoopNode *head = loop->_head->as_Loop();
IfNode* unswitch_iff = NULL;
@@ -3194,10 +1890,9 @@
}
-void ShenandoahWriteBarrierNode::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) {
+void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) {
Node_List heap_stable_tests;
Node_List gc_state_loads;
-
stack.push(phase->C->start(), 0);
do {
Node* n = stack.node();
@@ -3274,7 +1969,7 @@
}
#ifdef ASSERT
-void ShenandoahBarrierNode::verify_raw_mem(RootNode* root) {
+void ShenandoahBarrierC2Support::verify_raw_mem(RootNode* root) {
const bool trace = false;
ResourceMark rm;
Unique_Node_List nodes;
@@ -3372,6 +2067,10 @@
}
#endif
+ShenandoahEnqueueBarrierNode::ShenandoahEnqueueBarrierNode(Node* val) : Node(NULL, val) {
+ ShenandoahBarrierSetC2::bsc2()->state()->add_enqueue_barrier(this);
+}
+
const Type* ShenandoahEnqueueBarrierNode::bottom_type() const {
if (in(1) == NULL || in(1)->is_top()) {
return Type::TOP;
@@ -3531,6 +2230,26 @@
Node* call = in->in(0)->in(0);
assert(call->is_Call(), "");
mem = call->in(TypeFunc::Memory);
+ } else if (in->Opcode() == Op_NeverBranch) {
+ ResourceMark rm;
+ Unique_Node_List wq;
+ wq.push(in);
+ wq.push(in->as_Multi()->proj_out(0));
+ for (uint j = 1; j < wq.size(); j++) {
+ Node* c = wq.at(j);
+ assert(!c->is_Root(), "shouldn't leave loop");
+ if (c->is_SafePoint()) {
+ assert(mem == NULL, "only one safepoint");
+ mem = c->in(TypeFunc::Memory);
+ }
+ for (DUIterator_Fast kmax, k = c->fast_outs(kmax); k < kmax; k++) {
+ Node* u = c->fast_out(k);
+ if (u->is_CFG()) {
+ wq.push(u);
+ }
+ }
+ }
+ assert(mem != NULL, "should have found safepoint");
}
}
} else {
@@ -3569,12 +2288,6 @@
assert(_alias == Compile::AliasIdxRaw, "");
stack.push(mem, mem->req());
mem = mem->in(MemNode::Memory);
- } else if (mem->Opcode() == Op_ShenandoahWriteBarrier) {
- assert(_alias != Compile::AliasIdxRaw, "");
- mem = mem->in(ShenandoahBarrierNode::Memory);
- } else if (mem->Opcode() == Op_ShenandoahWBMemProj) {
- stack.push(mem, mem->req());
- mem = mem->in(ShenandoahWBMemProjNode::WriteBarrier);
} else {
#ifdef ASSERT
mem->dump();
@@ -3628,7 +2341,7 @@
while (progress) {
progress = false;
iteration++;
- assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop(), "");
+ assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");
if (trace) { tty->print_cr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); }
IdealLoopTree* last_updated_ilt = NULL;
for (int i = rpo_list.size() - 1; i >= 0; i--) {
@@ -3796,7 +2509,7 @@
mem = _memory_nodes[c->_idx];
}
if (n != NULL && mem_is_valid(mem, c)) {
- while (!ShenandoahWriteBarrierNode::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) {
+ while (!ShenandoahBarrierC2Support::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) {
mem = next_mem(mem, _alias);
}
if (mem->is_MergeMem()) {
@@ -3842,12 +2555,6 @@
} else if (old->Opcode() == Op_SCMemProj) {
assert(_alias == Compile::AliasIdxRaw, "");
old = old->in(0);
- } else if (old->Opcode() == Op_ShenandoahWBMemProj) {
- assert(_alias != Compile::AliasIdxRaw, "");
- old = old->in(ShenandoahWBMemProjNode::WriteBarrier);
- } else if (old->Opcode() == Op_ShenandoahWriteBarrier) {
- assert(_alias != Compile::AliasIdxRaw, "");
- old = old->in(ShenandoahBarrierNode::Memory);
} else {
ShouldNotReachHere();
}
@@ -3857,7 +2564,7 @@
_memory_nodes.map(ctrl->_idx, mem);
_memory_nodes.map(new_ctrl->_idx, mem_for_ctrl);
}
- uint input = prev->Opcode() == Op_ShenandoahWriteBarrier ? (uint)ShenandoahBarrierNode::Memory : (uint)MemNode::Memory;
+ uint input = (uint)MemNode::Memory;
_phase->igvn().replace_input_of(prev, input, new_mem);
} else {
uses.clear();
@@ -3925,19 +2632,14 @@
} else {
DEBUG_ONLY(if (trace) { tty->print("ZZZ NOT setting mem"); m->dump(); });
for (;;) {
- assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj() || m->Opcode() == Op_ShenandoahWriteBarrier || m->Opcode() == Op_ShenandoahWBMemProj, "");
+ assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj(), "");
Node* next = NULL;
if (m->is_Proj()) {
next = m->in(0);
- } else if (m->Opcode() == Op_ShenandoahWBMemProj) {
- next = m->in(ShenandoahWBMemProjNode::WriteBarrier);
- } else if (m->is_Mem() || m->is_LoadStore()) {
+ } else {
+ assert(m->is_Mem() || m->is_LoadStore(), "");
assert(_alias == Compile::AliasIdxRaw, "");
next = m->in(MemNode::Memory);
- } else {
- assert(_alias != Compile::AliasIdxRaw, "");
- assert (m->Opcode() == Op_ShenandoahWriteBarrier, "");
- next = m->in(ShenandoahBarrierNode::Memory);
}
if (_phase->get_ctrl(next) != u) {
break;
@@ -3954,8 +2656,8 @@
}
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting to phi"); m->dump(); });
- assert(m->is_Mem() || m->is_LoadStore() || m->Opcode() == Op_ShenandoahWriteBarrier, "");
- uint input = (m->is_Mem() || m->is_LoadStore()) ? (uint)MemNode::Memory : (uint)ShenandoahBarrierNode::Memory;
+ assert(m->is_Mem() || m->is_LoadStore(), "");
+ uint input = (uint)MemNode::Memory;
_phase->igvn().replace_input_of(m, input, phi);
push = false;
}
@@ -4181,20 +2883,7 @@
for (DUIterator i = mem->outs(); mem->has_out(i); i++) {
Node* u = mem->out(i);
if (u != replacement && u->_idx < last) {
- if (u->is_ShenandoahBarrier() && _alias != Compile::AliasIdxRaw) {
- if (_phase->C->get_alias_index(u->adr_type()) == _alias && ShenandoahWriteBarrierNode::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
- _phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);
- assert(u->find_edge(mem) == -1, "only one edge");
- --i;
- }
- } else if (u->is_Mem()) {
- if (_phase->C->get_alias_index(u->adr_type()) == _alias && ShenandoahWriteBarrierNode::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
- assert(_alias == Compile::AliasIdxRaw , "only raw memory can lead to a memory operation");
- _phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);
- assert(u->find_edge(mem) == -1, "only one edge");
- --i;
- }
- } else if (u->is_MergeMem()) {
+ if (u->is_MergeMem()) {
MergeMemNode* u_mm = u->as_MergeMem();
if (u_mm->memory_at(_alias) == mem) {
MergeMemNode* newmm = NULL;
@@ -4222,7 +2911,7 @@
}
}
} else {
- if (rep_ctrl != uu && ShenandoahWriteBarrierNode::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) {
+ if (rep_ctrl != uu && ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) {
if (newmm == NULL) {
newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);
}
@@ -4263,10 +2952,11 @@
u->Opcode() == Op_Rethrow ||
u->Opcode() == Op_Return ||
u->Opcode() == Op_SafePoint ||
+ u->Opcode() == Op_StoreLConditional ||
(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||
(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||
u->Opcode() == Op_CallLeaf, "");
- if (ShenandoahWriteBarrierNode::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
+ if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
if (mm == NULL) {
mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);
}
@@ -4274,7 +2964,7 @@
--i;
}
} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {
- if (ShenandoahWriteBarrierNode::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
+ if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
_phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);
--i;
}
@@ -4283,11 +2973,324 @@
}
}
-void MemoryGraphFixer::remove(Node* n) {
- assert(n->Opcode() == Op_ShenandoahWBMemProj, "");
- Node* c = _phase->get_ctrl(n);
- Node* mem = find_mem(c, NULL);
- if (mem == n) {
- _memory_nodes.map(c->_idx, mem->in(ShenandoahWBMemProjNode::WriteBarrier)->in(ShenandoahBarrierNode::Memory));
+ShenandoahLoadReferenceBarrierNode::ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* obj)
+: Node(ctrl, obj) {
+ ShenandoahBarrierSetC2::bsc2()->state()->add_load_reference_barrier(this);
+}
+
+const Type* ShenandoahLoadReferenceBarrierNode::bottom_type() const {
+ if (in(ValueIn) == NULL || in(ValueIn)->is_top()) {
+ return Type::TOP;
+ }
+ const Type* t = in(ValueIn)->bottom_type();
+ if (t == TypePtr::NULL_PTR) {
+ return t;
+ }
+ return t->is_oopptr();
+}
+
+const Type* ShenandoahLoadReferenceBarrierNode::Value(PhaseGVN* phase) const {
+ // Either input is TOP ==> the result is TOP
+ const Type *t2 = phase->type(in(ValueIn));
+ if( t2 == Type::TOP ) return Type::TOP;
+
+ if (t2 == TypePtr::NULL_PTR) {
+ return t2;
+ }
+
+ const Type* type = t2->is_oopptr()/*->cast_to_nonconst()*/;
+ return type;
+}
+
+Node* ShenandoahLoadReferenceBarrierNode::Identity(PhaseGVN* phase) {
+ Node* value = in(ValueIn);
+ if (!needs_barrier(phase, value)) {
+ return value;
+ }
+ return this;
+}
+
+bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) {
+ Unique_Node_List visited;
+ return needs_barrier_impl(phase, n, visited);
+}
+
+bool ShenandoahLoadReferenceBarrierNode::needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited) {
+ if (n == NULL) return false;
+ if (visited.member(n)) {
+ return false; // Been there.
+ }
+ visited.push(n);
+
+ if (n->is_Allocate()) {
+ // tty->print_cr("optimize barrier on alloc");
+ return false;
+ }
+ if (n->is_Call()) {
+ // tty->print_cr("optimize barrier on call");
+ return false;
+ }
+
+ const Type* type = phase->type(n);
+ if (type == Type::TOP) {
+ return false;
+ }
+ if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) {
+ // tty->print_cr("optimize barrier on null");
+ return false;
+ }
+ if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL) {
+ // tty->print_cr("optimize barrier on constant");
+ return false;
+ }
+
+ switch (n->Opcode()) {
+ case Op_AddP:
+ return true; // TODO: Can refine?
+ case Op_LoadP:
+ case Op_ShenandoahCompareAndExchangeN:
+ case Op_ShenandoahCompareAndExchangeP:
+ case Op_CompareAndExchangeN:
+ case Op_CompareAndExchangeP:
+ case Op_GetAndSetN:
+ case Op_GetAndSetP:
+ return true;
+ case Op_Phi: {
+ for (uint i = 1; i < n->req(); i++) {
+ if (needs_barrier_impl(phase, n->in(i), visited)) return true;
+ }
+ return false;
+ }
+ case Op_CheckCastPP:
+ case Op_CastPP:
+ return needs_barrier_impl(phase, n->in(1), visited);
+ case Op_Proj:
+ return needs_barrier_impl(phase, n->in(0), visited);
+ case Op_ShenandoahLoadReferenceBarrier:
+ // tty->print_cr("optimize barrier on barrier");
+ return false;
+ case Op_Parm:
+ // tty->print_cr("optimize barrier on input arg");
+ return false;
+ case Op_DecodeN:
+ case Op_EncodeP:
+ return needs_barrier_impl(phase, n->in(1), visited);
+ case Op_LoadN:
+ return true;
+ case Op_CMoveP:
+ return needs_barrier_impl(phase, n->in(2), visited) ||
+ needs_barrier_impl(phase, n->in(3), visited);
+ case Op_ShenandoahEnqueueBarrier:
+ return needs_barrier_impl(phase, n->in(1), visited);
+ default:
+ break;
}
+#ifdef ASSERT
+ tty->print("need barrier on?: ");
+ tty->print_cr("ins:");
+ n->dump(2);
+ tty->print_cr("outs:");
+ n->dump(-2);
+ ShouldNotReachHere();
+#endif
+ return true;
}
+
+ShenandoahLoadReferenceBarrierNode::Strength ShenandoahLoadReferenceBarrierNode::get_barrier_strength() {
+ Unique_Node_List visited;
+ Node_Stack stack(0);
+ stack.push(this, 0);
+ Strength strength = NONE;
+ while (strength != STRONG && stack.size() > 0) {
+ Node* n = stack.node();
+ if (visited.member(n)) {
+ stack.pop();
+ continue;
+ }
+ visited.push(n);
+ bool visit_users = false;
+ switch (n->Opcode()) {
+ case Op_StoreN:
+ case Op_StoreP: {
+ strength = STRONG;
+ break;
+ }
+ case Op_CmpP: {
+ if (!n->in(1)->bottom_type()->higher_equal(TypePtr::NULL_PTR) &&
+ !n->in(2)->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
+ strength = STRONG;
+ }
+ break;
+ }
+ case Op_CallStaticJava: {
+ strength = STRONG;
+ break;
+ }
+ case Op_CallDynamicJava:
+ case Op_CallLeaf:
+ case Op_CallLeafNoFP:
+ case Op_CompareAndSwapL:
+ case Op_CompareAndSwapI:
+ case Op_CompareAndSwapB:
+ case Op_CompareAndSwapS:
+ case Op_CompareAndSwapN:
+ case Op_CompareAndSwapP:
+ case Op_ShenandoahCompareAndSwapN:
+ case Op_ShenandoahCompareAndSwapP:
+ case Op_ShenandoahWeakCompareAndSwapN:
+ case Op_ShenandoahWeakCompareAndSwapP:
+ case Op_ShenandoahCompareAndExchangeN:
+ case Op_ShenandoahCompareAndExchangeP:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeB:
+ case Op_CompareAndExchangeS:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapB:
+ case Op_WeakCompareAndSwapS:
+ case Op_GetAndSetL:
+ case Op_GetAndSetI:
+ case Op_GetAndSetB:
+ case Op_GetAndSetS:
+ case Op_GetAndSetP:
+ case Op_GetAndSetN:
+ case Op_GetAndAddL:
+ case Op_GetAndAddI:
+ case Op_GetAndAddB:
+ case Op_GetAndAddS:
+ case Op_ShenandoahEnqueueBarrier:
+ case Op_FastLock:
+ case Op_FastUnlock:
+ case Op_Rethrow:
+ case Op_Return:
+ case Op_StoreB:
+ case Op_StoreC:
+ case Op_StoreD:
+ case Op_StoreF:
+ case Op_StoreL:
+ case Op_StoreLConditional:
+ case Op_StoreI:
+ case Op_StoreVector:
+ case Op_StrInflatedCopy:
+ case Op_StrCompressedCopy:
+ case Op_EncodeP:
+ case Op_CastP2X:
+ case Op_SafePoint:
+ case Op_EncodeISOArray:
+ strength = STRONG;
+ break;
+ case Op_LoadB:
+ case Op_LoadUB:
+ case Op_LoadUS:
+ case Op_LoadD:
+ case Op_LoadF:
+ case Op_LoadL:
+ case Op_LoadI:
+ case Op_LoadS:
+ case Op_LoadN:
+ case Op_LoadP:
+ case Op_LoadVector: {
+ const TypePtr* adr_type = n->adr_type();
+ int alias_idx = Compile::current()->get_alias_index(adr_type);
+ Compile::AliasType* alias_type = Compile::current()->alias_type(alias_idx);
+ ciField* field = alias_type->field();
+ bool is_static = field != NULL && field->is_static();
+ bool is_final = field != NULL && field->is_final();
+ bool is_stable = field != NULL && field->is_stable();
+ if (ShenandoahOptimizeStaticFinals && is_static && is_final) {
+ // Leave strength as is.
+ } else if (ShenandoahOptimizeInstanceFinals && !is_static && is_final) {
+ // Leave strength as is.
+ } else if (ShenandoahOptimizeStableFinals && (is_stable || (adr_type->isa_aryptr() && adr_type->isa_aryptr()->is_stable()))) {
+ // Leave strength as is.
+ } else {
+ strength = WEAK;
+ }
+ break;
+ }
+ case Op_AryEq: {
+ Node* n1 = n->in(2);
+ Node* n2 = n->in(3);
+ if (!ShenandoahOptimizeStableFinals ||
+ !n1->bottom_type()->isa_aryptr() || !n1->bottom_type()->isa_aryptr()->is_stable() ||
+ !n2->bottom_type()->isa_aryptr() || !n2->bottom_type()->isa_aryptr()->is_stable()) {
+ strength = WEAK;
+ }
+ break;
+ }
+ case Op_StrEquals:
+ case Op_StrComp:
+ case Op_StrIndexOf:
+ case Op_StrIndexOfChar:
+ if (!ShenandoahOptimizeStableFinals) {
+ strength = WEAK;
+ }
+ break;
+ case Op_Conv2B:
+ case Op_LoadRange:
+ case Op_LoadKlass:
+ case Op_LoadNKlass:
+ // NONE, i.e. leave current strength as is
+ break;
+ case Op_AddP:
+ case Op_CheckCastPP:
+ case Op_CastPP:
+ case Op_CMoveP:
+ case Op_Phi:
+ case Op_ShenandoahLoadReferenceBarrier:
+ visit_users = true;
+ break;
+ default: {
+#ifdef ASSERT
+ tty->print_cr("Unknown node in get_barrier_strength:");
+ n->dump(1);
+ ShouldNotReachHere();
+#else
+ strength = STRONG;
+#endif
+ }
+ }
+#ifdef ASSERT
+/*
+ if (strength == STRONG) {
+ tty->print("strengthening node: ");
+ n->dump();
+ }
+ */
+#endif
+ stack.pop();
+ if (visit_users) {
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ Node* user = n->fast_out(i);
+ if (user != NULL) {
+ stack.push(user, 0);
+ }
+ }
+ }
+ }
+ return strength;
+}
+
+CallStaticJavaNode* ShenandoahLoadReferenceBarrierNode::pin_and_expand_null_check(PhaseIterGVN& igvn) {
+ Node* val = in(ValueIn);
+
+ const Type* val_t = igvn.type(val);
+
+ if (val_t->meet(TypePtr::NULL_PTR) != val_t &&
+ val->Opcode() == Op_CastPP &&
+ val->in(0) != NULL &&
+ val->in(0)->Opcode() == Op_IfTrue &&
+ val->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&
+ val->in(0)->in(0)->is_If() &&
+ val->in(0)->in(0)->in(1)->Opcode() == Op_Bool &&
+ val->in(0)->in(0)->in(1)->as_Bool()->_test._test == BoolTest::ne &&
+ val->in(0)->in(0)->in(1)->in(1)->Opcode() == Op_CmpP &&
+ val->in(0)->in(0)->in(1)->in(1)->in(1) == val->in(1) &&
+ val->in(0)->in(0)->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) {
+ assert(val->in(0)->in(0)->in(1)->in(1)->in(1) == val->in(1), "");
+ CallStaticJavaNode* unc = val->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+ return unc;
+ }
+ return NULL;
+}
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -36,10 +36,8 @@
class PhaseGVN;
class MemoryGraphFixer;
-class ShenandoahBarrierNode : public TypeNode {
+class ShenandoahBarrierC2Support : public AllStatic {
private:
- bool _allow_fromspace;
-
#ifdef ASSERT
enum verify_type {
ShenandoahLoad,
@@ -50,204 +48,49 @@
};
static bool verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used);
-#endif
-
-public:
- enum { Control,
- Memory,
- ValueIn
- };
-
- ShenandoahBarrierNode(Node* ctrl, Node* mem, Node* obj, bool allow_fromspace)
- : TypeNode(obj->bottom_type()->isa_oopptr() ? obj->bottom_type()->is_oopptr()->cast_to_nonconst() : obj->bottom_type(), 3),
- _allow_fromspace(allow_fromspace) {
-
- init_req(Control, ctrl);
- init_req(Memory, mem);
- init_req(ValueIn, obj);
-
- init_class_id(Class_ShenandoahBarrier);
- }
-
- static Node* skip_through_barrier(Node* n);
-
- static const TypeOopPtr* brooks_pointer_type(const Type* t) {
- return t->is_oopptr()->cast_to_nonconst()->add_offset(ShenandoahBrooksPointer::byte_offset())->is_oopptr();
- }
-
- virtual const TypePtr* adr_type() const {
- if (bottom_type() == Type::TOP) {
- return NULL;
- }
- //const TypePtr* adr_type = in(MemNode::Address)->bottom_type()->is_ptr();
- const TypePtr* adr_type = brooks_pointer_type(bottom_type());
- assert(adr_type->offset() == ShenandoahBrooksPointer::byte_offset(), "sane offset");
- assert(Compile::current()->alias_type(adr_type)->is_rewritable(), "brooks ptr must be rewritable");
- return adr_type;
- }
-
- virtual uint ideal_reg() const { return Op_RegP; }
- virtual uint match_edge(uint idx) const {
- return idx >= ValueIn;
- }
-
- Node* Identity_impl(PhaseGVN* phase);
-
- virtual const Type* Value(PhaseGVN* phase) const;
- virtual bool depends_only_on_test() const {
- return true;
- };
-
- static bool needs_barrier(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace);
-
-#ifdef ASSERT
static void report_verify_failure(const char* msg, Node* n1 = NULL, Node* n2 = NULL);
- static void verify(RootNode* root);
static void verify_raw_mem(RootNode* root);
#endif
-#ifndef PRODUCT
- virtual void dump_spec(outputStream *st) const;
-#endif
-
- // protected:
- static Node* dom_mem(Node* mem, Node*& mem_ctrl, Node* n, Node* rep_ctrl, int alias, PhaseIdealLoop* phase);
static Node* dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase);
- static bool is_dominator(Node *d_c, Node *n_c, Node* d, Node* n, PhaseIdealLoop* phase);
- static bool is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase);
static Node* no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase);
- static bool build_loop_late_post(PhaseIdealLoop* phase, Node* n);
- bool sink_node(PhaseIdealLoop* phase, Node* ctrl, Node* n_ctrl);
-
-protected:
- uint hash() const;
- bool cmp(const Node& n) const;
- uint size_of() const;
-
-private:
- static bool needs_barrier_impl(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace, Unique_Node_List &visited);
-
- static bool dominates_memory(PhaseGVN* phase, Node* b1, Node* b2, bool linear);
- static bool dominates_memory_impl(PhaseGVN* phase, Node* b1, Node* b2, Node* current, bool linear);
-};
-
-class ShenandoahReadBarrierNode : public ShenandoahBarrierNode {
-public:
- ShenandoahReadBarrierNode(Node* ctrl, Node* mem, Node* obj)
- : ShenandoahBarrierNode(ctrl, mem, obj, true) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier ||
- ShenandoahWriteBarrier || ShenandoahAcmpBarrier),
- "should be enabled");
- }
- ShenandoahReadBarrierNode(Node* ctrl, Node* mem, Node* obj, bool allow_fromspace)
- : ShenandoahBarrierNode(ctrl, mem, obj, allow_fromspace) {
- assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier ||
- ShenandoahWriteBarrier || ShenandoahAcmpBarrier),
- "should be enabled");
- }
-
- virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
- virtual Node* Identity(PhaseGVN* phase);
- virtual int Opcode() const;
-
- bool is_independent(Node* mem);
-
- void try_move(PhaseIdealLoop* phase);
-
-private:
- static bool is_independent(const Type* in_type, const Type* this_type);
- static bool dominates_memory_rb(PhaseGVN* phase, Node* b1, Node* b2, bool linear);
- static bool dominates_memory_rb_impl(PhaseGVN* phase, Node* b1, Node* b2, Node* current, bool linear);
-};
-
-class ShenandoahWriteBarrierNode : public ShenandoahBarrierNode {
-public:
- ShenandoahWriteBarrierNode(Compile* C, Node* ctrl, Node* mem, Node* obj);
-
- virtual int Opcode() const;
- virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
- virtual Node* Identity(PhaseGVN* phase);
- virtual bool depends_only_on_test() const { return false; }
-
- static bool expand(Compile* C, PhaseIterGVN& igvn);
- static bool is_gc_state_load(Node *n);
static bool is_heap_state_test(Node* iff, int mask);
- static bool is_heap_stable_test(Node* iff);
static bool try_common_gc_state_load(Node *n, PhaseIdealLoop *phase);
static bool has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase);
-
- static LoopNode* try_move_before_pre_loop(Node* c, Node* val_ctrl, PhaseIdealLoop* phase);
- static Node* move_above_predicates(LoopNode* cl, Node* val_ctrl, PhaseIdealLoop* phase);
-#ifdef ASSERT
- static bool memory_dominates_all_paths(Node* mem, Node* rep_ctrl, int alias, PhaseIdealLoop* phase);
- static void memory_dominates_all_paths_helper(Node* c, Node* rep_ctrl, Unique_Node_List& controls, PhaseIdealLoop* phase);
-#endif
- void try_move_before_loop(GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses);
- void try_move_before_loop_helper(LoopNode* cl, Node* val_ctrl, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses);
- static void pin_and_expand(PhaseIdealLoop* phase);
- CallStaticJavaNode* pin_and_expand_null_check(PhaseIterGVN& igvn);
- void pin_and_expand_move_barrier(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, Unique_Node_List& uses);
- void pin_and_expand_helper(PhaseIdealLoop* phase);
static Node* find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase);
static void follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase);
static void test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase);
-
static void test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
PhaseIdealLoop* phase);
- static void call_wb_stub(Node*& ctrl, Node*& val, Node*& result_mem,
- Node* raw_mem, Node* wb_mem, int alias,
- PhaseIdealLoop* phase);
+ static void call_lrb_stub(Node*& ctrl, Node*& val, Node*& result_mem, Node* raw_mem, PhaseIdealLoop* phase);
static Node* clone_null_check(Node*& c, Node* val, Node* unc_ctrl, PhaseIdealLoop* phase);
static void fix_null_check(Node* unc, Node* unc_ctrl, Node* new_unc_ctrl, Unique_Node_List& uses,
PhaseIdealLoop* phase);
static void in_cset_fast_test(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
static void move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase);
-
- static void optimize_after_expansion(VectorSet &visited, Node_Stack &nstack, Node_List &old_new, PhaseIdealLoop* phase);
static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase);
static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase);
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
-
- static void optimize_before_expansion(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*> memory_graph_fixers, bool include_lsm);
- Node* would_subsume(ShenandoahBarrierNode* other, PhaseIdealLoop* phase);
static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase);
- Node* try_split_thru_phi(PhaseIdealLoop* phase);
-};
+public:
+ static bool is_dominator(Node* d_c, Node* n_c, Node* d, Node* n, PhaseIdealLoop* phase);
+ static bool is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase);
-class ShenandoahWBMemProjNode : public Node {
-public:
- enum { Control,
- WriteBarrier };
-
- ShenandoahWBMemProjNode(Node *src) : Node(NULL, src) {
- assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
- assert(src->Opcode() == Op_ShenandoahWriteBarrier || src->is_Mach(), "epxect wb");
- }
- virtual Node* Identity(PhaseGVN* phase);
+ static bool is_gc_state_load(Node* n);
+ static bool is_heap_stable_test(Node* iff);
- virtual int Opcode() const;
- virtual bool is_CFG() const { return false; }
- virtual const Type *bottom_type() const {return Type::MEMORY;}
- virtual const TypePtr *adr_type() const {
- Node* wb = in(WriteBarrier);
- if (wb == NULL || wb->is_top()) return NULL; // node is dead
- assert(wb->Opcode() == Op_ShenandoahWriteBarrier || (wb->is_Mach() && wb->as_Mach()->ideal_Opcode() == Op_ShenandoahWriteBarrier) || wb->is_Phi(), "expect wb");
- return ShenandoahBarrierNode::brooks_pointer_type(wb->bottom_type());
- }
+ static bool expand(Compile* C, PhaseIterGVN& igvn);
+ static void pin_and_expand(PhaseIdealLoop* phase);
+ static void optimize_after_expansion(VectorSet& visited, Node_Stack& nstack, Node_List& old_new, PhaseIdealLoop* phase);
- virtual uint ideal_reg() const { return 0;} // memory projections don't have a register
- virtual const Type *Value(PhaseGVN* phase ) const {
- return bottom_type();
- }
-#ifndef PRODUCT
- virtual void dump_spec(outputStream *st) const {};
+#ifdef ASSERT
+ static void verify(RootNode* root);
#endif
};
class ShenandoahEnqueueBarrierNode : public Node {
public:
- ShenandoahEnqueueBarrierNode(Node* val) : Node(NULL, val) {
- }
+ ShenandoahEnqueueBarrierNode(Node* val);
const Type *bottom_type() const;
const Type* Value(PhaseGVN* phase) const;
@@ -289,7 +132,6 @@
Node* find_mem(Node* ctrl, Node* n) const;
void fix_mem(Node* ctrl, Node* region, Node* mem, Node* mem_for_ctrl, Node* mem_phi, Unique_Node_List& uses);
int alias() const { return _alias; }
- void remove(Node* n);
};
class ShenandoahCompareAndSwapPNode : public CompareAndSwapPNode {
@@ -382,4 +224,41 @@
virtual int Opcode() const;
};
+class ShenandoahLoadReferenceBarrierNode : public Node {
+public:
+ enum {
+ Control,
+ ValueIn
+ };
+
+ enum Strength {
+ NONE, WEAK, STRONG, NA
+ };
+
+ ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* val);
+
+ virtual int Opcode() const;
+ virtual const Type* bottom_type() const;
+ virtual const Type* Value(PhaseGVN* phase) const;
+ virtual const class TypePtr *adr_type() const { return TypeOopPtr::BOTTOM; }
+ virtual uint match_edge(uint idx) const {
+ return idx >= ValueIn;
+ }
+ virtual uint ideal_reg() const { return Op_RegP; }
+
+ virtual Node* Identity(PhaseGVN* phase);
+
+ uint size_of() const {
+ return sizeof(*this);
+ }
+
+ Strength get_barrier_strength();
+ CallStaticJavaNode* pin_and_expand_null_check(PhaseIterGVN& igvn);
+
+private:
+ bool needs_barrier(PhaseGVN* phase, Node* n);
+ bool needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited);
+};
+
+
#endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHSUPPORT_HPP
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -41,13 +41,10 @@
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
// Final configuration checks
+ SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahReadBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahWriteBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValReadBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahAcmpBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
}
@@ -75,7 +72,7 @@
// we hit max_cset. When max_cset is hit, we terminate the cset selection. Note that in this scheme,
// ShenandoahGarbageThreshold is the soft threshold which would be ignored until min_garbage is hit.
- size_t capacity = ShenandoahHeap::heap()->capacity();
+ size_t capacity = ShenandoahHeap::heap()->max_capacity();
size_t free_target = ShenandoahMinFreeThreshold * capacity / 100;
size_t min_garbage = free_target > actual_free ? (free_target - actual_free) : 0;
size_t max_cset = (size_t)(1.0 * ShenandoahEvacReserve * capacity / 100 / ShenandoahEvacWaste);
@@ -126,12 +123,12 @@
bool ShenandoahAdaptiveHeuristics::should_start_normal_gc() const {
ShenandoahHeap* heap = ShenandoahHeap::heap();
- size_t capacity = heap->capacity();
+ size_t capacity = heap->max_capacity();
size_t available = heap->free_set()->available();
// Check if we are falling below the worst limit, time to trigger the GC, regardless of
// anything else.
- size_t min_threshold = ShenandoahMinFreeThreshold * heap->capacity() / 100;
+ size_t min_threshold = ShenandoahMinFreeThreshold * heap->max_capacity() / 100;
if (available < min_threshold) {
log_info(gc)("Trigger: Free (" SIZE_FORMAT "M) is below minimum threshold (" SIZE_FORMAT "M)",
available / M, min_threshold / M);
@@ -141,7 +138,7 @@
// Check if are need to learn a bit about the application
const size_t max_learn = ShenandoahLearningSteps;
if (_gc_times_learned < max_learn) {
- size_t init_threshold = ShenandoahInitFreeThreshold * heap->capacity() / 100;
+ size_t init_threshold = ShenandoahInitFreeThreshold * heap->max_capacity() / 100;
if (available < init_threshold) {
log_info(gc)("Trigger: Learning " SIZE_FORMAT " of " SIZE_FORMAT ". Free (" SIZE_FORMAT "M) is below initial threshold (" SIZE_FORMAT "M)",
_gc_times_learned + 1, max_learn, available / M, init_threshold / M);
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -47,13 +47,10 @@
}
// Final configuration checks
+ SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahReadBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahWriteBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValReadBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahAcmpBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
}
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -42,13 +42,10 @@
SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahGarbageThreshold, 10);
// Final configuration checks
+ SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahReadBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahWriteBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValReadBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahAcmpBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
}
@@ -56,8 +53,8 @@
ShenandoahHeap* heap = ShenandoahHeap::heap();
size_t available = heap->free_set()->available();
- size_t threshold_bytes_allocated = heap->capacity() * ShenandoahAllocationThreshold / 100;
- size_t min_threshold = ShenandoahMinFreeThreshold * heap->capacity() / 100;
+ size_t threshold_bytes_allocated = heap->max_capacity() * ShenandoahAllocationThreshold / 100;
+ size_t min_threshold = ShenandoahMinFreeThreshold * heap->max_capacity() / 100;
if (available < min_threshold) {
log_info(gc)("Trigger: Free (" SIZE_FORMAT "M) is below minimum threshold (" SIZE_FORMAT "M)",
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -43,14 +43,11 @@
}
// Disable known barriers by default.
+ SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahLoadRefBarrier);
SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahSATBBarrier);
SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahKeepAliveBarrier);
- SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahWriteBarrier);
- SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahReadBarrier);
SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValEnqueueBarrier);
- SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValReadBarrier);
SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCASBarrier);
- SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahAcmpBarrier);
SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCloneBarrier);
// Final configuration checks
@@ -84,7 +81,7 @@
// Do not select too large CSet that would overflow the available free space.
// Take at least the entire evacuation reserve, and be free to overflow to free space.
- size_t capacity = ShenandoahHeap::heap()->capacity();
+ size_t capacity = ShenandoahHeap::heap()->max_capacity();
size_t available = MAX2(ShenandoahEvacReserve * capacity / 100, actual_free);
size_t max_cset = (size_t)(available / ShenandoahEvacWaste);
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -40,13 +40,10 @@
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
// Final configuration checks
+ SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahReadBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahWriteBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValReadBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahAcmpBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
}
@@ -55,7 +52,7 @@
bool ShenandoahStaticHeuristics::should_start_normal_gc() const {
ShenandoahHeap* heap = ShenandoahHeap::heap();
- size_t capacity = heap->capacity();
+ size_t capacity = heap->max_capacity();
size_t available = heap->free_set()->available();
size_t threshold_available = (capacity * ShenandoahFreeThreshold) / 100;
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -37,27 +37,17 @@
_last_cset_select(0)
{
FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false);
- FLAG_SET_DEFAULT(ShenandoahStoreValReadBarrier, false);
FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, true);
FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false);
FLAG_SET_DEFAULT(ShenandoahAllowMixedAllocs, false);
- SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahRefProcFrequency, 1);
-
- // Adjust class unloading settings only if globally enabled.
- if (ClassUnloadingWithConcurrentMark) {
- SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahUnloadClassesFrequency, 1);
- }
-
SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
// Final configuration checks
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahReadBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahWriteBarrier);
+ SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValEnqueueBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
- SHENANDOAH_CHECK_FLAG_SET(ShenandoahAcmpBarrier);
SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
}
@@ -127,7 +117,7 @@
// The significant complication is that liveness data was collected at the previous cycle, and only
// for those regions that were allocated before previous cycle started.
- size_t capacity = heap->capacity();
+ size_t capacity = heap->max_capacity();
size_t actual_free = heap->free_set()->available();
size_t free_target = ShenandoahMinFreeThreshold * capacity / 100;
size_t min_garbage = free_target > actual_free ? (free_target - actual_free) : 0;
@@ -216,12 +206,12 @@
ShenandoahHeap* heap = ShenandoahHeap::heap();
assert(!heap->has_forwarded_objects(), "no forwarded objects here");
- size_t capacity = heap->capacity();
+ size_t capacity = heap->max_capacity();
size_t available = heap->free_set()->available();
// Check if we are falling below the worst limit, time to trigger the GC, regardless of
// anything else.
- size_t min_threshold = ShenandoahMinFreeThreshold * heap->capacity() / 100;
+ size_t min_threshold = ShenandoahMinFreeThreshold * heap->max_capacity() / 100;
if (available < min_threshold) {
log_info(gc)("Trigger: Free (" SIZE_FORMAT "M) is below minimum threshold (" SIZE_FORMAT "M)",
available / M, min_threshold / M);
@@ -231,7 +221,7 @@
// Check if are need to learn a bit about the application
const size_t max_learn = ShenandoahLearningSteps;
if (_gc_times_learned < max_learn) {
- size_t init_threshold = ShenandoahInitFreeThreshold * heap->capacity() / 100;
+ size_t init_threshold = ShenandoahInitFreeThreshold * heap->max_capacity() / 100;
if (available < init_threshold) {
log_info(gc)("Trigger: Learning " SIZE_FORMAT " of " SIZE_FORMAT ". Free (" SIZE_FORMAT "M) is below initial threshold (" SIZE_FORMAT "M)",
_gc_times_learned + 1, max_learn, available / M, init_threshold / M);
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -46,12 +46,8 @@
FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false);
FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false);
- FLAG_SET_DEFAULT(ShenandoahWriteBarrier, false);
- FLAG_SET_DEFAULT(ShenandoahReadBarrier, false);
FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, false);
- FLAG_SET_DEFAULT(ShenandoahStoreValReadBarrier, false);
FLAG_SET_DEFAULT(ShenandoahCASBarrier, false);
- FLAG_SET_DEFAULT(ShenandoahAcmpBarrier, false);
FLAG_SET_DEFAULT(ShenandoahCloneBarrier, false);
#endif
@@ -111,12 +107,8 @@
if (ShenandoahVerifyOptoBarriers &&
(!FLAG_IS_DEFAULT(ShenandoahSATBBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahKeepAliveBarrier) ||
- !FLAG_IS_DEFAULT(ShenandoahWriteBarrier) ||
- !FLAG_IS_DEFAULT(ShenandoahReadBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahStoreValEnqueueBarrier) ||
- !FLAG_IS_DEFAULT(ShenandoahStoreValReadBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahCASBarrier) ||
- !FLAG_IS_DEFAULT(ShenandoahAcmpBarrier) ||
!FLAG_IS_DEFAULT(ShenandoahCloneBarrier)
)) {
warning("Unusual barrier configuration, disabling C2 barrier verification");
@@ -147,6 +139,11 @@
FLAG_SET_DEFAULT(ShenandoahUncommit, false);
}
+ if ((InitialHeapSize == MaxHeapSize) && ShenandoahUncommit) {
+ log_info(gc)("Min heap equals to max heap, disabling ShenandoahUncommit");
+ FLAG_SET_DEFAULT(ShenandoahUncommit, false);
+ }
+
// If class unloading is disabled, no unloading for concurrent cycles as well.
// If class unloading is enabled, users should opt-in for unloading during
// concurrent cycles.
@@ -164,13 +161,6 @@
FLAG_SET_DEFAULT(UseAOT, false);
}
- // JNI fast get field stuff is not currently supported by Shenandoah.
- // It would introduce another heap memory access for reading the forwarding
- // pointer, which would have to be guarded by the signal handler machinery.
- // See:
- // http://mail.openjdk.java.net/pipermail/hotspot-dev/2018-June/032763.html
- FLAG_SET_DEFAULT(UseFastJNIAccessors, false);
-
// TLAB sizing policy makes resizing decisions before each GC cycle. It averages
// historical data, assigning more recent data the weight according to TLABAllocationWeight.
// Current default is good for generational collectors that run frequent young GCs.
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -107,11 +107,8 @@
}
void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
- assert(UseShenandoahGC, "should be enabled");
- if (count == 0) return;
- if (!ShenandoahCloneBarrier) return;
-
- if (!need_update_refs_barrier()) return;
+ assert(_heap->is_update_refs_in_progress(), "should not be here otherwise");
+ assert(count > 0, "Should have been filtered before");
if (_heap->is_concurrent_traversal_in_progress()) {
ShenandoahEvacOOMScope oom_evac_scope;
@@ -197,9 +194,8 @@
}
void ShenandoahBarrierSet::write_region(MemRegion mr) {
- assert(UseShenandoahGC, "should be enabled");
if (!ShenandoahCloneBarrier) return;
- if (! need_update_refs_barrier()) return;
+ if (!_heap->is_update_refs_in_progress()) return;
// This is called for cloning an object (see jvm.cpp) after the clone
// has been made. We are not interested in any 'previous value' because
@@ -218,31 +214,25 @@
}
}
-oop ShenandoahBarrierSet::read_barrier(oop src) {
- // Check for forwarded objects, because on Full GC path we might deal with
- // non-trivial fwdptrs that contain Full GC specific metadata. We could check
- // for is_full_gc_in_progress(), but this also covers the case of stable heap,
- // which provides a bit of performance improvement.
- if (ShenandoahReadBarrier && _heap->has_forwarded_objects()) {
- return ShenandoahBarrierSet::resolve_forwarded(src);
+oop ShenandoahBarrierSet::load_reference_barrier_not_null(oop obj) {
+ if (ShenandoahLoadRefBarrier && _heap->has_forwarded_objects()) {
+ return load_reference_barrier_impl(obj);
} else {
- return src;
+ return obj;
}
}
-bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
- bool eq = oopDesc::equals_raw(obj1, obj2);
- if (! eq && ShenandoahAcmpBarrier) {
- OrderAccess::loadload();
- obj1 = resolve_forwarded(obj1);
- obj2 = resolve_forwarded(obj2);
- eq = oopDesc::equals_raw(obj1, obj2);
+oop ShenandoahBarrierSet::load_reference_barrier(oop obj) {
+ if (obj != NULL) {
+ return load_reference_barrier_not_null(obj);
+ } else {
+ return obj;
}
- return eq;
}
-oop ShenandoahBarrierSet::write_barrier_mutator(oop obj) {
- assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
+
+oop ShenandoahBarrierSet::load_reference_barrier_mutator(oop obj) {
+ assert(ShenandoahLoadRefBarrier, "should be enabled");
assert(_heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL), "evac should be in progress");
shenandoah_assert_in_cset(NULL, obj);
@@ -288,8 +278,8 @@
return fwd;
}
-oop ShenandoahBarrierSet::write_barrier_impl(oop obj) {
- assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
+oop ShenandoahBarrierSet::load_reference_barrier_impl(oop obj) {
+ assert(ShenandoahLoadRefBarrier, "should be enabled");
if (!CompressedOops::is_null(obj)) {
bool evac_in_progress = _heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL);
oop fwd = resolve_forwarded_not_null(obj);
@@ -311,23 +301,10 @@
}
}
-oop ShenandoahBarrierSet::write_barrier(oop obj) {
- if (ShenandoahWriteBarrier && _heap->has_forwarded_objects()) {
- return write_barrier_impl(obj);
- } else {
- return obj;
- }
-}
-
-oop ShenandoahBarrierSet::storeval_barrier(oop obj) {
+void ShenandoahBarrierSet::storeval_barrier(oop obj) {
if (ShenandoahStoreValEnqueueBarrier && !CompressedOops::is_null(obj) && _heap->is_concurrent_traversal_in_progress()) {
- obj = write_barrier(obj);
enqueue(obj);
}
- if (ShenandoahStoreValReadBarrier) {
- obj = resolve_forwarded(obj);
- }
- return obj;
}
void ShenandoahBarrierSet::keep_alive_barrier(oop obj) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -87,34 +87,23 @@
virtual void on_thread_attach(Thread* thread);
virtual void on_thread_detach(Thread* thread);
- virtual oop read_barrier(oop src);
-
static inline oop resolve_forwarded_not_null(oop p);
static inline oop resolve_forwarded(oop p);
- virtual oop write_barrier(oop obj);
-
- oop write_barrier_mutator(oop obj);
-
- virtual oop storeval_barrier(oop obj);
+ void storeval_barrier(oop obj);
+ void keep_alive_barrier(oop obj);
- virtual void keep_alive_barrier(oop obj);
-
- bool obj_equals(oop obj1, oop obj2);
-
-#ifdef CHECK_UNHANDLED_OOPS
- bool oop_equals_operator_allowed() { return !ShenandoahVerifyObjectEquals; }
-#endif
+ oop load_reference_barrier(oop obj);
+ oop load_reference_barrier_mutator(oop obj);
+ oop load_reference_barrier_not_null(oop obj);
void enqueue(oop obj);
private:
- inline bool need_update_refs_barrier();
-
template <class T, bool STOREVAL_WRITE_BARRIER>
void write_ref_array_loop(HeapWord* start, size_t count);
- oop write_barrier_impl(oop obj);
+ oop load_reference_barrier_impl(oop obj);
static void keep_alive_if_weak(DecoratorSet decorators, oop value) {
assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
@@ -149,114 +138,31 @@
class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> {
typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw;
- public:
- // Primitive heap accesses. These accessors get resolved when
- // IN_HEAP is set (e.g. when using the HeapAccess API), it is
- // not an oop_* overload, and the barrier strength is AS_NORMAL.
template <typename T>
- static T load_in_heap(T* addr) {
- ShouldNotReachHere();
- return Raw::template load<T>(addr);
- }
-
- template <typename T>
- static T load_in_heap_at(oop base, ptrdiff_t offset) {
- base = ShenandoahBarrierSet::resolve_forwarded(base);
- return Raw::template load_at<T>(base, offset);
- }
-
- template <typename T>
- static void store_in_heap(T* addr, T value) {
- ShouldNotReachHere();
- Raw::store(addr, value);
- }
-
- template <typename T>
- static void store_in_heap_at(oop base, ptrdiff_t offset, T value) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- Raw::store_at(base, offset, value);
- }
+ static oop oop_atomic_cmpxchg_in_heap_impl(oop new_value, T* addr, oop compare_value);
template <typename T>
- static T atomic_cmpxchg_in_heap(T new_value, T* addr, T compare_value) {
- ShouldNotReachHere();
- return Raw::atomic_cmpxchg(new_value, addr, compare_value);
- }
-
- template <typename T>
- static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- return Raw::atomic_cmpxchg_at(new_value, base, offset, compare_value);
- }
+ static oop oop_atomic_xchg_in_heap_impl(oop new_value, T* addr);
- template <typename T>
- static T atomic_xchg_in_heap(T new_value, T* addr) {
- ShouldNotReachHere();
- return Raw::atomic_xchg(new_value, addr);
- }
-
- template <typename T>
- static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- return Raw::atomic_xchg_at(new_value, base, offset);
- }
-
- template <typename T>
- static void arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
- arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
- size_t length);
-
+ public:
// Heap oop accesses. These accessors get resolved when
// IN_HEAP is set (e.g. when using the HeapAccess API), it is
// an oop_* overload, and the barrier strength is AS_NORMAL.
template <typename T>
- static oop oop_load_in_heap(T* addr) {
- // ShouldNotReachHere();
- oop value = Raw::template oop_load<oop>(addr);
- keep_alive_if_weak(decorators, value);
- return value;
- }
-
- static oop oop_load_in_heap_at(oop base, ptrdiff_t offset) {
- base = ShenandoahBarrierSet::resolve_forwarded(base);
- oop value = Raw::template oop_load_at<oop>(base, offset);
- keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value);
- return value;
- }
+ static oop oop_load_in_heap(T* addr);
+ static oop oop_load_in_heap_at(oop base, ptrdiff_t offset);
template <typename T>
- static void oop_store_in_heap(T* addr, oop value) {
- const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
- if (keep_alive) {
- ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
- }
- Raw::oop_store(addr, value);
- }
-
- static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(value);
-
- oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value);
- }
+ static void oop_store_in_heap(T* addr, oop value);
+ static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value);
template <typename T>
static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value);
-
- static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
- return oop_atomic_cmpxchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset), compare_value);
- }
+ static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value);
template <typename T>
static oop oop_atomic_xchg_in_heap(oop new_value, T* addr);
-
- static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) {
- base = ShenandoahBarrierSet::barrier_set()->write_barrier(base);
- new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
- return oop_atomic_xchg_in_heap(new_value, AccessInternal::oop_field_addr<decorators>(base, offset));
- }
+ static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset);
template <typename T>
static bool oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
@@ -268,19 +174,13 @@
// Needed for loads on non-heap weak references
template <typename T>
- static oop oop_load_not_in_heap(T* addr) {
- oop value = Raw::oop_load_not_in_heap(addr);
- keep_alive_if_weak(decorators, value);
- return value;
- }
+ static oop oop_load_not_in_heap(T* addr);
- static oop resolve(oop obj) {
- return ShenandoahBarrierSet::barrier_set()->write_barrier(obj);
- }
+ template <typename T>
+ static oop oop_atomic_cmpxchg_not_in_heap(oop new_value, T* addr, oop compare_value);
- static bool equals(oop o1, oop o2) {
- return ShenandoahBarrierSet::barrier_set()->obj_equals(o1, o2);
- }
+ template <typename T>
+ static oop oop_atomic_xchg_not_in_heap(oop new_value, T* addr);
};
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -32,12 +32,6 @@
#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
-bool ShenandoahBarrierSet::need_update_refs_barrier() {
- return _heap->is_update_refs_in_progress() ||
- _heap->is_concurrent_traversal_in_progress() ||
- (_heap->is_concurrent_mark_in_progress() && _heap->has_forwarded_objects());
-}
-
inline oop ShenandoahBarrierSet::resolve_forwarded_not_null(oop p) {
return ShenandoahBrooksPointer::forwardee(p);
}
@@ -52,7 +46,49 @@
template <DecoratorSet decorators, typename BarrierSetT>
template <typename T>
-inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) {
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(T* addr) {
+ oop value = Raw::oop_load_in_heap(addr);
+ value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(value);
+ keep_alive_if_weak(decorators, value);
+ return value;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) {
+ oop value = Raw::oop_load_in_heap_at(base, offset);
+ value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(value);
+ keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value);
+ return value;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) {
+ oop value = Raw::oop_load_not_in_heap(addr);
+ value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(value);
+ keep_alive_if_weak(decorators, value);
+ return value;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap(T* addr, oop value) {
+ ShenandoahBarrierSet::barrier_set()->storeval_barrier(value);
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive) {
+ ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
+ }
+ Raw::oop_store_in_heap(addr, value);
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) {
+ oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value);
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(oop new_value, T* addr, oop compare_value) {
oop res;
oop expected = compare_value;
do {
@@ -60,42 +96,79 @@
res = Raw::oop_atomic_cmpxchg(new_value, addr, compare_value);
expected = res;
} while ((! oopDesc::equals_raw(compare_value, expected)) && oopDesc::equals_raw(resolve_forwarded(compare_value), resolve_forwarded(expected)));
- if (oopDesc::equals_raw(expected, compare_value)) {
- const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
- if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value) &&
- ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
- ShenandoahBarrierSet::barrier_set()->enqueue(compare_value);
- }
+ if (res != NULL) {
+ return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(res);
+ } else {
+ return res;
+ }
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_impl(oop new_value, T* addr, oop compare_value) {
+ ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
+ oop result = oop_atomic_cmpxchg_not_in_heap(new_value, addr, compare_value);
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(result) &&
+ oopDesc::equals_raw(result, compare_value) &&
+ ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
+ ShenandoahBarrierSet::barrier_set()->enqueue(result);
}
- return res;
+ return result;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) {
+ oop result = oop_atomic_cmpxchg_in_heap_impl(new_value, addr, compare_value);
+ keep_alive_if_weak(decorators, result);
+ return result;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) {
+ oop result = oop_atomic_cmpxchg_in_heap_impl(new_value, AccessInternal::oop_field_addr<decorators>(base, offset), compare_value);
+ keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), result);
+ return result;
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(oop new_value, T* addr) {
+ oop previous = Raw::oop_atomic_xchg(new_value, addr);
+ if (previous != NULL) {
+ return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(previous);
+ } else {
+ return previous;
+ }
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_impl(oop new_value, T* addr) {
+ ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
+ oop result = oop_atomic_xchg_not_in_heap(new_value, addr);
+ const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+ if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(result) &&
+ ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
+ ShenandoahBarrierSet::barrier_set()->enqueue(result);
+ }
+ return result;
}
template <DecoratorSet decorators, typename BarrierSetT>
template <typename T>
inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(oop new_value, T* addr) {
- oop previous = Raw::oop_atomic_xchg(new_value, addr);
- if (ShenandoahSATBBarrier) {
- const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
- if (keep_alive && !CompressedOops::is_null(previous) &&
- ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
- ShenandoahBarrierSet::barrier_set()->enqueue(previous);
- }
- }
- return previous;
+ oop result = oop_atomic_xchg_in_heap_impl(new_value, addr);
+ keep_alive_if_weak(addr, result);
+ return result;
}
template <DecoratorSet decorators, typename BarrierSetT>
-template <typename T>
-void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
- arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
- size_t length) {
- if (!CompressedOops::is_null(src_obj)) {
- src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj));
- }
- if (!CompressedOops::is_null(dst_obj)) {
- dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj));
- }
- Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length);
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) {
+ oop result = oop_atomic_xchg_in_heap_impl(new_value, AccessInternal::oop_field_addr<decorators>(base, offset));
+ keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), result);
+ return result;
}
template <typename T>
@@ -248,8 +321,6 @@
// Clone barrier support
template <DecoratorSet decorators, typename BarrierSetT>
void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
- src = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src));
- dst = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst));
Raw::clone(src, dst, size);
ShenandoahBarrierSet::barrier_set()->write_region(MemRegion((HeapWord*) dst, size));
}
@@ -260,13 +331,6 @@
arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
size_t length) {
ShenandoahHeap* heap = ShenandoahHeap::heap();
- if (!CompressedOops::is_null(src_obj)) {
- src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj));
- }
- if (!CompressedOops::is_null(dst_obj)) {
- dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj));
- }
-
bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress();
bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
bool disjoint = HasDecorator<decorators, ARRAYCOPY_DISJOINT>::value;
@@ -274,7 +338,7 @@
if (heap->has_forwarded_objects()) {
if (heap->is_concurrent_traversal_in_progress()) {
storeval_mode = WRITE_BARRIER;
- } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
+ } else if (heap->is_update_refs_in_progress()) {
storeval_mode = READ_BARRIER;
} else {
assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -119,39 +119,6 @@
}
};
-class ShenandoahNMethodOopInitializer : public OopClosure {
-private:
- ShenandoahHeap* const _heap;
-
-public:
- ShenandoahNMethodOopInitializer() : _heap(ShenandoahHeap::heap()) {};
-
-private:
- template <class T>
- inline void do_oop_work(T* p) {
- T o = RawAccess<>::oop_load(p);
- if (! CompressedOops::is_null(o)) {
- oop obj1 = CompressedOops::decode_not_null(o);
- oop obj2 = ShenandoahBarrierSet::barrier_set()->write_barrier(obj1);
- if (! oopDesc::equals_raw(obj1, obj2)) {
- shenandoah_assert_not_in_cset(NULL, obj2);
- RawAccess<IS_NOT_NULL>::oop_store(p, obj2);
- if (_heap->is_concurrent_traversal_in_progress()) {
- ShenandoahBarrierSet::barrier_set()->enqueue(obj2);
- }
- }
- }
- }
-
-public:
- void do_oop(oop* o) {
- do_oop_work(o);
- }
- void do_oop(narrowOop* o) {
- do_oop_work(o);
- }
-};
-
ShenandoahCodeRoots::PaddedLock ShenandoahCodeRoots::_recorded_nms_lock;
GrowableArray<ShenandoahNMethod*>* ShenandoahCodeRoots::_recorded_nms;
@@ -163,21 +130,13 @@
void ShenandoahCodeRoots::add_nmethod(nmethod* nm) {
switch (ShenandoahCodeRootsStyle) {
case 0:
- case 1: {
- ShenandoahNMethodOopInitializer init;
- nm->oops_do(&init);
- nm->fix_oop_relocations();
+ case 1:
break;
- }
case 2: {
ShenandoahNMethodOopDetector detector;
nm->oops_do(&detector);
if (detector.has_oops()) {
- ShenandoahNMethodOopInitializer init;
- nm->oops_do(&init);
- nm->fix_oop_relocations();
-
ShenandoahNMethod* nmr = new ShenandoahNMethod(nm, detector.oops());
nmr->assert_alive_and_correct();
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -462,9 +462,11 @@
void ShenandoahControlThread::service_uncommit(double shrink_before) {
ShenandoahHeap* heap = ShenandoahHeap::heap();
- // Scan through the heap and determine if there is work to do. This avoids taking
- // heap lock if there is no work available, avoids spamming logs with superfluous
- // logging messages, and minimises the amount of work while locks are taken.
+ // Determine if there is work to do. This avoids taking heap lock if there is
+ // no work available, avoids spamming logs with superfluous logging messages,
+ // and minimises the amount of work while locks are taken.
+
+ if (heap->committed() <= heap->min_capacity()) return;
bool has_work = false;
for (size_t i = 0; i < heap->num_regions(); i++) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -31,8 +31,8 @@
* Provides safe handling of out-of-memory situations during evacuation.
*
* When a Java thread encounters out-of-memory while evacuating an object in a
- * write-barrier (i.e. it cannot copy the object to to-space), it does not necessarily
- * follow we can return immediately from the WB (and store to from-space).
+ * load-reference-barrier (i.e. it cannot copy the object to to-space), it does not
+ * necessarily follow we can return immediately from the LRB (and store to from-space).
*
* In very basic case, on such failure we may wait until the the evacuation is over,
* and then resolve the forwarded copy, and to the store there. This is possible
@@ -64,17 +64,17 @@
* - failure:
* - if offending value is a valid counter, then try again
* - if offending value is OOM-during-evac special value: loop until
- * counter drops to 0, then exit with read-barrier
+ * counter drops to 0, then exit with resolving the ptr
*
* Upon exit, exiting thread will decrease the counter using atomic dec.
*
* Upon OOM-during-evac, any thread will attempt to CAS OOM-during-evac
* special value into the counter. Depending on result:
- * - success: busy-loop until counter drops to zero, then exit with RB
+ * - success: busy-loop until counter drops to zero, then exit with resolve
* - failure:
* - offender is valid counter update: try again
* - offender is OOM-during-evac: busy loop until counter drops to
- * zero, then exit with RB
+ * zero, then exit with resolve
*/
class ShenandoahEvacOOMHandler {
private:
@@ -94,7 +94,7 @@
*
* When this returns true, it is safe to continue with normal evacuation.
* When this method returns false, evacuation must not be entered, and caller
- * may safely continue with a read-barrier (if Java thread).
+ * may safely continue with a simple resolve (if Java thread).
*/
void enter_evacuation();
@@ -106,7 +106,7 @@
/**
* Signal out-of-memory during evacuation. It will prevent any other threads
* from entering the evacuation path, then wait until all threads have left the
- * evacuation path, and then return. It is then safe to continue with a read-barrier.
+ * evacuation path, and then return. It is then safe to continue with a simple resolve.
*/
void handle_out_of_memory_during_evacuation();
--- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -430,7 +430,7 @@
}
// Evac reserve: reserve trailing space for evacuations
- size_t to_reserve = ShenandoahEvacReserve * _heap->capacity() / 100;
+ size_t to_reserve = ShenandoahEvacReserve * _heap->max_capacity() / 100;
size_t reserved = 0;
for (size_t idx = _heap->num_regions() - 1; idx > 0; idx--) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -141,6 +141,7 @@
//
size_t init_byte_size = collector_policy()->initial_heap_byte_size();
+ size_t min_byte_size = collector_policy()->min_heap_byte_size();
size_t max_byte_size = collector_policy()->max_heap_byte_size();
size_t heap_alignment = collector_policy()->heap_alignment();
@@ -159,8 +160,13 @@
size_t num_committed_regions = init_byte_size / reg_size_bytes;
num_committed_regions = MIN2(num_committed_regions, _num_regions);
assert(num_committed_regions <= _num_regions, "sanity");
-
_initial_size = num_committed_regions * reg_size_bytes;
+
+ size_t num_min_regions = min_byte_size / reg_size_bytes;
+ num_min_regions = MIN2(num_min_regions, _num_regions);
+ assert(num_min_regions <= _num_regions, "sanity");
+ _minimum_size = num_min_regions * reg_size_bytes;
+
_committed = _initial_size;
size_t heap_page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size();
@@ -351,8 +357,11 @@
_control_thread = new ShenandoahControlThread();
- log_info(gc, init)("Initialize Shenandoah heap with initial size " SIZE_FORMAT "%s",
- byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size));
+ log_info(gc, init)("Initialize Shenandoah heap: " SIZE_FORMAT "%s initial, " SIZE_FORMAT "%s min, " SIZE_FORMAT "%s max",
+ byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size),
+ byte_size_in_proper_unit(_minimum_size), proper_unit_for_byte_size(_minimum_size),
+ byte_size_in_proper_unit(max_capacity()), proper_unit_for_byte_size(max_capacity())
+ );
log_info(gc, init)("Safepointing mechanism: %s",
SafepointMechanism::uses_thread_local_poll() ? "thread-local poll" :
@@ -389,10 +398,6 @@
err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.",
_heuristics->name()));
}
-
- if (ShenandoahStoreValEnqueueBarrier && ShenandoahStoreValReadBarrier) {
- vm_exit_during_initialization("Cannot use both ShenandoahStoreValEnqueueBarrier and ShenandoahStoreValReadBarrier");
- }
log_info(gc, init)("Shenandoah heuristics: %s",
_heuristics->name());
} else {
@@ -506,7 +511,7 @@
void ShenandoahHeap::print_on(outputStream* st) const {
st->print_cr("Shenandoah Heap");
st->print_cr(" " SIZE_FORMAT "K total, " SIZE_FORMAT "K committed, " SIZE_FORMAT "K used",
- capacity() / K, committed() / K, used() / K);
+ max_capacity() / K, committed() / K, used() / K);
st->print_cr(" " SIZE_FORMAT " x " SIZE_FORMAT"K regions",
num_regions(), ShenandoahHeapRegion::region_size_bytes() / K);
@@ -619,13 +624,17 @@
}
size_t ShenandoahHeap::capacity() const {
- return num_regions() * ShenandoahHeapRegion::region_size_bytes();
+ return committed();
}
size_t ShenandoahHeap::max_capacity() const {
return _num_regions * ShenandoahHeapRegion::region_size_bytes();
}
+size_t ShenandoahHeap::min_capacity() const {
+ return _minimum_size;
+}
+
size_t ShenandoahHeap::initial_capacity() const {
return _initial_size;
}
@@ -639,12 +648,22 @@
void ShenandoahHeap::op_uncommit(double shrink_before) {
assert (ShenandoahUncommit, "should be enabled");
+ // Application allocates from the beginning of the heap, and GC allocates at
+ // the end of it. It is more efficient to uncommit from the end, so that applications
+ // could enjoy the near committed regions. GC allocations are much less frequent,
+ // and therefore can accept the committing costs.
+
size_t count = 0;
- for (size_t i = 0; i < num_regions(); i++) {
- ShenandoahHeapRegion* r = get_region(i);
+ for (size_t i = num_regions(); i > 0; i--) { // care about size_t underflow
+ ShenandoahHeapRegion* r = get_region(i - 1);
if (r->is_empty_committed() && (r->empty_time() < shrink_before)) {
ShenandoahHeapLocker locker(lock());
if (r->is_empty_committed()) {
+ // Do not uncommit below minimal capacity
+ if (committed() < min_capacity() + ShenandoahHeapRegion::region_size_bytes()) {
+ break;
+ }
+
r->make_uncommitted();
count++;
}
@@ -653,8 +672,6 @@
}
if (count > 0) {
- log_info(gc)("Uncommitted " SIZE_FORMAT "M. Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M committed, " SIZE_FORMAT "M used",
- count * ShenandoahHeapRegion::region_size_bytes() / M, capacity() / M, committed() / M, used() / M);
control_thread()->notify_heap_changed();
}
}
@@ -791,7 +808,7 @@
assert(req.is_gc_alloc(), "Can only accept GC allocs here");
result = allocate_memory_under_lock(req, in_new_region);
// Do not call handle_alloc_failure() here, because we cannot block.
- // The allocation failure would be handled by the WB slowpath with handle_alloc_failure_evac().
+ // The allocation failure would be handled by the LRB slowpath with handle_alloc_failure_evac().
}
if (in_new_region) {
@@ -1105,7 +1122,6 @@
ShenandoahParallelWorkerSession worker_session(worker_id);
ShenandoahEvacOOMScope oom_evac_scope;
ShenandoahEvacuateUpdateRootsClosure cl;
-
MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
_rp->process_evacuate_roots(&cl, &blobsCl, worker_id);
}
@@ -1209,7 +1225,9 @@
void ShenandoahHeap::gc_threads_do(ThreadClosure* tcl) const {
workers()->threads_do(tcl);
- _safepoint_workers->threads_do(tcl);
+ if (_safepoint_workers != NULL) {
+ _safepoint_workers->threads_do(tcl);
+ }
if (ShenandoahStringDedup::is_enabled()) {
ShenandoahStringDedup::threads_do(tcl);
}
@@ -1550,6 +1568,10 @@
if (ShenandoahPacing) {
pacer()->setup_for_evac();
}
+
+ if (ShenandoahVerify) {
+ verifier()->verify_during_evacuation();
+ }
} else {
if (ShenandoahVerify) {
verifier()->verify_after_concmark();
@@ -1800,13 +1822,13 @@
void ShenandoahHeap::stop_concurrent_marking() {
assert(is_concurrent_mark_in_progress(), "How else could we get here?");
+ set_concurrent_mark_in_progress(false);
if (!cancelled_gc()) {
// If we needed to update refs, and concurrent marking has been cancelled,
// we need to finish updating references.
set_has_forwarded_objects(false);
mark_complete_marking_context();
}
- set_concurrent_mark_in_progress(false);
}
void ShenandoahHeap::force_satb_flush_all_threads() {
@@ -1836,12 +1858,16 @@
}
void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) {
- set_gc_state_mask(MARKING, in_progress);
+ if (has_forwarded_objects()) {
+ set_gc_state_mask(MARKING | UPDATEREFS, in_progress);
+ } else {
+ set_gc_state_mask(MARKING, in_progress);
+ }
ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
}
void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
- set_gc_state_mask(TRAVERSAL | HAS_FORWARDED, in_progress);
+ set_gc_state_mask(TRAVERSAL | HAS_FORWARDED | UPDATEREFS, in_progress);
ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
}
@@ -2062,14 +2088,12 @@
}
oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) {
- o = ShenandoahBarrierSet::barrier_set()->write_barrier(o);
ShenandoahHeapLocker locker(lock());
heap_region_containing(o)->make_pinned();
return o;
}
void ShenandoahHeap::unpin_object(JavaThread* thr, oop o) {
- o = ShenandoahBarrierSet::barrier_set()->read_barrier(o);
ShenandoahHeapLocker locker(lock());
heap_region_containing(o)->make_unpinned();
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -198,6 +198,7 @@
//
private:
size_t _initial_size;
+ size_t _minimum_size;
DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
volatile size_t _used;
volatile size_t _committed;
@@ -216,6 +217,7 @@
size_t bytes_allocated_since_gc_start();
void reset_bytes_allocated_since_gc_start();
+ size_t min_capacity() const;
size_t max_capacity() const;
size_t initial_capacity() const;
size_t capacity() const;
@@ -270,16 +272,16 @@
//
public:
enum GCStateBitPos {
- // Heap has forwarded objects: need RB, ACMP, CAS barriers.
+ // Heap has forwarded objects: needs LRB barriers.
HAS_FORWARDED_BITPOS = 0,
// Heap is under marking: needs SATB barriers.
MARKING_BITPOS = 1,
- // Heap is under evacuation: needs WB barriers. (Set together with UNSTABLE)
+ // Heap is under evacuation: needs LRB barriers. (Set together with HAS_FORWARDED)
EVACUATION_BITPOS = 2,
- // Heap is under updating: needs SVRB/SVWB barriers.
+ // Heap is under updating: needs no additional barriers.
UPDATEREFS_BITPOS = 3,
// Heap is under traversal collection
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -129,7 +129,7 @@
// Once marking is done, which may have fixed up forwarded objects, we can drop it.
// Coming out of Full GC, we would not have any forwarded objects.
- // This also prevents read barrier from kicking in while adjusting pointers in phase3.
+ // This also prevents resolves with fwdptr from kicking in while adjusting pointers in phase3.
heap->set_has_forwarded_objects(false);
heap->set_full_gc_move_in_progress(true);
--- a/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -46,12 +46,12 @@
ShenandoahHeap* _heap;
public:
ShenandoahGenerationCounters(ShenandoahHeap* heap) :
- GenerationCounters("Heap", 1, 1, heap->initial_capacity(), heap->max_capacity(), heap->committed()),
+ GenerationCounters("Heap", 1, 1, heap->initial_capacity(), heap->max_capacity(), heap->capacity()),
_heap(heap)
{};
virtual void update_all() {
- _current_size->set_value(_heap->committed());
+ _current_size->set_value(_heap->capacity());
}
};
@@ -94,7 +94,7 @@
if (UsePerfData) {
ShenandoahHeap* heap = ShenandoahHeap::heap();
size_t used = heap->used();
- size_t capacity = heap->capacity();
+ size_t capacity = heap->max_capacity();
_heap_counters->update_all();
_space_counters->update_all(capacity, used);
_heap_region_counters->update();
--- a/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -34,7 +34,7 @@
enum UpdateRefsMode {
NONE, // No reference updating
- RESOLVE, // Only a read-barrier (no reference updating)
+ RESOLVE, // Only a resolve (no reference updating)
SIMPLE, // Reference updating using simple store
CONCURRENT // Reference updating using CAS
};
@@ -184,24 +184,16 @@
virtual bool do_metadata() { return true; }
};
-class ShenandoahUpdateHeapRefsSuperClosure : public BasicOopIterateClosure {
+class ShenandoahUpdateHeapRefsClosure : public BasicOopIterateClosure {
private:
ShenandoahHeap* _heap;
-public:
- ShenandoahUpdateHeapRefsSuperClosure() :
- _heap(ShenandoahHeap::heap()) {}
template <class T>
- void work(T *p);
-};
-
-class ShenandoahUpdateHeapRefsClosure : public ShenandoahUpdateHeapRefsSuperClosure {
-private:
- template <class T>
- inline void do_oop_work(T* p) { work<T>(p); }
+ void do_oop_work(T* p);
public:
- ShenandoahUpdateHeapRefsClosure() : ShenandoahUpdateHeapRefsSuperClosure() {}
+ ShenandoahUpdateHeapRefsClosure() :
+ _heap(ShenandoahHeap::heap()) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop(oop* p) { do_oop_work(p); }
--- a/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -34,7 +34,7 @@
}
template <class T>
-inline void ShenandoahUpdateHeapRefsSuperClosure::work(T* p) {
+inline void ShenandoahUpdateHeapRefsClosure::do_oop_work(T* p) {
_heap->maybe_update_with_forwarded(p);
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -153,7 +153,7 @@
void ShenandoahPacer::setup_for_idle() {
assert(ShenandoahPacing, "Only be here when pacing is enabled");
- size_t initial = _heap->capacity() * ShenandoahPacingIdleSlack / 100;
+ size_t initial = _heap->max_capacity() * ShenandoahPacingIdleSlack / 100;
double tax = 1;
restart_with(initial, tax);
@@ -166,7 +166,7 @@
if (_progress == -1) {
// First initialization, report some prior
Atomic::store((intptr_t)PACING_PROGRESS_ZERO, &_progress);
- return (size_t) (_heap->capacity() * 0.1);
+ return (size_t) (_heap->max_capacity() * 0.1);
} else {
// Record history, and reply historical data
_progress_history->add(_progress);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -242,13 +242,21 @@
_evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
_srs(n_workers),
_phase(phase),
- _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator())
+ _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
+ _par_state_string(StringTable::weak_storage())
+
{
heap->phase_timings()->record_workers_start(_phase);
+ if (ShenandoahStringDedup::is_enabled()) {
+ StringDedup::gc_prologue(false);
+ }
}
ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
delete _evacuation_tasks;
+ if (ShenandoahStringDedup::is_enabled()) {
+ StringDedup::gc_epilogue();
+ }
ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
}
@@ -270,11 +278,38 @@
_coderoots_cset_iterator.possibly_parallel_blobs_do(blobs);
}
- if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) {
+ if (ShenandoahStringDedup::is_enabled()) {
ShenandoahForwardedIsAliveClosure is_alive;
+ ShenandoahStringDedup::parallel_oops_do(&is_alive, oops, worker_id);
+ }
+
+ if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Universe_oops_do)) {
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
+ Universe::oops_do(oops);
+ }
+
+ if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Management_oops_do)) {
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
+ Management::oops_do(oops);
+ }
+
+ if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) {
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
+ JvmtiExport::oops_do(oops);
+ ShenandoahForwardedIsAliveClosure is_alive;
JvmtiExport::weak_oops_do(&is_alive, oops);
}
+
+ if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_SystemDictionary_oops_do)) {
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
+ SystemDictionary::oops_do(oops);
+ }
+
+ if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_ObjectSynchronizer_oops_do)) {
+ ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
+ ObjectSynchronizer::oops_do(oops);
+ }
+
}
uint ShenandoahRootEvacuator::n_workers() const {
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -58,7 +58,7 @@
StrongRootsScope _srs;
OopStorage::ParState<false, false> _par_state_string;
ShenandoahPhaseTimings::Phase _phase;
- ParallelCLDRootIterator _cld_iterator;
+ ParallelCLDRootIterator _cld_iterator;
ShenandoahAllCodeRootsIterator _coderoots_all_iterator;
CodeBlobClosure* _threads_nmethods_cl;
WeakProcessorPhaseTimes _weak_processor_timings;
@@ -120,11 +120,16 @@
StrongRootsScope _srs;
ShenandoahPhaseTimings::Phase _phase;
ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
+ OopStorage::ParState<false, false> _par_state_string;
enum Shenandoah_evacuate_roots_tasks {
- SHENANDOAH_EVAC_jvmti_oops_do,
- // Leave this one last.
- SHENANDOAH_EVAC_NumElements
+ SHENANDOAH_EVAC_Universe_oops_do,
+ SHENANDOAH_EVAC_ObjectSynchronizer_oops_do,
+ SHENANDOAH_EVAC_Management_oops_do,
+ SHENANDOAH_EVAC_SystemDictionary_oops_do,
+ SHENANDOAH_EVAC_jvmti_oops_do,
+ // Leave this one last.
+ SHENANDOAH_EVAC_NumElements
};
public:
ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers,
--- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -55,8 +55,8 @@
ShenandoahThreadLocalData::satb_mark_queue(thread).enqueue_known_active(orig);
JRT_END
-JRT_LEAF(oopDesc*, ShenandoahRuntime::write_barrier_JRT(oopDesc* src))
- oop result = ShenandoahBarrierSet::barrier_set()->write_barrier_mutator(src);
+JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_JRT(oopDesc* src))
+ oop result = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src);
return (oopDesc*) result;
JRT_END
--- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -37,7 +37,7 @@
static void write_ref_array_post_entry(HeapWord* dst, size_t length);
static void write_ref_field_pre_entry(oopDesc* orig, JavaThread* thread);
- static oopDesc* write_barrier_JRT(oopDesc* src);
+ static oopDesc* load_reference_barrier_JRT(oopDesc* src);
static void shenandoah_clone_barrier(oopDesc* obj);
};
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -595,11 +595,10 @@
}
if (!_heap->cancelled_gc()) {
+ fixup_roots();
if (_heap->unload_classes()) {
_heap->unload_classes_and_cleanup_tables(false);
}
-
- fixup_roots();
}
if (!_heap->cancelled_gc()) {
@@ -769,29 +768,6 @@
void do_oop(oop* p) { do_oop_work(p); }
};
-class ShenandoahTraversalWeakUpdateClosure : public OopClosure {
-private:
- template <class T>
- inline void do_oop_work(T* p) {
- // Cannot call maybe_update_with_forwarded, because on traversal-degen
- // path the collection set is already dropped. Instead, do the unguarded store.
- // TODO: This can be fixed after degen-traversal stops dropping cset.
- T o = RawAccess<>::oop_load(p);
- if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
- obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
- shenandoah_assert_marked(p, obj);
- RawAccess<IS_NOT_NULL>::oop_store(p, obj);
- }
- }
-
-public:
- ShenandoahTraversalWeakUpdateClosure() {}
-
- void do_oop(narrowOop* p) { do_oop_work(p); }
- void do_oop(oop* p) { do_oop_work(p); }
-};
-
class ShenandoahTraversalKeepAliveUpdateDegenClosure : public OopClosure {
private:
ShenandoahObjToScanQueue* _queue;
@@ -1104,16 +1080,6 @@
&pt);
}
- {
- ShenandoahGCPhase phase(phase_process);
- ShenandoahTerminationTracker termination(ShenandoahPhaseTimings::weakrefs_termination);
-
- // Process leftover weak oops (using parallel version)
- ShenandoahTraversalWeakUpdateClosure cl;
- WeakProcessor::weak_oops_do(workers, &is_alive, &cl, 1);
-
- pt.print_all_references();
-
- assert(task_queues()->is_empty() || _heap->cancelled_gc(), "Should be empty");
- }
+ pt.print_all_references();
+ assert(task_queues()->is_empty() || _heap->cancelled_gc(), "Should be empty");
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -628,6 +628,10 @@
enabled = true;
expected = ShenandoahHeap::HAS_FORWARDED;
break;
+ case _verify_gcstate_evacuation:
+ enabled = true;
+ expected = ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION;
+ break;
case _verify_gcstate_stable:
enabled = true;
expected = ShenandoahHeap::STABLE;
@@ -808,6 +812,18 @@
);
}
+void ShenandoahVerifier::verify_during_evacuation() {
+ verify_at_safepoint(
+ "During Evacuation",
+ _verify_forwarded_allow, // some forwarded references are allowed
+ _verify_marked_disable, // walk only roots
+ _verify_cset_disable, // some cset references are not forwarded yet
+ _verify_liveness_disable, // liveness data might be already stale after pre-evacs
+ _verify_regions_disable, // trash regions not yet recycled
+ _verify_gcstate_evacuation // evacuation is in progress
+ );
+}
+
void ShenandoahVerifier::verify_after_evacuation() {
verify_at_safepoint(
"After Evacuation",
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -135,6 +135,9 @@
// Nothing is in progress, some objects are forwarded
_verify_gcstate_forwarded,
+
+ // Evacuation is in progress, some objects are forwarded
+ _verify_gcstate_evacuation,
} VerifyGCState;
struct VerifyOptions {
@@ -173,6 +176,7 @@
void verify_before_concmark();
void verify_after_concmark();
void verify_before_evacuation();
+ void verify_during_evacuation();
void verify_after_evacuation();
void verify_before_updaterefs();
void verify_after_updaterefs();
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -244,7 +244,7 @@
"Time is in microseconds.") \
\
experimental(uintx, ShenandoahEvacAssist, 10, \
- "How many objects to evacuate on WB assist path. " \
+ "How many objects to evacuate on LRB assist path. " \
"Use zero to disable.") \
\
experimental(bool, ShenandoahPacing, true, \
@@ -352,27 +352,18 @@
diagnostic(bool, ShenandoahKeepAliveBarrier, true, \
"Turn on/off keep alive barriers in Shenandoah") \
\
- diagnostic(bool, ShenandoahWriteBarrier, true, \
- "Turn on/off write barriers in Shenandoah") \
- \
- diagnostic(bool, ShenandoahReadBarrier, true, \
- "Turn on/off read barriers in Shenandoah") \
- \
diagnostic(bool, ShenandoahStoreValEnqueueBarrier, false, \
"Turn on/off enqueuing of oops for storeval barriers") \
\
- diagnostic(bool, ShenandoahStoreValReadBarrier, true, \
- "Turn on/off store val read barriers in Shenandoah") \
- \
diagnostic(bool, ShenandoahCASBarrier, true, \
"Turn on/off CAS barriers in Shenandoah") \
\
- diagnostic(bool, ShenandoahAcmpBarrier, true, \
- "Turn on/off acmp barriers in Shenandoah") \
- \
diagnostic(bool, ShenandoahCloneBarrier, true, \
"Turn on/off clone barriers in Shenandoah") \
\
+ diagnostic(bool, ShenandoahLoadRefBarrier, true, \
+ "Turn on/off load-reference barriers in Shenandoah") \
+ \
diagnostic(bool, ShenandoahStoreCheck, false, \
"Emit additional code that checks objects are written to only" \
" in to-space") \
@@ -401,20 +392,13 @@
"Turn it off for maximum compatibility with reflection or JNI " \
"code that manipulates final fields.") \
\
- diagnostic(bool, ShenandoahDecreaseRegisterPressure, false, \
- "Try to reuse after-barrier values to reduce register pressure") \
- \
experimental(bool, ShenandoahCommonGCStateLoads, false, \
"Enable commonming for GC state loads in generated code.") \
\
develop(bool, ShenandoahVerifyOptoBarriers, false, \
"Verify no missing barriers in C2") \
\
- experimental(bool, ShenandoahDontIncreaseWBFreq, true, \
- "Common 2 WriteBarriers or WriteBarrier and a ReadBarrier only " \
- "if the resulting WriteBarrier isn't executed more frequently") \
- \
experimental(bool, ShenandoahLoopOptsAfterExpansion, true, \
- "Attempt more loop opts after write barrier expansion") \
+ "Attempt more loop opts after barrier expansion") \
#endif // SHARE_GC_SHENANDOAH_SHENANDOAH_GLOBALS_HPP
--- a/src/hotspot/share/interpreter/linkResolver.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -264,10 +264,6 @@
_check_access = true;
}
-char* LinkInfo::method_string() const {
- return Method::name_and_sig_as_C_string(_resolved_klass, _name, _signature);
-}
-
#ifndef PRODUCT
void LinkInfo::print() {
ResourceMark rm;
@@ -593,14 +589,12 @@
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
- "class %s tried to access %s%s%smethod %s.%s%s (%s%s%s)",
+ "class %s tried to access %s%s%smethod '%s' (%s%s%s)",
ref_klass->external_name(),
sel_method->is_abstract() ? "abstract " : "",
sel_method->is_protected() ? "protected " : "",
sel_method->is_private() ? "private " : "",
- sel_klass->external_name(),
- sel_method->name()->as_C_string(),
- sel_method->signature()->as_C_string(),
+ sel_method->external_name(),
(same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
(same_module) ? "" : "; ",
(same_module) ? "" : sel_klass->class_in_module_of_loader()
@@ -670,12 +664,11 @@
assert(target_loader_data != NULL, "resolved method's class has no class loader data");
stringStream ss;
- ss.print("loader constraint violation: when resolving %s"
- " \"%s\" the class loader %s of the current class, %s,"
+ ss.print("loader constraint violation: when resolving %s '", method_type);
+ Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
+ ss.print("' the class loader %s of the current class, %s,"
" and the class loader %s for the method's defining class, %s, have"
" different Class objects for the type %s used in the signature (%s; %s)",
- method_type,
- link_info.method_string(),
current_loader_data->loader_name_and_id(),
current_class->name()->as_C_string(),
target_loader_data->loader_name_and_id(),
@@ -739,9 +732,11 @@
// 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref
if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Method %s must be Methodref constant", link_info.method_string());
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Method '");
+ Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
+ ss.print("' must be Methodref constant");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
// 3. lookup method in resolved klass and its super klasses
@@ -764,11 +759,12 @@
// 5. method lookup failed
if (resolved_method.is_null()) {
ResourceMark rm(THREAD);
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature());
+ ss.print("'");
THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(),
- Method::name_and_sig_as_C_string(resolved_klass,
- link_info.name(),
- link_info.signature()),
- nested_exception, NULL);
+ ss.as_string(), nested_exception, NULL);
}
// 6. access checks, access checking may be turned off when calling from within the VM.
@@ -840,9 +836,11 @@
// check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref
if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Method %s must be InterfaceMethodref constant", link_info.method_string());
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Method '");
+ Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature());
+ ss.print("' must be InterfaceMethodref constant");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
// lookup method in this interface or its super, java.lang.Object
@@ -857,10 +855,11 @@
if (resolved_method.is_null()) {
// no method found
ResourceMark rm(THREAD);
- THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(),
- Method::name_and_sig_as_C_string(resolved_klass,
- link_info.name(),
- link_info.signature()));
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature());
+ ss.print("'");
+ THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string());
}
if (link_info.check_access()) {
@@ -881,11 +880,12 @@
if (code != Bytecodes::_invokestatic && resolved_method->is_static()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s",
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(), resolved_method->signature()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Expected instance not static method '");
+ Method::print_external_name(&ss, resolved_klass,
+ resolved_method->name(), resolved_method->signature());
+ ss.print("'");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
if (log_develop_is_enabled(Trace, itables)) {
@@ -1086,11 +1086,11 @@
// check if static
if (!resolved_method->is_static()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Expected static method '");
+ resolved_method()->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
return resolved_method;
}
@@ -1127,14 +1127,16 @@
if (resolved_method->name() == vmSymbols::object_initializer_name() &&
resolved_method->method_holder() != resolved_klass) {
ResourceMark rm(THREAD);
+ stringStream ss;
+ ss.print("%s: method '", resolved_klass->external_name());
+ resolved_method->signature()->print_as_signature_external_return_type(&ss);
+ ss.print(" %s(", resolved_method->name()->as_C_string());
+ resolved_method->signature()->print_as_signature_external_parameters(&ss);
+ ss.print(")' not found");
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_NoSuchMethodError(),
- "%s: method %s%s not found",
- resolved_klass->external_name(),
- resolved_method->name()->as_C_string(),
- resolved_method->signature()->as_C_string()
- );
+ "%s", ss.as_string());
return NULL;
}
@@ -1153,27 +1155,23 @@
if (!is_reflect &&
!klass_to_check->is_same_or_direct_interface(resolved_klass)) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf),
- "Interface method reference: %s, is in an indirect superinterface of %s",
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()),
- current_klass->external_name());
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Interface method reference: '");
+ resolved_method->print_external_name(&ss);
+ ss.print("', is in an indirect superinterface of %s",
+ current_klass->external_name());
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
}
// check if not static
if (resolved_method->is_static()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf),
- "Expecting non-static method %s",
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Expecting non-static method '");
+ resolved_method->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
if (log_develop_is_enabled(Trace, itables)) {
@@ -1219,10 +1217,11 @@
// check if found
if (sel_method.is_null()) {
ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()));
+ stringStream ss;
+ ss.print("'");
+ resolved_method->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
// check loader constraints if found a different method
} else if (sel_method() != resolved_method()) {
check_method_loader_constraints(link_info, sel_method, "method", CHECK);
@@ -1244,8 +1243,8 @@
char buf[500];
jio_snprintf(buf, sizeof(buf),
"Receiver class %s must be the current class or a subtype of interface %s",
- receiver_klass->name()->as_C_string(),
- sender->name()->as_C_string());
+ receiver_klass->external_name(),
+ sender->external_name());
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), buf);
}
}
@@ -1254,20 +1253,21 @@
// check if not static
if (sel_method->is_static()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Expecting non-static method '");
+ resolved_method->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
// check if abstract
if (sel_method->is_abstract()) {
ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(resolved_klass,
- sel_method->name(),
- sel_method->signature()));
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, resolved_klass, sel_method->name(), sel_method->signature());
+ ss.print("'");
+ THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
}
if (log_develop_is_enabled(Trace, itables)) {
@@ -1305,23 +1305,22 @@
// This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method
if (resolved_klass->is_interface() && resolved_method->is_private()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s",
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()),
- (current_klass == NULL ? "<NULL>" : current_klass->internal_name()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("private interface method requires invokespecial, not invokevirtual: method '");
+ resolved_method->print_external_name(&ss);
+ ss.print("', caller-class: %s",
+ (current_klass == NULL ? "<null>" : current_klass->internal_name()));
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
// check if not static
if (resolved_method->is_static()) {
ResourceMark rm(THREAD);
- char buf[200];
- jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Expecting non-static method '");
+ resolved_method->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
if (log_develop_is_enabled(Trace, vtables)) {
@@ -1470,10 +1469,11 @@
// Throw Illegal Access Error if selected_method is not public.
if (!selected_method->is_public()) {
ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
- Method::name_and_sig_as_C_string(recv_klass,
- selected_method->name(),
- selected_method->signature()));
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, recv_klass, selected_method->name(), selected_method->signature());
+ ss.print("'");
+ THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
}
// check if abstract
if (check_null_and_abstract && selected_method->is_abstract()) {
@@ -1806,19 +1806,22 @@
}
assert(resolved_method.not_null(), "Sanity");
- ss.print(" resolved method %s%s%s%s of %s %s.",
+ ss.print(" resolved method '%s%s",
resolved_method->is_abstract() ? "abstract " : "",
- resolved_method->is_private() ? "private " : "",
- resolved_method->name()->as_C_string(),
- resolved_method->signature()->as_C_string(),
+ resolved_method->is_private() ? "private " : "");
+ resolved_method->signature()->print_as_signature_external_return_type(&ss);
+ ss.print(" %s(", resolved_method->name()->as_C_string());
+ resolved_method->signature()->print_as_signature_external_parameters(&ss);
+ ss.print(")' of %s %s.",
resolved_klass->external_kind(),
resolved_klass->external_name());
if (selected_method.not_null() && !(resolved_method == selected_method)) {
- ss.print(" Selected method is %s%s%s.",
+ ss.print(" Selected method is '%s%s",
selected_method->is_abstract() ? "abstract " : "",
- selected_method->is_private() ? "private " : "",
- selected_method->name_and_sig_as_C_string());
+ selected_method->is_private() ? "private " : "");
+ selected_method->print_external_name(&ss);
+ ss.print("'.");
}
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
--- a/src/hotspot/share/interpreter/linkResolver.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/interpreter/linkResolver.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -182,7 +182,6 @@
methodHandle current_method() const { return _current_method; }
constantTag tag() const { return _tag; }
bool check_access() const { return _check_access; }
- char* method_string() const;
void print() PRODUCT_RETURN;
};
--- a/src/hotspot/share/memory/allocation.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/allocation.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -84,8 +84,14 @@
return Metaspace::allocate(loader_data, word_size, type, THREAD);
}
-bool MetaspaceObj::is_metaspace_object() const {
- return Metaspace::contains((void*)this);
+bool MetaspaceObj::is_valid(const MetaspaceObj* p) {
+ // Weed out obvious bogus values first without traversing metaspace
+ if ((size_t)p < os::min_page_size()) {
+ return false;
+ } else if (!is_aligned((address)p, sizeof(MetaWord))) {
+ return false;
+ }
+ return Metaspace::contains((void*)p);
}
void MetaspaceObj::print_address_on(outputStream* st) const {
--- a/src/hotspot/share/memory/allocation.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/allocation.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -258,12 +258,19 @@
static void* _shared_metaspace_top; // (exclusive) high address
public:
- bool is_metaspace_object() const;
- bool is_shared() const {
+
+ // Returns true if the pointer points to a valid MetaspaceObj. A valid
+ // MetaspaceObj is MetaWord-aligned and contained within either
+ // non-shared or shared metaspace.
+ static bool is_valid(const MetaspaceObj* p);
+
+ static bool is_shared(const MetaspaceObj* p) {
// If no shared metaspace regions are mapped, _shared_metaspace_{base,top} will
// both be NULL and all values of p will be rejected quickly.
- return (((void*)this) < _shared_metaspace_top && ((void*)this) >= _shared_metaspace_base);
+ return (((void*)p) < _shared_metaspace_top && ((void*)p) >= _shared_metaspace_base);
}
+ bool is_shared() const { return MetaspaceObj::is_shared(this); }
+
void print_address_on(outputStream* st) const; // nonvirtual address printing
static void set_shared_metaspace_range(void* base, void* top) {
--- a/src/hotspot/share/memory/heapShared.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/heapShared.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -69,6 +69,7 @@
{"java/lang/Short$ShortCache", "archivedCache"},
{"java/lang/Character$CharacterCache", "archivedCache"},
{"java/util/jar/Attributes$Name", "KNOWN_NAMES"},
+ {"sun/util/locale/BaseLocale", "constantBaseLocales"},
};
// Entry fields for subgraphs archived in the open archive heap region.
static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = {
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -92,9 +92,9 @@
assert_lock_strong(MetaspaceExpand_lock);
// Don't use a VirtualSpaceListIterator because this
// list is being changed and a straightforward use of an iterator is not safe.
- VirtualSpaceNode* purged_vsl = NULL;
VirtualSpaceNode* prev_vsl = virtual_space_list();
VirtualSpaceNode* next_vsl = prev_vsl;
+ int num_purged_nodes = 0;
while (next_vsl != NULL) {
VirtualSpaceNode* vsl = next_vsl;
DEBUG_ONLY(vsl->verify(false);)
@@ -118,20 +118,17 @@
dec_reserved_words(vsl->reserved_words());
dec_committed_words(vsl->committed_words());
dec_virtual_space_count();
- purged_vsl = vsl;
delete vsl;
+ num_purged_nodes ++;
} else {
prev_vsl = vsl;
}
}
+
+ // Verify list
#ifdef ASSERT
- if (purged_vsl != NULL) {
- // List should be stable enough to use an iterator here.
- VirtualSpaceListIterator iter(virtual_space_list());
- while (iter.repeat()) {
- VirtualSpaceNode* vsl = iter.get_next();
- assert(vsl != purged_vsl, "Purge of vsl failed");
- }
+ if (num_purged_nodes > 0) {
+ verify(false);
}
#endif
}
@@ -143,11 +140,13 @@
VirtualSpaceNode* VirtualSpaceList::find_enclosing_space(const void* ptr) {
// List should be stable enough to use an iterator here because removing virtual
// space nodes is only allowed at a safepoint.
- VirtualSpaceListIterator iter(virtual_space_list());
- while (iter.repeat()) {
- VirtualSpaceNode* vsn = iter.get_next();
- if (vsn->contains(ptr)) {
- return vsn;
+ if (is_within_envelope((address)ptr)) {
+ VirtualSpaceListIterator iter(virtual_space_list());
+ while (iter.repeat()) {
+ VirtualSpaceNode* vsn = iter.get_next();
+ if (vsn->contains(ptr)) {
+ return vsn;
+ }
}
}
return NULL;
@@ -170,7 +169,9 @@
_is_class(false),
_reserved_words(0),
_committed_words(0),
- _virtual_space_count(0) {
+ _virtual_space_count(0),
+ _envelope_lo((address)max_uintx),
+ _envelope_hi(NULL) {
MutexLockerEx cl(MetaspaceExpand_lock,
Mutex::_no_safepoint_check_flag);
create_new_virtual_space(word_size);
@@ -182,12 +183,17 @@
_is_class(true),
_reserved_words(0),
_committed_words(0),
- _virtual_space_count(0) {
+ _virtual_space_count(0),
+ _envelope_lo((address)max_uintx),
+ _envelope_hi(NULL) {
MutexLockerEx cl(MetaspaceExpand_lock,
Mutex::_no_safepoint_check_flag);
VirtualSpaceNode* class_entry = new VirtualSpaceNode(is_class(), rs);
bool succeeded = class_entry->initialize();
if (succeeded) {
+ expand_envelope_to_include_node(class_entry);
+ // ensure lock-free iteration sees fully initialized node
+ OrderAccess::storestore();
link_vs(class_entry);
}
}
@@ -224,12 +230,16 @@
} else {
assert(new_entry->reserved_words() == vs_word_size,
"Reserved memory size differs from requested memory size");
+ expand_envelope_to_include_node(new_entry);
// ensure lock-free iteration sees fully initialized node
OrderAccess::storestore();
link_vs(new_entry);
DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_vsnodes_created));
return true;
}
+
+ DEBUG_ONLY(verify(false);)
+
}
void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) {
@@ -399,5 +409,41 @@
}
}
+// Given a node, expand range such that it includes the node.
+void VirtualSpaceList::expand_envelope_to_include_node(const VirtualSpaceNode* node) {
+ _envelope_lo = MIN2(_envelope_lo, (address)node->low_boundary());
+ _envelope_hi = MAX2(_envelope_hi, (address)node->high_boundary());
+}
+
+
+#ifdef ASSERT
+void VirtualSpaceList::verify(bool slow) {
+ VirtualSpaceNode* list = virtual_space_list();
+ VirtualSpaceListIterator iter(list);
+ size_t reserved = 0;
+ size_t committed = 0;
+ size_t node_count = 0;
+ while (iter.repeat()) {
+ VirtualSpaceNode* node = iter.get_next();
+ if (slow) {
+ node->verify(true);
+ }
+ // Check that the node resides fully within our envelope.
+ assert((address)node->low_boundary() >= _envelope_lo && (address)node->high_boundary() <= _envelope_hi,
+ "Node " SIZE_FORMAT " [" PTR_FORMAT ", " PTR_FORMAT ") outside envelope [" PTR_FORMAT ", " PTR_FORMAT ").",
+ node_count, p2i(node->low_boundary()), p2i(node->high_boundary()), p2i(_envelope_lo), p2i(_envelope_hi));
+ reserved += node->reserved_words();
+ committed += node->committed_words();
+ node_count ++;
+ }
+ assert(reserved == reserved_words() && committed == committed_words() && node_count == _virtual_space_count,
+ "Mismatch: reserved real: " SIZE_FORMAT " expected: " SIZE_FORMAT
+ ", committed real: " SIZE_FORMAT " expected: " SIZE_FORMAT
+ ", node count real: " SIZE_FORMAT " expected: " SIZE_FORMAT ".",
+ reserved, reserved_words(), committed, committed_words(),
+ node_count, _virtual_space_count);
+}
+#endif // ASSERT
+
} // namespace metaspace
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -58,6 +58,19 @@
// Number of virtual spaces
size_t _virtual_space_count;
+ // Optimization: we keep an address range to quickly exclude pointers
+ // which are clearly not pointing into metaspace. This is an optimization for
+ // VirtualSpaceList::contains().
+ address _envelope_lo;
+ address _envelope_hi;
+
+ bool is_within_envelope(address p) const {
+ return p >= _envelope_lo && p < _envelope_hi;
+ }
+
+ // Given a node, expand range such that it includes the node.
+ void expand_envelope_to_include_node(const VirtualSpaceNode* node);
+
~VirtualSpaceList();
VirtualSpaceNode* virtual_space_list() const { return _virtual_space_list; }
@@ -80,6 +93,8 @@
// virtual space and add the chunks to the free list.
void retire_current_virtual_space();
+ DEBUG_ONLY(bool contains_node(const VirtualSpaceNode* node) const;)
+
public:
VirtualSpaceList(size_t word_size);
VirtualSpaceList(ReservedSpace rs);
@@ -126,6 +141,8 @@
void print_on(outputStream* st, size_t scale) const;
void print_map(outputStream* st) const;
+ DEBUG_ONLY(void verify(bool slow);)
+
class VirtualSpaceListIterator : public StackObj {
VirtualSpaceNode* _virtual_spaces;
public:
--- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -60,6 +60,8 @@
// Convenience functions to access the _virtual_space
char* low() const { return virtual_space()->low(); }
char* high() const { return virtual_space()->high(); }
+ char* low_boundary() const { return virtual_space()->low_boundary(); }
+ char* high_boundary() const { return virtual_space()->high_boundary(); }
// The first Metachunk will be allocated at the bottom of the
// VirtualSpace
--- a/src/hotspot/share/oops/constantPool.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/constantPool.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1000,14 +1000,17 @@
if ((callee->is_interface() && m_tag.is_method()) ||
((!callee->is_interface() && m_tag.is_interface_method()))) {
ResourceMark rm(THREAD);
- char buf[400];
- jio_snprintf(buf, sizeof(buf),
- "Inconsistent constant pool data in classfile for class %s. "
- "Method %s%s at index %d is %s and should be %s",
- callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index,
- callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
- callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ stringStream ss;
+ ss.print("Inconsistent constant pool data in classfile for class %s. "
+ "Method '", callee->name()->as_C_string());
+ signature->print_as_signature_external_return_type(&ss);
+ ss.print(" %s(", name->as_C_string());
+ signature->print_as_signature_external_parameters(&ss);
+ ss.print(")' at index %d is %s and should be %s",
+ index,
+ callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
+ callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
Klass* klass = this_cp->pool_holder();
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/instanceKlass.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -3104,7 +3104,7 @@
for (int i = 0; i < len; i++) {
intptr_t e = start[i];
st->print("%d : " INTPTR_FORMAT, i, e);
- if (e != 0 && ((Metadata*)e)->is_metaspace_object()) {
+ if (MetaspaceObj::is_valid((Metadata*)e)) {
st->print(" ");
((Metadata*)e)->print_value_on(st);
}
--- a/src/hotspot/share/oops/klassVtable.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/klassVtable.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -500,11 +500,11 @@
if (failed_type_symbol != NULL) {
stringStream ss;
ss.print("loader constraint violation for class %s: when selecting "
- "overriding method %s the class loader %s of the "
+ "overriding method '", klass->external_name());
+ target_method()->print_external_name(&ss),
+ ss.print("' the class loader %s of the "
"selected method's type %s, and the class loader %s for its super "
"type %s have different Class objects for the type %s used in the signature (%s; %s)",
- klass->external_name(),
- target_method()->name_and_sig_as_C_string(),
target_klass->class_loader_data()->loader_name_and_id(),
target_klass->external_name(),
super_klass->class_loader_data()->loader_name_and_id(),
@@ -1227,15 +1227,16 @@
if (failed_type_symbol != NULL) {
stringStream ss;
ss.print("loader constraint violation in interface itable"
- " initialization for class %s: when selecting method %s the"
- " class loader %s for super interface %s, and the class"
- " loader %s of the selected method's type, %s have"
+ " initialization for class %s: when selecting method '",
+ _klass->external_name());
+ m->print_external_name(&ss),
+ ss.print("' the class loader %s for super interface %s, and the class"
+ " loader %s of the selected method's %s, %s have"
" different Class objects for the type %s used in the signature (%s; %s)",
- _klass->external_name(),
- m->name_and_sig_as_C_string(),
interf->class_loader_data()->loader_name_and_id(),
interf->external_name(),
target()->method_holder()->class_loader_data()->loader_name_and_id(),
+ target()->method_holder()->external_kind(),
target()->method_holder()->external_name(),
failed_type_symbol->as_klass_external_name(),
interf->class_in_module_of_loader(false, true),
--- a/src/hotspot/share/oops/method.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/method.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -178,6 +178,27 @@
return buf;
}
+const char* Method::external_name() const {
+ return external_name(constants()->pool_holder(), name(), signature());
+}
+
+void Method::print_external_name(outputStream *os) const {
+ print_external_name(os, constants()->pool_holder(), name(), signature());
+}
+
+const char* Method::external_name(Klass* klass, Symbol* method_name, Symbol* signature) {
+ stringStream ss;
+ print_external_name(&ss, klass, method_name, signature);
+ return ss.as_string();
+}
+
+void Method::print_external_name(outputStream *os, Klass* klass, Symbol* method_name, Symbol* signature) {
+ signature->print_as_signature_external_return_type(os);
+ os->print(" %s.%s(", klass->external_name(), method_name->as_C_string());
+ signature->print_as_signature_external_parameters(os);
+ os->print(")");
+}
+
int Method::fast_exception_handler_bci_for(const methodHandle& mh, Klass* ex_klass, int throw_bci, TRAPS) {
// exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index)
// access exception table
--- a/src/hotspot/share/oops/method.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/method.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -180,8 +180,8 @@
}
// Helper routine: get klass name + "." + method name + signature as
- // C string, for the purpose of providing more useful NoSuchMethodErrors
- // and fatal error handling. The string is allocated in resource
+ // C string, for the purpose of providing more useful
+ // fatal error handling. The string is allocated in resource
// area if a buffer is not provided by the caller.
char* name_and_sig_as_C_string() const;
char* name_and_sig_as_C_string(char* buf, int size) const;
@@ -190,6 +190,18 @@
static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature);
static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size);
+ // Get return type + klass name + "." + method name + ( parameters types )
+ // as a C string or print it to an outputStream.
+ // This is to be used to assemble strings passed to Java, so that
+ // the text more resembles Java code. Used in exception messages.
+ // Memory is allocated in the resource area; the caller needs
+ // a ResourceMark.
+ const char* external_name() const;
+ void print_external_name(outputStream *os) const;
+
+ static const char* external_name( Klass* klass, Symbol* method_name, Symbol* signature);
+ static void print_external_name(outputStream *os, Klass* klass, Symbol* method_name, Symbol* signature);
+
Bytecodes::Code java_code_at(int bci) const {
return Bytecodes::java_code_at(this, bcp_from(bci));
}
--- a/src/hotspot/share/oops/symbol.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/symbol.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -200,6 +200,66 @@
return str;
}
+static void print_class(outputStream *os, char *class_str, int len) {
+ for (int i = 0; i < len; ++i) {
+ if (class_str[i] == '/') {
+ os->put('.');
+ } else {
+ os->put(class_str[i]);
+ }
+ }
+}
+
+static void print_array(outputStream *os, char *array_str, int len) {
+ int dimensions = 0;
+ for (int i = 0; i < len; ++i) {
+ if (array_str[i] == '[') {
+ dimensions++;
+ } else if (array_str[i] == 'L') {
+ // Expected format: L<type name>;. Skip 'L' and ';' delimiting the type name.
+ print_class(os, array_str+i+1, len-i-2);
+ break;
+ } else {
+ os->print("%s", type2name(char2type(array_str[i])));
+ }
+ }
+ for (int i = 0; i < dimensions; ++i) {
+ os->print("[]");
+ }
+}
+
+void Symbol::print_as_signature_external_return_type(outputStream *os) {
+ for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
+ if (ss.at_return_type()) {
+ if (ss.is_array()) {
+ print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
+ } else if (ss.is_object()) {
+ // Expected format: L<type name>;. Skip 'L' and ';' delimiting the class name.
+ print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
+ } else {
+ os->print("%s", type2name(ss.type()));
+ }
+ }
+ }
+}
+
+void Symbol::print_as_signature_external_parameters(outputStream *os) {
+ bool first = true;
+ for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
+ if (ss.at_return_type()) break;
+ if (!first) { os->print(", "); }
+ if (ss.is_array()) {
+ print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
+ } else if (ss.is_object()) {
+ // Skip 'L' and ';'.
+ print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
+ } else {
+ os->print("%s", type2name(ss.type()));
+ }
+ first = false;
+ }
+}
+
// Increment refcount while checking for zero. If the Symbol's refcount becomes zero
// a thread could be concurrently removing the Symbol. This is used during SymbolTable
// lookup to avoid reviving a dead Symbol.
--- a/src/hotspot/share/oops/symbol.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/oops/symbol.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -229,6 +229,15 @@
const char* as_klass_external_name() const;
const char* as_klass_external_name(char* buf, int size) const;
+ // Treating the symbol as a signature, print the return
+ // type to the outputStream. Prints external names as 'double' or
+ // 'java.lang.Object[][]'.
+ void print_as_signature_external_return_type(outputStream *os);
+ // Treating the symbol as a signature, print the parameter types
+ // seperated by ', ' to the outputStream. Prints external names as
+ // 'double' or 'java.lang.Object[][]'.
+ void print_as_signature_external_parameters(outputStream *os);
+
void metaspace_pointers_do(MetaspaceClosure* it);
MetaspaceObj::Type type() const { return SymbolType; }
--- a/src/hotspot/share/opto/classes.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/classes.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -281,9 +281,7 @@
shmacro(ShenandoahWeakCompareAndSwapN)
shmacro(ShenandoahWeakCompareAndSwapP)
shmacro(ShenandoahEnqueueBarrier)
-shmacro(ShenandoahReadBarrier)
-shmacro(ShenandoahWriteBarrier)
-shmacro(ShenandoahWBMemProj)
+shmacro(ShenandoahLoadReferenceBarrier)
macro(SCMemProj)
macro(SqrtD)
macro(SqrtF)
--- a/src/hotspot/share/opto/compile.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/compile.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -3070,7 +3070,7 @@
Node *m = wq.at(next);
for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) {
Node* use = m->fast_out(i);
- if (use->is_Mem() || use->is_EncodeNarrowPtr() || use->is_ShenandoahBarrier()) {
+ if (use->is_Mem() || use->is_EncodeNarrowPtr()) {
use->ensure_control_or_add_prec(n->in(0));
} else {
switch(use->Opcode()) {
--- a/src/hotspot/share/opto/lcm.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/lcm.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -178,7 +178,6 @@
case Op_LoadRange:
case Op_LoadD_unaligned:
case Op_LoadL_unaligned:
- case Op_ShenandoahReadBarrier:
assert(mach->in(2) == val, "should be address");
break;
case Op_StoreB:
--- a/src/hotspot/share/opto/library_call.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/library_call.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -4485,7 +4485,7 @@
for (MergeMemStream mms(merged_memory(), mem->as_MergeMem()); mms.next_non_empty2(); ) {
Node* n = mms.memory();
if (n != mms.memory2() && !(n->is_Proj() && n->in(0) == alloc->initialization())) {
- assert(n->is_Store() || n->Opcode() == Op_ShenandoahWBMemProj, "what else?");
+ assert(n->is_Store(), "what else?");
no_interfering_store = false;
break;
}
@@ -4494,7 +4494,7 @@
for (MergeMemStream mms(merged_memory()); mms.next_non_empty(); ) {
Node* n = mms.memory();
if (n != mem && !(n->is_Proj() && n->in(0) == alloc->initialization())) {
- assert(n->is_Store() || n->Opcode() == Op_ShenandoahWBMemProj, "what else?");
+ assert(n->is_Store(), "what else?");
no_interfering_store = false;
break;
}
--- a/src/hotspot/share/opto/loopPredicate.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/loopPredicate.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -536,9 +536,6 @@
if (_lpt->is_invariant(n)) { // known invariant
_invariant.set(n->_idx);
} else if (!n->is_CFG()) {
- if (n->Opcode() == Op_ShenandoahWriteBarrier) {
- return;
- }
Node *n_ctrl = _phase->ctrl_or_self(n);
Node *u_ctrl = _phase->ctrl_or_self(use); // self if use is a CFG
if (_phase->is_dominator(n_ctrl, u_ctrl)) {
--- a/src/hotspot/share/opto/loopnode.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/loopnode.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -3971,7 +3971,7 @@
}
while(worklist.size() != 0 && LCA != early) {
Node* s = worklist.pop();
- if (s->is_Load() || s->is_ShenandoahBarrier() || s->Opcode() == Op_SafePoint ||
+ if (s->is_Load() || s->Opcode() == Op_SafePoint ||
(s->is_CallStaticJava() && s->as_CallStaticJava()->uncommon_trap_request() != 0)) {
continue;
} else if (s->is_MergeMem()) {
--- a/src/hotspot/share/opto/loopnode.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/loopnode.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -38,8 +38,6 @@
class LoopNode;
class Node;
class OuterStripMinedLoopEndNode;
-class ShenandoahBarrierNode;
-class ShenandoahWriteBarrierNode;
class PathFrequency;
class PhaseIdealLoop;
class CountedLoopReserveKit;
@@ -638,8 +636,7 @@
friend class IdealLoopTree;
friend class SuperWord;
friend class CountedLoopReserveKit;
- friend class ShenandoahBarrierNode;
- friend class ShenandoahWriteBarrierNode;
+ friend class ShenandoahBarrierC2Support;
// Pre-computed def-use info
PhaseIterGVN &_igvn;
--- a/src/hotspot/share/opto/loopopts.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/loopopts.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1082,11 +1082,6 @@
Node* m = n->fast_out(j);
if (m->is_FastLock())
return false;
-#if INCLUDE_SHENANDOAHGC
- if (m->is_ShenandoahBarrier() && m->has_out_with(Op_FastLock)) {
- return false;
- }
-#endif
#ifdef _LP64
if (m->Opcode() == Op_ConvI2L)
return false;
@@ -3210,7 +3205,7 @@
// if not pinned and not a load (which maybe anti-dependent on a store)
// and not a CMove (Matcher expects only bool->cmove).
- if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove() && n->Opcode() != Op_ShenandoahWBMemProj) {
+ if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove()) {
cloned_for_outside_use += clone_for_use_outside_loop( loop, n, worklist );
sink_list.push(n);
peel >>= n->_idx; // delete n from peel set.
--- a/src/hotspot/share/opto/node.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/opto/node.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -142,7 +142,6 @@
class RootNode;
class SafePointNode;
class SafePointScalarObjectNode;
-class ShenandoahBarrierNode;
class StartNode;
class State;
class StoreNode;
@@ -676,7 +675,6 @@
DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6)
DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0)
DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1)
- DEFINE_CLASS_ID(ShenandoahBarrier, Type, 7)
DEFINE_CLASS_ID(Proj, Node, 3)
DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -875,7 +873,6 @@
DEFINE_CLASS_QUERY(Root)
DEFINE_CLASS_QUERY(SafePoint)
DEFINE_CLASS_QUERY(SafePointScalarObject)
- DEFINE_CLASS_QUERY(ShenandoahBarrier)
DEFINE_CLASS_QUERY(Start)
DEFINE_CLASS_QUERY(Store)
DEFINE_CLASS_QUERY(Sub)
--- a/src/hotspot/share/prims/jni.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/jni.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -2955,8 +2955,9 @@
if (method == NULL) {
ResourceMark rm;
stringStream st;
- st.print("Method %s name or signature does not match",
- Method::name_and_sig_as_C_string(k, name, signature));
+ st.print("Method '");
+ Method::print_external_name(&st, k, name, signature);
+ st.print("' name or signature does not match");
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
}
if (!method->is_native()) {
@@ -2965,8 +2966,9 @@
if (method == NULL) {
ResourceMark rm;
stringStream st;
- st.print("Method %s is not declared as native",
- Method::name_and_sig_as_C_string(k, name, signature));
+ st.print("Method '");
+ Method::print_external_name(&st, k, name, signature);
+ st.print("' is not declared as native");
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
}
}
@@ -4166,7 +4168,7 @@
if (attach_failed) {
// Added missing cleanup
- thread->cleanup_failed_attach_current_thread();
+ thread->cleanup_failed_attach_current_thread(daemon);
return JNI_ERR;
}
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -167,7 +167,12 @@
RawMonitor_lock->unlock() ;
if (w != NULL) {
guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+ // Once we set TState to TS_RUN the waiting thread can complete
+ // SimpleEnter and 'w' is pointing into random stack space. So we have
+ // to ensure we extract the ParkEvent (which is in type-stable memory)
+ // before we set the state, and then don't access 'w'.
ParkEvent * ev = w->_event ;
+ OrderAccess::loadstore();
w->TState = ObjectWaiter::TS_RUN ;
OrderAccess::fence() ;
ev->unpark() ;
@@ -200,7 +205,7 @@
// If thread still resides on the waitset then unlink it.
// Double-checked locking -- the usage is safe in this context
- // as we TState is volatile and the lock-unlock operators are
+ // as TState is volatile and the lock-unlock operators are
// serializing (barrier-equivalent).
if (Node.TState == ObjectWaiter::TS_WAIT) {
--- a/src/hotspot/share/prims/nativeLookup.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/nativeLookup.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -380,8 +380,11 @@
if (entry != NULL) return entry;
// Native function not found, throw UnsatisfiedLinkError
- THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(),
- method->name_and_sig_as_C_string());
+ stringStream ss;
+ ss.print("'");
+ method->print_external_name(&ss);
+ ss.print("'");
+ THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string());
}
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -126,17 +126,14 @@
Method* method = m();
// Check if method has been redefined while taking out ResolvedMethodTable_lock, if so
- // use new method. The old method won't be deallocated because it's passed in as a Handle.
+ // use new method in the ResolvedMethodName. The old method won't be deallocated
+ // yet because it's passed in as a Handle.
if (method->is_old()) {
- // Replace method with redefined version
- InstanceKlass* holder = method->method_holder();
- method = holder->method_with_idnum(method->method_idnum());
- if (method == NULL) {
- // Replace deleted method with NSME.
- method = Universe::throw_no_such_method_error();
- }
+ method = (method->is_deleted()) ? Universe::throw_no_such_method_error() :
+ method->get_new_method();
java_lang_invoke_ResolvedMethodName::set_vmtarget(resolved_method_name(), method);
}
+
// Set flag in class to indicate this InstanceKlass has entries in the table
// to avoid walking table during redefinition if none of the redefined classes
// have any membernames in the table.
--- a/src/hotspot/share/prims/stackwalk.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/stackwalk.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -151,8 +151,8 @@
index == start_index && method->caller_sensitive()) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
- err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
- method->name_and_sig_as_C_string()));
+ err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method",
+ method->external_name()));
}
// fill in StackFrameInfo and initialize MemberName
stream.fill_frame(index, frames_array, method, CHECK_0);
--- a/src/hotspot/share/prims/unsafe.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/prims/unsafe.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -292,18 +292,6 @@
return JNIHandles::make_local(env, v);
} UNSAFE_END
-UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) {
-#ifdef VM_LITTLE_ENDIAN
- return false;
-#else
- return true;
-#endif
-} UNSAFE_END
-
-UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) {
- return UseUnalignedAccesses;
-} UNSAFE_END
-
#define DEFINE_GETSETOOP(java_type, Type) \
\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
@@ -446,14 +434,6 @@
////// Random queries
-UNSAFE_LEAF(jint, Unsafe_AddressSize0(JNIEnv *env, jobject unsafe)) {
- return sizeof(void*);
-} UNSAFE_END
-
-UNSAFE_LEAF(jint, Unsafe_PageSize()) {
- return os::vm_page_size();
-} UNSAFE_END
-
static jlong find_field_offset(jclass clazz, jstring name, TRAPS) {
assert(clazz != NULL, "clazz must not be NULL");
assert(name != NULL, "name must not be NULL");
@@ -1073,8 +1053,6 @@
{CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)},
{CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)},
{CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)},
- {CC "addressSize0", CC "()I", FN_PTR(Unsafe_AddressSize0)},
- {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)},
{CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)},
{CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
@@ -1102,9 +1080,6 @@
{CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)},
{CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)},
{CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)},
-
- {CC "isBigEndian0", CC "()Z", FN_PTR(Unsafe_isBigEndian0)},
- {CC "unalignedAccess0", CC "()Z", FN_PTR(Unsafe_unalignedAccess0)}
};
#undef CC
--- a/src/hotspot/share/runtime/init.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/runtime/init.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -122,6 +122,7 @@
accessFlags_init();
templateTable_init();
InterfaceSupport_init();
+ VMRegImpl::set_regName(); // need this before generate_stubs (for printing oop maps).
SharedRuntime::generate_stubs();
universe2_init(); // dependent on codeCache_init and stubRoutines_init1
javaClasses_init();// must happen after vtable initialization, before referenceProcessor_init
@@ -139,7 +140,6 @@
if (!compileBroker_init()) {
return JNI_EINVAL;
}
- VMRegImpl::set_regName();
if (!universe_post_init()) {
return JNI_ERR;
--- a/src/hotspot/share/runtime/os.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/runtime/os.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1024,8 +1024,9 @@
}
bool os::is_readable_range(const void* from, const void* to) {
- for (address p = align_down((address)from, min_page_size()); p < to; p += min_page_size()) {
- if (!is_readable_pointer(p)) {
+ if ((uintptr_t)from >= (uintptr_t)to) return false;
+ for (uintptr_t p = align_down((uintptr_t)from, min_page_size()); p < (uintptr_t)to; p += min_page_size()) {
+ if (!is_readable_pointer((const void*)p)) {
return false;
}
}
--- a/src/hotspot/share/runtime/reflection.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/runtime/reflection.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1085,11 +1085,12 @@
if (method->is_abstract()) {
// new default: 6531596
ResourceMark rm(THREAD);
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, target_klass, method->name(), method->signature());
+ ss.print("'");
Handle h_origexception = Exceptions::new_exception(THREAD,
- vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(target_klass,
- method->name(),
- method->signature()));
+ vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
JavaCallArguments args(h_origexception);
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
vmSymbols::throwable_void_signature(),
@@ -1104,10 +1105,13 @@
// an internal vtable bug. If you ever get this please let Karen know.
if (method.is_null()) {
ResourceMark rm(THREAD);
- THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
- Method::name_and_sig_as_C_string(klass,
- reflected_method->name(),
- reflected_method->signature()));
+ stringStream ss;
+ ss.print("'");
+ Method::print_external_name(&ss, klass,
+ reflected_method->name(),
+ reflected_method->signature());
+ ss.print("'");
+ THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string());
}
assert(ptypes->is_objArray(), "just checking");
--- a/src/hotspot/share/runtime/thread.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/runtime/thread.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -2021,6 +2021,10 @@
_timer_exit_phase1.stop();
_timer_exit_phase2.start();
}
+
+ // Capture daemon status before the thread is marked as terminated.
+ bool daemon = is_daemon(threadObj());
+
// Notify waiters on thread object. This has to be done after exit() is called
// on the thread (if the thread is the last thread in a daemon ThreadGroup the
// group should have the destroyed bit set before waiters are notified).
@@ -2089,7 +2093,7 @@
_timer_exit_phase4.start();
}
// Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
- Threads::remove(this);
+ Threads::remove(this, daemon);
if (log_is_enabled(Debug, os, thread, timer)) {
_timer_exit_phase4.stop();
@@ -2107,7 +2111,7 @@
}
}
-void JavaThread::cleanup_failed_attach_current_thread() {
+void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) {
if (active_handles() != NULL) {
JNIHandleBlock* block = active_handles();
set_active_handles(NULL);
@@ -2129,7 +2133,7 @@
BarrierSet::barrier_set()->on_thread_detach(this);
- Threads::remove(this);
+ Threads::remove(this, is_daemon);
this->smr_delete();
}
@@ -3624,6 +3628,7 @@
initialize_class(vmSymbols::java_lang_Thread(), CHECK);
oop thread_object = create_initial_thread(thread_group, main_thread, CHECK);
main_thread->set_threadObj(thread_object);
+
// Set thread status to running since main thread has
// been started and running.
java_lang_Thread::set_thread_status(thread_object,
@@ -3632,6 +3637,15 @@
// The VM creates objects of this class.
initialize_class(vmSymbols::java_lang_Module(), CHECK);
+#ifdef ASSERT
+ InstanceKlass *k = SystemDictionary::UnsafeConstants_klass();
+ assert(k->is_not_initialized(), "UnsafeConstants should not already be initialized");
+#endif
+
+ // initialize the hardware-specific constants needed by Unsafe
+ initialize_class(vmSymbols::jdk_internal_misc_UnsafeConstants(), CHECK);
+ jdk_internal_misc_UnsafeConstants::set_unsafe_constants();
+
// The VM preresolves methods to these classes. Make sure that they get initialized
initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK);
initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK);
@@ -4455,7 +4469,7 @@
Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p));
}
-void Threads::remove(JavaThread* p) {
+void Threads::remove(JavaThread* p, bool is_daemon) {
// Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread.
ObjectSynchronizer::omFlush(p);
@@ -4484,11 +4498,8 @@
}
_number_of_threads--;
- oop threadObj = p->threadObj();
- bool daemon = true;
- if (!is_daemon(threadObj)) {
+ if (!is_daemon) {
_number_of_non_daemon_threads--;
- daemon = false;
// Only one thread left, do a notify on the Threads_lock so a thread waiting
// on destroy_vm will wake up.
@@ -4496,7 +4507,7 @@
Threads_lock->notify_all();
}
}
- ThreadService::remove_thread(p, daemon);
+ ThreadService::remove_thread(p, is_daemon);
// Make sure that safepoint code disregard this thread. This is needed since
// the thread might mess around with locks after this point. This can cause it
--- a/src/hotspot/share/runtime/thread.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/runtime/thread.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -1242,7 +1242,7 @@
};
void exit(bool destroy_vm, ExitType exit_type = normal_exit);
- void cleanup_failed_attach_current_thread();
+ void cleanup_failed_attach_current_thread(bool is_daemon);
// Testers
virtual bool is_Java_thread() const { return true; }
@@ -2235,7 +2235,7 @@
// force_daemon is a concession to JNI, where we may need to add a
// thread to the thread list before allocating its thread object
static void add(JavaThread* p, bool force_daemon = false);
- static void remove(JavaThread* p);
+ static void remove(JavaThread* p, bool is_daemon);
static void non_java_threads_do(ThreadClosure* tc);
static void java_threads_do(ThreadClosure* tc);
static void java_threads_and_vm_thread_do(ThreadClosure* tc);
--- a/src/hotspot/share/utilities/hashtable.cpp Wed Apr 10 10:32:43 2019 +0530
+++ b/src/hotspot/share/utilities/hashtable.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -129,7 +129,7 @@
}
}
-static int literal_size(ClassLoaderWeakHandle v) {
+static int literal_size(WeakHandle<vm_class_loader_data> v) {
return literal_size(v.peek());
}
@@ -244,7 +244,7 @@
l->print();
}
-static void print_literal(ClassLoaderWeakHandle l) {
+static void print_literal(WeakHandle<vm_class_loader_data> l) {
l.print();
}
@@ -308,15 +308,14 @@
template class Hashtable<Symbol*, mtSymbol>;
template class Hashtable<Klass*, mtClass>;
template class Hashtable<InstanceKlass*, mtClass>;
-template class Hashtable<ClassLoaderWeakHandle, mtClass>;
+template class Hashtable<WeakHandle<vm_class_loader_data>, mtClass>;
template class Hashtable<Symbol*, mtModule>;
template class Hashtable<oop, mtSymbol>;
-template class Hashtable<ClassLoaderWeakHandle, mtSymbol>;
template class Hashtable<Symbol*, mtClass>;
template class HashtableEntry<Symbol*, mtSymbol>;
template class HashtableEntry<Symbol*, mtClass>;
template class HashtableEntry<oop, mtSymbol>;
-template class HashtableEntry<ClassLoaderWeakHandle, mtSymbol>;
+template class HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass>;
template class HashtableBucket<mtClass>;
template class BasicHashtableEntry<mtSymbol>;
template class BasicHashtableEntry<mtCode>;
--- a/src/java.base/share/classes/java/io/File.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/io/File.java Wed Apr 10 10:46:53 2019 +0530
@@ -1869,7 +1869,7 @@
*
* <p> The returned number of available bytes is a hint, but not a
* guarantee, that it is possible to use most or any of these bytes. The
- * number of unallocated bytes is most likely to be accurate immediately
+ * number of available bytes is most likely to be accurate immediately
* after this call. It is likely to be made inaccurate by any external
* I/O operations including those made on the system outside of this
* virtual machine. This method makes no guarantee that write operations
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Apr 10 10:46:53 2019 +0530
@@ -92,19 +92,57 @@
}
/**
- * Creates an AbstractStringBuilder with the specified coder and with
- * the initial capacity equal to the smaller of (length + addition)
- * and Integer.MAX_VALUE.
+ * Constructs an AbstractStringBuilder that contains the same characters
+ * as the specified {@code String}. The initial capacity of
+ * the string builder is {@code 16} plus the length of the
+ * {@code String} argument.
+ *
+ * @param str the string to copy.
*/
- AbstractStringBuilder(byte coder, int length, int addition) {
+ AbstractStringBuilder(String str) {
+ int length = str.length();
+ int capacity = (length < Integer.MAX_VALUE - 16)
+ ? length + 16 : Integer.MAX_VALUE;
+ final byte initCoder = str.coder();
+ coder = initCoder;
+ value = (initCoder == LATIN1)
+ ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
+ append(str);
+ }
+
+ /**
+ * Constructs an AbstractStringBuilder that contains the same characters
+ * as the specified {@code CharSequence}. The initial capacity of
+ * the string builder is {@code 16} plus the length of the
+ * {@code CharSequence} argument.
+ *
+ * @param seq the sequence to copy.
+ */
+ AbstractStringBuilder(CharSequence seq) {
+ int length = seq.length();
if (length < 0) {
throw new NegativeArraySizeException("Negative length: " + length);
}
- this.coder = coder;
- int capacity = (length < Integer.MAX_VALUE - addition)
- ? length + addition : Integer.MAX_VALUE;
- value = (coder == LATIN1)
+ int capacity = (length < Integer.MAX_VALUE - 16)
+ ? length + 16 : Integer.MAX_VALUE;
+
+ final byte initCoder;
+ if (COMPACT_STRINGS) {
+ if (seq instanceof AbstractStringBuilder) {
+ initCoder = ((AbstractStringBuilder)seq).getCoder();
+ } else if (seq instanceof String) {
+ initCoder = ((String)seq).coder();
+ } else {
+ initCoder = LATIN1;
+ }
+ } else {
+ initCoder = UTF16;
+ }
+
+ coder = initCoder;
+ value = (initCoder == LATIN1)
? new byte[capacity] : StringUTF16.newBytesFor(capacity);
+ append(seq);
}
/**
--- a/src/java.base/share/classes/java/lang/StringBuffer.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/lang/StringBuffer.java Wed Apr 10 10:46:53 2019 +0530
@@ -148,8 +148,7 @@
*/
@HotSpotIntrinsicCandidate
public StringBuffer(String str) {
- super(str.coder(), str.length(), 16);
- append(str);
+ super(str);
}
/**
@@ -162,8 +161,7 @@
* @since 1.5
*/
public StringBuffer(CharSequence seq) {
- super(String.LATIN1, seq.length(), 16);
- append(seq);
+ super(seq);
}
/**
--- a/src/java.base/share/classes/java/lang/StringBuilder.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/lang/StringBuilder.java Wed Apr 10 10:46:53 2019 +0530
@@ -121,8 +121,7 @@
*/
@HotSpotIntrinsicCandidate
public StringBuilder(String str) {
- super(str.coder(), str.length(), 16);
- append(str);
+ super(str);
}
/**
@@ -134,8 +133,7 @@
* @param seq the sequence to copy.
*/
public StringBuilder(CharSequence seq) {
- super(String.LATIN1, seq.length(), 16);
- append(seq);
+ super(seq);
}
/**
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -56,7 +56,10 @@
* {@code Field}s, {@code Method}s, or {@code Constructor}s are used to get or
* set fields, to invoke methods, or to create and initialize new instances of
* classes, respectively. Every reflected object checks that the code using it
- * is in an appropriate class, package, or module. </p>
+ * is in an appropriate class, package, or module. The check when invoked by
+ * <a href="{@docRoot}/../specs/jni/index.html">JNI code</a> with no Java
+ * class on the stack only succeeds if the member and the declaring class are
+ * public, and the class is in a package that is exported to all modules. </p>
*
* <p> The one variation from Java language access control is that the checks
* by reflected objects assume readability. That is, the module containing
@@ -670,6 +673,13 @@
private boolean slowVerifyAccess(Class<?> caller, Class<?> memberClass,
Class<?> targetClass, int modifiers)
{
+
+ if (caller == null) {
+ // No caller frame when a native thread attaches to the VM
+ // only allow access to a public accessible member
+ return Reflection.verifyPublicMemberAccess(memberClass, modifiers);
+ }
+
if (!Reflection.verifyMemberAccess(caller, memberClass, targetClass, modifiers)) {
// access denied
return false;
--- a/src/java.base/share/classes/java/security/Permissions.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/security/Permissions.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -25,21 +25,20 @@
package java.security;
+import java.io.InvalidObjectException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
-import java.util.NoSuchElementException;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
import java.util.Iterator;
-import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
-import java.io.Serializable;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-
/**
* This class represents a heterogeneous collection of Permissions. That is,
@@ -392,6 +391,22 @@
permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);
+ // Check that Class is mapped to PermissionCollection containing
+ // Permissions of the same class
+ for (Map.Entry<Class<?>, PermissionCollection> e : perms.entrySet()) {
+ Class<?> k = e.getKey();
+ PermissionCollection v = e.getValue();
+ Enumeration<Permission> en = v.elements();
+ while (en.hasMoreElements()) {
+ Permission p = en.nextElement();
+ if (!k.equals(p.getClass())) {
+ throw new InvalidObjectException("Permission with class " +
+ k + " incorrectly mapped to PermissionCollection " +
+ "containing Permission with " + p.getClass());
+ }
+ }
+ }
+
// Set hasUnresolved
UnresolvedPermissionCollection uc =
(UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class);
@@ -584,5 +599,15 @@
(Hashtable<Permission, Permission>)gfields.get("perms", null);
permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);
+
+ // check that the Permission key and value are the same object
+ for (Map.Entry<Permission, Permission> e : perms.entrySet()) {
+ Permission k = e.getKey();
+ Permission v = e.getValue();
+ if (k != v) {
+ throw new InvalidObjectException("Permission (" + k +
+ ") incorrectly mapped to Permission (" + v + ")");
+ }
+ }
}
}
--- a/src/java.base/share/classes/java/security/Signature.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/security/Signature.java Wed Apr 10 10:46:53 2019 +0530
@@ -40,6 +40,8 @@
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
import javax.crypto.NoSuchPaddingException;
+import jdk.internal.access.JavaSecuritySignatureAccess;
+import jdk.internal.access.SharedSecrets;
import sun.security.util.Debug;
import sun.security.jca.*;
@@ -118,6 +120,34 @@
public abstract class Signature extends SignatureSpi {
+ static {
+ SharedSecrets.setJavaSecuritySignatureAccess(
+ new JavaSecuritySignatureAccess() {
+ @Override
+ public void initVerify(Signature s, PublicKey publicKey,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ s.initVerify(publicKey, params);
+ }
+ @Override
+ public void initVerify(Signature s,
+ java.security.cert.Certificate certificate,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ s.initVerify(certificate, params);
+ }
+ @Override
+ public void initSign(Signature s, PrivateKey privateKey,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ s.initSign(privateKey, params, random);
+ }
+ });
+ }
+
private static final Debug debug =
Debug.getInstance("jca", "Signature");
@@ -482,6 +512,53 @@
}
/**
+ * Initialize this object for verification. If this method is called
+ * again with different arguments, it negates the effect
+ * of this call.
+ *
+ * @param publicKey the public key of the identity whose signature is
+ * going to be verified.
+ * @param params the parameters used for verifying this signature.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ * @exception InvalidAlgorithmParameterException if the params is invalid.
+ */
+ final void initVerify(PublicKey publicKey, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ engineInitVerify(publicKey, params);
+ state = VERIFY;
+
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " verification algorithm from: " + getProviderName());
+ }
+ }
+
+ private static PublicKey getPublicKeyFromCert(Certificate cert)
+ throws InvalidKeyException {
+ // If the certificate is of type X509Certificate,
+ // we should check whether it has a Key Usage
+ // extension marked as critical.
+ //if (cert instanceof java.security.cert.X509Certificate) {
+ if (cert instanceof X509Certificate) {
+ // Check whether the cert has a key usage extension
+ // marked as a critical extension.
+ // The OID for KeyUsage extension is 2.5.29.15.
+ X509Certificate c = (X509Certificate)cert;
+ Set<String> critSet = c.getCriticalExtensionOIDs();
+
+ if (critSet != null && !critSet.isEmpty()
+ && critSet.contains("2.5.29.15")) {
+ boolean[] keyUsageInfo = c.getKeyUsage();
+ // keyUsageInfo[0] is for digitalSignature.
+ if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
+ throw new InvalidKeyException("Wrong key usage");
+ }
+ }
+ return cert.getPublicKey();
+ }
+
+ /**
* Initializes this object for verification, using the public key from
* the given certificate.
* <p>If the certificate is of type X.509 and has a <i>key usage</i>
@@ -501,27 +578,40 @@
*/
public final void initVerify(Certificate certificate)
throws InvalidKeyException {
- // If the certificate is of type X509Certificate,
- // we should check whether it has a Key Usage
- // extension marked as critical.
- if (certificate instanceof java.security.cert.X509Certificate) {
- // Check whether the cert has a key usage extension
- // marked as a critical extension.
- // The OID for KeyUsage extension is 2.5.29.15.
- X509Certificate cert = (X509Certificate)certificate;
- Set<String> critSet = cert.getCriticalExtensionOIDs();
+ engineInitVerify(getPublicKeyFromCert(certificate));
+ state = VERIFY;
+
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " verification algorithm from: " + getProviderName());
+ }
+ }
- if (critSet != null && !critSet.isEmpty()
- && critSet.contains("2.5.29.15")) {
- boolean[] keyUsageInfo = cert.getKeyUsage();
- // keyUsageInfo[0] is for digitalSignature.
- if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
- throw new InvalidKeyException("Wrong key usage");
- }
- }
-
- PublicKey publicKey = certificate.getPublicKey();
- engineInitVerify(publicKey);
+ /**
+ * Initializes this object for verification, using the public key from
+ * the given certificate.
+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for digital signatures, an
+ * {@code InvalidKeyException} is thrown.
+ *
+ * @param certificate the certificate of the identity whose signature is
+ * going to be verified.
+ * @param params the parameters used for verifying this signature.
+ *
+ * @exception InvalidKeyException if the public key in the certificate
+ * is not encoded properly or does not include required parameter
+ * information or cannot be used for digital signature purposes.
+ * @exception InvalidAlgorithmParameterException if the params is invalid.
+ *
+ * @since 13
+ */
+ final void initVerify(Certificate certificate,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ engineInitVerify(getPublicKeyFromCert(certificate), params);
state = VERIFY;
if (!skipDebug && pdebug != null) {
@@ -575,6 +665,31 @@
}
/**
+ * Initialize this object for signing. If this method is called
+ * again with different arguments, it negates the effect
+ * of this call.
+ *
+ * @param privateKey the private key of the identity whose signature
+ * is going to be generated.
+ * @param params the parameters used for generating signature.
+ * @param random the source of randomness for this signature.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ * @exception InvalidAlgorithmParameterException if the params is invalid
+ */
+ final void initSign(PrivateKey privateKey,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ engineInitSign(privateKey, params, random);
+ state = SIGN;
+
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " signing algorithm from: " + getProviderName());
+ }
+ }
+
+ /**
* Returns the signature bytes of all the data updated.
* The format of the signature depends on the underlying
* signature scheme.
@@ -1110,11 +1225,13 @@
}
}
- private void chooseProvider(int type, Key key, SecureRandom random)
- throws InvalidKeyException {
+ // Used by engineSetParameter/engineInitSign/engineInitVerify() to
+ // find the right provider with the supplied key, parameters, random source
+ private void chooseProvider(int type, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
if (sigSpi != null) {
- init(sigSpi, type, key, random);
return;
}
Exception lastException = null;
@@ -1127,7 +1244,7 @@
s = serviceIterator.next();
}
// if provider says it does not support this key, ignore it
- if (s.supportsParameter(key) == false) {
+ if (key != null && s.supportsParameter(key) == false) {
continue;
}
// if instance is not a SignatureSpi, ignore it
@@ -1136,7 +1253,7 @@
}
try {
SignatureSpi spi = newInstance(s);
- init(spi, type, key, random);
+ tryOperation(spi, type, key, params, random);
provider = s.getProvider();
sigSpi = spi;
firstService = null;
@@ -1158,6 +1275,10 @@
if (lastException instanceof RuntimeException) {
throw (RuntimeException)lastException;
}
+ if (lastException instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)lastException;
+ }
+
String k = (key != null) ? key.getClass().getName() : "(null)";
throw new InvalidKeyException
("No installed provider supports this key: "
@@ -1165,22 +1286,35 @@
}
}
- private static final int I_PUB = 1;
- private static final int I_PRIV = 2;
- private static final int I_PRIV_SR = 3;
+ private static final int I_PUB = 1;
+ private static final int I_PRIV = 2;
+ private static final int I_PRIV_SR = 3;
+ private static final int I_PUB_PARAM = 4;
+ private static final int I_PRIV_PARAM_SR = 5;
+ private static final int S_PARAM = 6;
- private void init(SignatureSpi spi, int type, Key key,
- SecureRandom random) throws InvalidKeyException {
+ private void tryOperation(SignatureSpi spi, int type, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
switch (type) {
case I_PUB:
spi.engineInitVerify((PublicKey)key);
break;
+ case I_PUB_PARAM:
+ spi.engineInitVerify((PublicKey)key, params);
+ break;
case I_PRIV:
spi.engineInitSign((PrivateKey)key);
break;
case I_PRIV_SR:
spi.engineInitSign((PrivateKey)key, random);
break;
+ case I_PRIV_PARAM_SR:
+ spi.engineInitSign((PrivateKey)key, params, random);
+ break;
+ case S_PARAM:
+ spi.engineSetParameter(params);
+ break;
default:
throw new AssertionError("Internal error: " + type);
}
@@ -1191,7 +1325,22 @@
if (sigSpi != null) {
sigSpi.engineInitVerify(publicKey);
} else {
- chooseProvider(I_PUB, publicKey, null);
+ try {
+ chooseProvider(I_PUB, publicKey, null, null);
+ } catch (InvalidAlgorithmParameterException iape) {
+ // should not happen, re-throw as IKE just in case
+ throw new InvalidKeyException(iape);
+ }
+ }
+ }
+
+ void engineInitVerify(PublicKey publicKey,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (sigSpi != null) {
+ sigSpi.engineInitVerify(publicKey, params);
+ } else {
+ chooseProvider(I_PUB_PARAM, publicKey, params, null);
}
}
@@ -1200,7 +1349,12 @@
if (sigSpi != null) {
sigSpi.engineInitSign(privateKey);
} else {
- chooseProvider(I_PRIV, privateKey, null);
+ try {
+ chooseProvider(I_PRIV, privateKey, null, null);
+ } catch (InvalidAlgorithmParameterException iape) {
+ // should not happen, re-throw as IKE just in case
+ throw new InvalidKeyException(iape);
+ }
}
}
@@ -1209,7 +1363,22 @@
if (sigSpi != null) {
sigSpi.engineInitSign(privateKey, sr);
} else {
- chooseProvider(I_PRIV_SR, privateKey, sr);
+ try {
+ chooseProvider(I_PRIV_SR, privateKey, null, sr);
+ } catch (InvalidAlgorithmParameterException iape) {
+ // should not happen, re-throw as IKE just in case
+ throw new InvalidKeyException(iape);
+ }
+ }
+ }
+
+ void engineInitSign(PrivateKey privateKey,
+ AlgorithmParameterSpec params, SecureRandom sr)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (sigSpi != null) {
+ sigSpi.engineInitSign(privateKey, params, sr);
+ } else {
+ chooseProvider(I_PRIV_PARAM_SR, privateKey, params, sr);
}
}
@@ -1260,8 +1429,16 @@
protected void engineSetParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
- chooseFirstProvider();
- sigSpi.engineSetParameter(params);
+ if (sigSpi != null) {
+ sigSpi.engineSetParameter(params);
+ } else {
+ try {
+ chooseProvider(S_PARAM, null, params, null);
+ } catch (InvalidKeyException ike) {
+ // should never happen, rethrow just in case
+ throw new InvalidAlgorithmParameterException(ike);
+ }
+ }
}
protected Object engineGetParameter(String param)
--- a/src/java.base/share/classes/java/security/SignatureSpi.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/security/SignatureSpi.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -72,6 +72,33 @@
/**
* Initializes this signature object with the specified
+ * public key for verification operations.
+ *
+ * @param publicKey the public key of the identity whose signature is
+ * going to be verified.
+ * @param params the parameters for generating this signature
+ *
+ * @exception InvalidKeyException if the key is improperly
+ * encoded, does not work with the given parameters, and so on.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * is invalid.
+ */
+ void engineInitVerify(PublicKey publicKey,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (params != null) {
+ try {
+ engineSetParameter(params);
+ } catch (UnsupportedOperationException usoe) {
+ // error out if not overrridden
+ throw new InvalidAlgorithmParameterException(usoe);
+ }
+ }
+ engineInitVerify(publicKey);
+ }
+
+ /**
+ * Initializes this signature object with the specified
* private key for signing operations.
*
* @param privateKey the private key of the identity whose signature
@@ -98,10 +125,41 @@
* encoded, parameters are missing, and so on.
*/
protected void engineInitSign(PrivateKey privateKey,
- SecureRandom random)
- throws InvalidKeyException {
- this.appRandom = random;
- engineInitSign(privateKey);
+ SecureRandom random)
+ throws InvalidKeyException {
+ this.appRandom = random;
+ engineInitSign(privateKey);
+ }
+
+ /**
+ * Initializes this signature object with the specified
+ * private key and source of randomness for signing operations.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ *
+ * @param privateKey the private key of the identity whose signature
+ * will be generated.
+ * @param params the parameters for generating this signature
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the key is improperly
+ * encoded, parameters are missing, and so on.
+ * @exception InvalidAlgorithmParameterException if the parameters is
+ * invalid.
+ */
+ void engineInitSign(PrivateKey privateKey,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (params != null) {
+ try {
+ engineSetParameter(params);
+ } catch (UnsupportedOperationException usoe) {
+ // error out if not overrridden
+ throw new InvalidAlgorithmParameterException(usoe);
+ }
+ }
+ engineInitSign(privateKey, random);
}
/**
@@ -127,7 +185,7 @@
* properly
*/
protected abstract void engineUpdate(byte[] b, int off, int len)
- throws SignatureException;
+ throws SignatureException;
/**
* Updates the data to be signed or verified using the specified
@@ -223,7 +281,7 @@
* @since 1.2
*/
protected int engineSign(byte[] outbuf, int offset, int len)
- throws SignatureException {
+ throws SignatureException {
byte[] sig = engineSign();
if (len < sig.length) {
throw new SignatureException
@@ -251,7 +309,7 @@
* process the input data provided, etc.
*/
protected abstract boolean engineVerify(byte[] sigBytes)
- throws SignatureException;
+ throws SignatureException;
/**
* Verifies the passed-in signature in the specified array
@@ -273,7 +331,7 @@
* @since 1.4
*/
protected boolean engineVerify(byte[] sigBytes, int offset, int length)
- throws SignatureException {
+ throws SignatureException {
byte[] sigBytesCopy = new byte[length];
System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length);
return engineVerify(sigBytesCopy);
@@ -305,7 +363,7 @@
*/
@Deprecated
protected abstract void engineSetParameter(String param, Object value)
- throws InvalidParameterException;
+ throws InvalidParameterException;
/**
* <p>This method is overridden by providers to initialize
@@ -321,8 +379,8 @@
* are inappropriate for this signature engine
*/
protected void engineSetParameter(AlgorithmParameterSpec params)
- throws InvalidAlgorithmParameterException {
- throw new UnsupportedOperationException();
+ throws InvalidAlgorithmParameterException {
+ throw new UnsupportedOperationException();
}
/**
--- a/src/java.base/share/classes/java/security/cert/X509CRL.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/security/cert/X509CRL.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -239,16 +239,15 @@
public void verify(PublicKey key, Provider sigProvider)
throws CRLException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException {
+ String sigAlgName = getSigAlgName();
Signature sig = (sigProvider == null)
- ? Signature.getInstance(getSigAlgName())
- : Signature.getInstance(getSigAlgName(), sigProvider);
+ ? Signature.getInstance(sigAlgName)
+ : Signature.getInstance(sigAlgName, sigProvider);
- sig.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selections occur when key is set
try {
- SignatureUtil.specialSetParameter(sig, getSigAlgParams());
+ byte[] paramBytes = getSigAlgParams();
+ SignatureUtil.initVerifyWithParam(sig, key,
+ SignatureUtil.getParamSpec(sigAlgName, paramBytes));
} catch (ProviderException e) {
throw new CRLException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
--- a/src/java.base/share/classes/java/security/cert/X509Certificate.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/security/cert/X509Certificate.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -676,16 +676,14 @@
public void verify(PublicKey key, Provider sigProvider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException {
+ String sigName = getSigAlgName();
Signature sig = (sigProvider == null)
- ? Signature.getInstance(getSigAlgName())
- : Signature.getInstance(getSigAlgName(), sigProvider);
+ ? Signature.getInstance(sigName)
+ : Signature.getInstance(sigName, sigProvider);
- sig.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selections occur when key is set
try {
- SignatureUtil.specialSetParameter(sig, getSigAlgParams());
+ SignatureUtil.initVerifyWithParam(sig, key,
+ SignatureUtil.getParamSpec(sigName, getSigAlgParams()));
} catch (ProviderException e) {
throw new CertificateException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/ImmutableCollections.java Wed Apr 10 10:46:53 2019 +0530
@@ -95,11 +95,6 @@
}
}
- @SuppressWarnings("unchecked")
- static <E> List<E> emptyList() {
- return (List<E>) ListN.EMPTY_LIST;
- }
-
static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
implements List<E>, RandomAccess {
@@ -409,6 +404,11 @@
}
@Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
public E get(int index) {
if (index == 0) {
return e0;
@@ -485,7 +485,7 @@
@Override
public boolean isEmpty() {
- return size() == 0;
+ return elements.length == 0;
}
@Override
@@ -556,11 +556,6 @@
public abstract int hashCode();
}
- @SuppressWarnings("unchecked")
- static <E> Set<E> emptySet() {
- return (Set<E>) SetN.EMPTY_SET;
- }
-
static final class Set12<E> extends AbstractImmutableSet<E>
implements Serializable {
@@ -589,6 +584,11 @@
}
@Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
public boolean contains(Object o) {
return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
}
@@ -716,6 +716,11 @@
}
@Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
public boolean contains(Object o) {
Objects.requireNonNull(o);
return size > 0 && probe(o) >= 0;
@@ -844,11 +849,6 @@
// ---------- Map Implementations ----------
- @SuppressWarnings("unchecked")
- static <K,V> Map<K,V> emptyMap() {
- return (Map<K,V>) MapN.EMPTY_MAP;
- }
-
abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {
@Override public void clear() { throw uoe(); }
@Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }
@@ -882,6 +882,11 @@
}
@Override
+ public V get(Object o) {
+ return o.equals(k0) ? v0 : null; // implicit nullcheck of o
+ }
+
+ @Override
public boolean containsKey(Object o) {
return o.equals(k0); // implicit nullcheck of o
}
@@ -891,6 +896,16 @@
return o.equals(v0); // implicit nullcheck of o
}
+ @Override
+ public int size() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@@ -1008,6 +1023,11 @@
return size;
}
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
class MapNIterator implements Iterator<Map.Entry<K,V>> {
private int remaining;
@@ -1248,7 +1268,7 @@
return Set.of(array);
case IMM_MAP:
if (array.length == 0) {
- return ImmutableCollections.emptyMap();
+ return ImmutableCollections.MapN.EMPTY_MAP;
} else if (array.length == 2) {
return new ImmutableCollections.Map1<>(array[0], array[1]);
} else {
--- a/src/java.base/share/classes/java/util/List.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/List.java Wed Apr 10 10:46:53 2019 +0530
@@ -787,8 +787,9 @@
*
* @since 9
*/
+ @SuppressWarnings("unchecked")
static <E> List<E> of() {
- return ImmutableCollections.emptyList();
+ return (List<E>) ImmutableCollections.ListN.EMPTY_LIST;
}
/**
@@ -1031,7 +1032,9 @@
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
- return ImmutableCollections.emptyList();
+ @SuppressWarnings("unchecked")
+ var list = (List<E>) ImmutableCollections.ListN.EMPTY_LIST;
+ return list;
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
--- a/src/java.base/share/classes/java/util/Locale.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/Locale.java Wed Apr 10 10:46:53 2019 +0530
@@ -484,63 +484,111 @@
*/
public final class Locale implements Cloneable, Serializable {
- private static final Cache LOCALECACHE = new Cache();
+ /** Useful constant for language.
+ */
+ public static final Locale ENGLISH;
/** Useful constant for language.
*/
- public static final Locale ENGLISH = createConstant("en", "");
+ public static final Locale FRENCH;
/** Useful constant for language.
*/
- public static final Locale FRENCH = createConstant("fr", "");
+ public static final Locale GERMAN;
/** Useful constant for language.
*/
- public static final Locale GERMAN = createConstant("de", "");
+ public static final Locale ITALIAN;
+
+ /** Useful constant for language.
+ */
+ public static final Locale JAPANESE;
/** Useful constant for language.
*/
- public static final Locale ITALIAN = createConstant("it", "");
+ public static final Locale KOREAN;
/** Useful constant for language.
*/
- public static final Locale JAPANESE = createConstant("ja", "");
+ public static final Locale CHINESE;
/** Useful constant for language.
*/
- public static final Locale KOREAN = createConstant("ko", "");
+ public static final Locale SIMPLIFIED_CHINESE;
/** Useful constant for language.
*/
- public static final Locale CHINESE = createConstant("zh", "");
+ public static final Locale TRADITIONAL_CHINESE;
+
+ /** Useful constant for country.
+ */
+ public static final Locale FRANCE;
- /** Useful constant for language.
+ /** Useful constant for country.
+ */
+ public static final Locale GERMANY;
+
+ /** Useful constant for country.
+ */
+ public static final Locale ITALY;
+
+ /** Useful constant for country.
*/
- public static final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
+ public static final Locale JAPAN;
+
+ /** Useful constant for country.
+ */
+ public static final Locale KOREA;
- /** Useful constant for language.
+ /** Useful constant for country.
+ */
+ public static final Locale UK;
+
+ /** Useful constant for country.
*/
- public static final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
+ public static final Locale US;
+
+ /** Useful constant for country.
+ */
+ public static final Locale CANADA;
/** Useful constant for country.
*/
- public static final Locale FRANCE = createConstant("fr", "FR");
+ public static final Locale CANADA_FRENCH;
- /** Useful constant for country.
- */
- public static final Locale GERMANY = createConstant("de", "DE");
-
- /** Useful constant for country.
+ /**
+ * Useful constant for the root locale. The root locale is the locale whose
+ * language, country, and variant are empty ("") strings. This is regarded
+ * as the base locale of all locales, and is used as the language/country
+ * neutral locale for the locale sensitive operations.
+ *
+ * @since 1.6
*/
- public static final Locale ITALY = createConstant("it", "IT");
+ public static final Locale ROOT;
+
+ private static final Map<BaseLocale, Locale> CONSTANT_LOCALES = new HashMap<>();
- /** Useful constant for country.
- */
- public static final Locale JAPAN = createConstant("ja", "JP");
-
- /** Useful constant for country.
- */
- public static final Locale KOREA = createConstant("ko", "KR");
+ static {
+ ENGLISH = createConstant(BaseLocale.ENGLISH);
+ FRENCH = createConstant(BaseLocale.FRENCH);
+ GERMAN = createConstant(BaseLocale.GERMAN);
+ ITALIAN = createConstant(BaseLocale.ITALIAN);
+ JAPANESE = createConstant(BaseLocale.JAPANESE);
+ KOREAN = createConstant(BaseLocale.KOREAN);
+ CHINESE = createConstant(BaseLocale.CHINESE);
+ SIMPLIFIED_CHINESE = createConstant(BaseLocale.SIMPLIFIED_CHINESE);
+ TRADITIONAL_CHINESE = createConstant(BaseLocale.TRADITIONAL_CHINESE);
+ FRANCE = createConstant(BaseLocale.FRANCE);
+ GERMANY = createConstant(BaseLocale.GERMANY);
+ ITALY = createConstant(BaseLocale.ITALY);
+ JAPAN = createConstant(BaseLocale.JAPAN);
+ KOREA = createConstant(BaseLocale.KOREA);
+ UK = createConstant(BaseLocale.UK);
+ US = createConstant(BaseLocale.US);
+ CANADA = createConstant(BaseLocale.CANADA);
+ CANADA_FRENCH = createConstant(BaseLocale.CANADA_FRENCH);
+ ROOT = createConstant(BaseLocale.ROOT);
+ }
/** Useful constant for country.
*/
@@ -554,31 +602,16 @@
*/
public static final Locale TAIWAN = TRADITIONAL_CHINESE;
- /** Useful constant for country.
- */
- public static final Locale UK = createConstant("en", "GB");
-
- /** Useful constant for country.
- */
- public static final Locale US = createConstant("en", "US");
-
- /** Useful constant for country.
+ /**
+ * This method must be called only for creating the Locale.*
+ * constants due to making shortcuts.
*/
- public static final Locale CANADA = createConstant("en", "CA");
-
- /** Useful constant for country.
- */
- public static final Locale CANADA_FRENCH = createConstant("fr", "CA");
-
- /**
- * Useful constant for the root locale. The root locale is the locale whose
- * language, country, and variant are empty ("") strings. This is regarded
- * as the base locale of all locales, and is used as the language/country
- * neutral locale for the locale sensitive operations.
- *
- * @since 1.6
- */
- public static final Locale ROOT = createConstant("", "");
+ private static Locale createConstant(byte baseType) {
+ BaseLocale base = BaseLocale.constantBaseLocales[baseType];
+ Locale locale = new Locale(base, null);
+ CONSTANT_LOCALES.put(base, locale);
+ return locale;
+ }
/**
* The key for the private use extension ('x').
@@ -709,7 +742,7 @@
* @exception NullPointerException thrown if any argument is null.
*/
public Locale(String language, String country, String variant) {
- if (language== null || country == null || variant == null) {
+ if (language == null || country == null || variant == null) {
throw new NullPointerException();
}
baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
@@ -767,15 +800,6 @@
}
/**
- * This method must be called only for creating the Locale.*
- * constants due to making shortcuts.
- */
- private static Locale createConstant(String lang, String country) {
- BaseLocale base = BaseLocale.createInstance(lang, country);
- return getInstance(base, null);
- }
-
- /**
* Returns a <code>Locale</code> constructed from the given
* <code>language</code>, <code>country</code> and
* <code>variant</code>. If the same <code>Locale</code> instance
@@ -803,20 +827,27 @@
extensions = getCompatibilityExtensions(language, script, country, variant);
}
- BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
+ BaseLocale baseloc = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
return getInstance(baseloc, extensions);
}
static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
if (extensions == null) {
- return LOCALECACHE.get(baseloc);
+ Locale locale = CONSTANT_LOCALES.get(baseloc);
+ if (locale != null) {
+ return locale;
+ }
+ return Cache.LOCALECACHE.get(baseloc);
} else {
LocaleKey key = new LocaleKey(baseloc, extensions);
- return LOCALECACHE.get(key);
+ return Cache.LOCALECACHE.get(key);
}
}
private static class Cache extends LocaleObjectCache<Object, Locale> {
+
+ private static final Cache LOCALECACHE = new Cache();
+
private Cache() {
}
@@ -977,8 +1008,11 @@
}
private static Optional<LocaleExtensions> getDefaultExtensions(String extensionsProp) {
+ if (LocaleUtils.isEmpty(extensionsProp)) {
+ return Optional.empty();
+ }
+
LocaleExtensions exts = null;
-
try {
exts = new InternalLocaleBuilder()
.setExtensions(extensionsProp)
@@ -2308,6 +2342,7 @@
String country = (String)fields.get("country", "");
String variant = (String)fields.get("variant", "");
String extStr = (String)fields.get("extensions", "");
+
baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
if (!extStr.isEmpty()) {
try {
--- a/src/java.base/share/classes/java/util/Map.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/Map.java Wed Apr 10 10:46:53 2019 +0530
@@ -1286,8 +1286,9 @@
*
* @since 9
*/
+ @SuppressWarnings("unchecked")
static <K, V> Map<K, V> of() {
- return ImmutableCollections.emptyMap();
+ return (Map<K,V>) ImmutableCollections.MapN.EMPTY_MAP;
}
/**
@@ -1604,7 +1605,9 @@
@SuppressWarnings("varargs")
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
if (entries.length == 0) { // implicit null check of entries array
- return ImmutableCollections.emptyMap();
+ @SuppressWarnings("unchecked")
+ var map = (Map<K,V>) ImmutableCollections.MapN.EMPTY_MAP;
+ return map;
} else if (entries.length == 1) {
// implicit null check of the array slot
return new ImmutableCollections.Map1<>(entries[0].getKey(),
--- a/src/java.base/share/classes/java/util/Optional.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/Optional.java Wed Apr 10 10:46:53 2019 +0530
@@ -61,7 +61,7 @@
/**
* Common instance for {@code empty()}.
*/
- private static final Optional<?> EMPTY = new Optional<>();
+ private static final Optional<?> EMPTY = new Optional<>(null);
/**
* If non-null, the value; if null, indicates no value is present
@@ -69,16 +69,6 @@
private final T value;
/**
- * Constructs an empty instance.
- *
- * @implNote Generally only one empty instance, {@link Optional#EMPTY},
- * should exist per VM.
- */
- private Optional() {
- this.value = null;
- }
-
- /**
* Returns an empty {@code Optional} instance. No value is present for this
* {@code Optional}.
*
@@ -100,11 +90,12 @@
/**
* Constructs an instance with the described value.
*
- * @param value the non-{@code null} value to describe
- * @throws NullPointerException if value is {@code null}
+ * @param value the value to describe; it's the caller's responsibility to
+ * ensure the value is non-{@code null} unless creating the singleton
+ * instance returned by {@code empty()}.
*/
private Optional(T value) {
- this.value = Objects.requireNonNull(value);
+ this.value = value;
}
/**
@@ -117,7 +108,7 @@
* @throws NullPointerException if value is {@code null}
*/
public static <T> Optional<T> of(T value) {
- return new Optional<>(value);
+ return new Optional<>(Objects.requireNonNull(value));
}
/**
@@ -129,8 +120,10 @@
* @return an {@code Optional} with a present value if the specified value
* is non-{@code null}, otherwise an empty {@code Optional}
*/
+ @SuppressWarnings("unchecked")
public static <T> Optional<T> ofNullable(T value) {
- return value == null ? empty() : of(value);
+ return value == null ? (Optional<T>) EMPTY
+ : new Optional<>(value);
}
/**
--- a/src/java.base/share/classes/java/util/Set.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/java/util/Set.java Wed Apr 10 10:46:53 2019 +0530
@@ -448,8 +448,9 @@
*
* @since 9
*/
+ @SuppressWarnings("unchecked")
static <E> Set<E> of() {
- return ImmutableCollections.emptySet();
+ return (Set<E>) ImmutableCollections.SetN.EMPTY_SET;
}
/**
@@ -692,7 +693,9 @@
static <E> Set<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
- return ImmutableCollections.emptySet();
+ @SuppressWarnings("unchecked")
+ var set = (Set<E>) ImmutableCollections.SetN.EMPTY_SET;
+ return set;
case 1:
return new ImmutableCollections.Set12<>(elements[0]);
case 2:
--- a/src/java.base/share/classes/javax/net/ssl/SSLContext.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/javax/net/ssl/SSLContext.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -26,8 +26,9 @@
package javax.net.ssl;
import java.security.*;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import java.util.Objects;
-
import sun.security.jca.GetInstance;
/**
@@ -58,6 +59,20 @@
private final String protocol;
+ private static volatile SSLContext defaultContext;
+
+ private static final VarHandle VH_DEFAULT_CONTEXT;
+
+ static {
+ try {
+ VH_DEFAULT_CONTEXT = MethodHandles.lookup()
+ .findStaticVarHandle(
+ SSLContext.class, "defaultContext", SSLContext.class);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
/**
* Creates an SSLContext object.
*
@@ -72,8 +87,6 @@
this.protocol = protocol;
}
- private static SSLContext defaultContext;
-
/**
* Returns the default SSL context.
*
@@ -91,12 +104,16 @@
* {@link SSLContext#getInstance SSLContext.getInstance()} call fails
* @since 1.6
*/
- public static synchronized SSLContext getDefault()
- throws NoSuchAlgorithmException {
- if (defaultContext == null) {
- defaultContext = SSLContext.getInstance("Default");
+ public static SSLContext getDefault() throws NoSuchAlgorithmException {
+ SSLContext temporaryContext = defaultContext;
+ if (temporaryContext == null) {
+ temporaryContext = SSLContext.getInstance("Default");
+ if (!VH_DEFAULT_CONTEXT.compareAndSet(null, temporaryContext)) {
+ temporaryContext = defaultContext;
+ }
}
- return defaultContext;
+
+ return temporaryContext;
}
/**
@@ -111,7 +128,7 @@
* {@code SSLPermission("setDefaultSSLContext")}
* @since 1.6
*/
- public static synchronized void setDefault(SSLContext context) {
+ public static void setDefault(SSLContext context) {
if (context == null) {
throw new NullPointerException();
}
@@ -119,6 +136,7 @@
if (sm != null) {
sm.checkPermission(new SSLPermission("setDefaultSSLContext"));
}
+
defaultContext = context;
}
--- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -42,17 +42,7 @@
* @see SSLServerSocket
* @author David Brownell
*/
-public abstract class SSLServerSocketFactory extends ServerSocketFactory
-{
- private static SSLServerSocketFactory theFactory;
-
- private static boolean propertyChecked;
-
- private static void log(String msg) {
- if (SSLSocketFactory.DEBUG) {
- System.out.println(msg);
- }
- }
+public abstract class SSLServerSocketFactory extends ServerSocketFactory {
/**
* Constructor is used only by subclasses.
@@ -75,39 +65,9 @@
* @return the default <code>ServerSocketFactory</code>
* @see SSLContext#getDefault
*/
- public static synchronized ServerSocketFactory getDefault() {
- if (theFactory != null) {
- return theFactory;
- }
-
- if (propertyChecked == false) {
- propertyChecked = true;
- String clsName = SSLSocketFactory.getSecurityProperty
- ("ssl.ServerSocketFactory.provider");
- if (clsName != null) {
- log("setting up default SSLServerSocketFactory");
- try {
- Class<?> cls = null;
- try {
- cls = Class.forName(clsName);
- } catch (ClassNotFoundException e) {
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- if (cl != null) {
- cls = cl.loadClass(clsName);
- }
- }
- log("class " + clsName + " is loaded");
- @SuppressWarnings("deprecation")
- SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance();
- log("instantiated an instance of class " + clsName);
- theFactory = fac;
- return fac;
- } catch (Exception e) {
- log("SSLServerSocketFactory instantiation failed: " + e);
- theFactory = new DefaultSSLServerSocketFactory(e);
- return theFactory;
- }
- }
+ public static ServerSocketFactory getDefault() {
+ if (DefaultFactoryHolder.defaultFactory != null) {
+ return DefaultFactoryHolder.defaultFactory;
}
try {
@@ -156,9 +116,51 @@
* @see #getDefaultCipherSuites()
*/
public abstract String [] getSupportedCipherSuites();
+
+ // lazy initialization holder class idiom for static default factory
+ //
+ // See Effective Java Second Edition: Item 71.
+ private static final class DefaultFactoryHolder {
+ private static final SSLServerSocketFactory defaultFactory;
+
+ static {
+ SSLServerSocketFactory mediator = null;
+ String clsName = SSLSocketFactory.getSecurityProperty(
+ "ssl.ServerSocketFactory.provider");
+ if (clsName != null) {
+ log("setting up default SSLServerSocketFactory");
+ try {
+ Class<?> cls = null;
+ try {
+ cls = Class.forName(clsName);
+ } catch (ClassNotFoundException e) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ if (cl != null) {
+ cls = cl.loadClass(clsName);
+ }
+ }
+ log("class " + clsName + " is loaded");
+
+ mediator = (SSLServerSocketFactory)cls
+ .getDeclaredConstructor().newInstance();
+ log("instantiated an instance of class " + clsName);
+ } catch (Exception e) {
+ log("SSLServerSocketFactory instantiation failed: " + e);
+ mediator = new DefaultSSLServerSocketFactory(e);
+ }
+ }
+
+ defaultFactory = mediator;
+ }
+
+ private static void log(String msg) {
+ if (SSLSocketFactory.DEBUG) {
+ System.out.println(msg);
+ }
+ }
+ }
}
-
//
// The default factory does NOTHING.
//
--- a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -42,31 +42,20 @@
* @see SSLSocket
* @author David Brownell
*/
-public abstract class SSLSocketFactory extends SocketFactory
-{
- private static SSLSocketFactory theFactory;
-
- private static boolean propertyChecked;
-
+public abstract class SSLSocketFactory extends SocketFactory {
static final boolean DEBUG;
static {
- String s = GetPropertyAction.privilegedGetProperty("javax.net.debug", "")
- .toLowerCase(Locale.ENGLISH);
-
+ String s = GetPropertyAction.privilegedGetProperty(
+ "javax.net.debug", "").toLowerCase(Locale.ENGLISH);
DEBUG = s.contains("all") || s.contains("ssl");
}
- private static void log(String msg) {
- if (DEBUG) {
- System.out.println(msg);
- }
- }
-
/**
* Constructor is used only by subclasses.
*/
public SSLSocketFactory() {
+ // blank
}
/**
@@ -85,38 +74,9 @@
* @return the default <code>SocketFactory</code>
* @see SSLContext#getDefault
*/
- public static synchronized SocketFactory getDefault() {
- if (theFactory != null) {
- return theFactory;
- }
-
- if (propertyChecked == false) {
- propertyChecked = true;
- String clsName = getSecurityProperty("ssl.SocketFactory.provider");
- if (clsName != null) {
- log("setting up default SSLSocketFactory");
- try {
- Class<?> cls = null;
- try {
- cls = Class.forName(clsName);
- } catch (ClassNotFoundException e) {
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- if (cl != null) {
- cls = cl.loadClass(clsName);
- }
- }
- log("class " + clsName + " is loaded");
- @SuppressWarnings("deprecation")
- SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
- log("instantiated an instance of class " + clsName);
- theFactory = fac;
- return fac;
- } catch (Exception e) {
- log("SSLSocketFactory instantiation failed: " + e.toString());
- theFactory = new DefaultSSLSocketFactory(e);
- return theFactory;
- }
- }
+ public static SocketFactory getDefault() {
+ if (DefaultFactoryHolder.defaultFactory != null) {
+ return DefaultFactoryHolder.defaultFactory;
}
try {
@@ -246,6 +206,49 @@
boolean autoClose) throws IOException {
throw new UnsupportedOperationException();
}
+
+ // lazy initialization holder class idiom for static default factory
+ //
+ // See Effective Java Second Edition: Item 71.
+ private static final class DefaultFactoryHolder {
+ private static final SSLSocketFactory defaultFactory;
+
+ static {
+ SSLSocketFactory mediator = null;
+ String clsName = getSecurityProperty("ssl.SocketFactory.provider");
+ if (clsName != null) {
+ log("setting up default SSLSocketFactory");
+ try {
+ Class<?> cls = null;
+ try {
+ cls = Class.forName(clsName);
+ } catch (ClassNotFoundException e) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ if (cl != null) {
+ cls = cl.loadClass(clsName);
+ }
+ }
+ log("class " + clsName + " is loaded");
+
+ mediator = (SSLSocketFactory)cls
+ .getDeclaredConstructor().newInstance();
+
+ log("instantiated an instance of class " + clsName);
+ } catch (Exception e) {
+ log("SSLSocketFactory instantiation failed: " + e);
+ mediator = new DefaultSSLSocketFactory(e);
+ }
+ }
+
+ defaultFactory = mediator;
+ }
+
+ private static void log(String msg) {
+ if (DEBUG) {
+ System.out.println(msg);
+ }
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/access/JavaSecuritySignatureAccess.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, 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 jdk.internal.access;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+public interface JavaSecuritySignatureAccess {
+
+ void initVerify(Signature s, PublicKey publicKey, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ void initVerify(Signature s, java.security.cert.Certificate certificate,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ void initSign(Signature s, PrivateKey privateKey,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+}
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java Wed Apr 10 10:46:53 2019 +0530
@@ -36,6 +36,7 @@
import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
import java.security.ProtectionDomain;
+import java.security.Signature;
import jdk.internal.misc.Unsafe;
/** A repository of "shared secrets", which are a mechanism for
@@ -73,6 +74,7 @@
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
+ private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -327,6 +329,17 @@
return javaIORandomAccessFileAccess;
}
+ public static void setJavaSecuritySignatureAccess(JavaSecuritySignatureAccess jssa) {
+ javaSecuritySignatureAccess = jssa;
+ }
+
+ public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() {
+ if (javaSecuritySignatureAccess == null) {
+ unsafe.ensureClassInitialized(Signature.class);
+ }
+ return javaSecuritySignatureAccess;
+ }
+
public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) {
javaxCryptoSealedObjectAccess = jcsoa;
}
--- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed Apr 10 10:46:53 2019 +0530
@@ -64,6 +64,7 @@
import jdk.internal.misc.VM;
import jdk.internal.module.ModulePatcher.PatchedModuleReader;
import jdk.internal.module.Resources;
+import jdk.internal.vm.annotation.Stable;
/**
@@ -117,14 +118,18 @@
private static class LoadedModule {
private final BuiltinClassLoader loader;
private final ModuleReference mref;
- private final URL codeSourceURL; // may be null
+ private final URI uri; // may be null
+ private @Stable URL codeSourceURL; // may be null
LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
URL url = null;
- if (mref.location().isPresent()) {
- try {
- url = mref.location().get().toURL();
- } catch (MalformedURLException | IllegalArgumentException e) { }
+ this.uri = mref.location().orElse(null);
+
+ // for non-jrt schemes we need to resolve the codeSourceURL
+ // eagerly during bootstrap since the handler might be
+ // overridden
+ if (uri != null && !"jrt".equals(uri.getScheme())) {
+ url = createURL(uri);
}
this.loader = loader;
this.mref = mref;
@@ -134,7 +139,23 @@
BuiltinClassLoader loader() { return loader; }
ModuleReference mref() { return mref; }
String name() { return mref.descriptor().name(); }
- URL codeSourceURL() { return codeSourceURL; }
+
+ URL codeSourceURL() {
+ URL url = codeSourceURL;
+ if (url == null && uri != null) {
+ codeSourceURL = url = createURL(uri);
+ }
+ return url;
+ }
+
+ private URL createURL(URI uri) {
+ URL url = null;
+ try {
+ url = uri.toURL();
+ } catch (MalformedURLException | IllegalArgumentException e) {
+ }
+ return url;
+ }
}
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed Apr 10 10:46:53 2019 +0530
@@ -33,6 +33,7 @@
import java.lang.reflect.Field;
import java.security.ProtectionDomain;
+import static jdk.internal.misc.UnsafeConstants.*;
/**
* A collection of methods for performing low-level, unsafe operations.
@@ -1166,14 +1167,13 @@
}
/** The value of {@code addressSize()} */
- public static final int ADDRESS_SIZE = theUnsafe.addressSize0();
+ public static final int ADDRESS_SIZE = ADDRESS_SIZE0;
/**
* Reports the size in bytes of a native memory page (whatever that is).
* This value will always be a power of two.
*/
- public native int pageSize();
-
+ public int pageSize() { return PAGE_SIZE; }
/// random trusted operations from JNI:
@@ -1417,7 +1417,7 @@
byte x) {
long wordOffset = offset & ~3;
int shift = (int) (offset & 3) << 3;
- if (BE) {
+ if (BIG_ENDIAN) {
shift = 24 - shift;
}
int mask = 0xFF << shift;
@@ -1491,7 +1491,7 @@
}
long wordOffset = offset & ~3;
int shift = (int) (offset & 3) << 3;
- if (BE) {
+ if (BIG_ENDIAN) {
shift = 16 - shift;
}
int mask = 0xFFFF << shift;
@@ -3354,14 +3354,14 @@
* @return Returns true if the native byte ordering of this
* platform is big-endian, false if it is little-endian.
*/
- public final boolean isBigEndian() { return BE; }
+ public final boolean isBigEndian() { return BIG_ENDIAN; }
/**
* @return Returns true if this platform is capable of performing
* accesses at addresses which are not aligned for the type of the
* primitive type being accessed, false otherwise.
*/
- public final boolean unalignedAccess() { return unalignedAccess; }
+ public final boolean unalignedAccess() { return UNALIGNED_ACCESS; }
/**
* Fetches a value at some byte offset into a given Java object.
@@ -3603,14 +3603,7 @@
putCharUnaligned(o, offset, convEndian(bigEndian, x));
}
- // JVM interface methods
- // BE is true iff the native endianness of this platform is big.
- private static final boolean BE = theUnsafe.isBigEndian0();
-
- // unalignedAccess is true iff this platform can perform unaligned accesses.
- private static final boolean unalignedAccess = theUnsafe.unalignedAccess0();
-
- private static int pickPos(int top, int pos) { return BE ? top - pos : pos; }
+ private static int pickPos(int top, int pos) { return BIG_ENDIAN ? top - pos : pos; }
// These methods construct integers from bytes. The byte ordering
// is the native endianness of this platform.
@@ -3649,9 +3642,9 @@
| (toUnsignedInt(i1) << pickPos(8, 8)));
}
- private static byte pick(byte le, byte be) { return BE ? be : le; }
- private static short pick(short le, short be) { return BE ? be : le; }
- private static int pick(int le, int be) { return BE ? be : le; }
+ private static byte pick(byte le, byte be) { return BIG_ENDIAN ? be : le; }
+ private static short pick(short le, short be) { return BIG_ENDIAN ? be : le; }
+ private static int pick(int le, int be) { return BIG_ENDIAN ? be : le; }
// These methods write integers to memory from smaller parts
// provided by their caller. The ordering in which these parts
@@ -3699,10 +3692,10 @@
private static long toUnsignedLong(int n) { return n & 0xffffffffl; }
// Maybe byte-reverse an integer
- private static char convEndian(boolean big, char n) { return big == BE ? n : Character.reverseBytes(n); }
- private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; }
- private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; }
- private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; }
+ private static char convEndian(boolean big, char n) { return big == BIG_ENDIAN ? n : Character.reverseBytes(n); }
+ private static short convEndian(boolean big, short n) { return big == BIG_ENDIAN ? n : Short.reverseBytes(n) ; }
+ private static int convEndian(boolean big, int n) { return big == BIG_ENDIAN ? n : Integer.reverseBytes(n) ; }
+ private static long convEndian(boolean big, long n) { return big == BIG_ENDIAN ? n : Long.reverseBytes(n) ; }
@@ -3721,11 +3714,8 @@
private native void ensureClassInitialized0(Class<?> c);
private native int arrayBaseOffset0(Class<?> arrayClass);
private native int arrayIndexScale0(Class<?> arrayClass);
- private native int addressSize0();
private native Class<?> defineAnonymousClass0(Class<?> hostClass, byte[] data, Object[] cpPatches);
private native int getLoadAverage0(double[] loadavg, int nelems);
- private native boolean unalignedAccess0();
- private native boolean isBigEndian0();
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/UnsafeConstants.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019, Red Hat Inc. 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 jdk.internal.misc;
+
+/**
+ * A class used to expose details of the underlying hardware that
+ * configure the operation of class Unsafe. This class is
+ * package-private as the only intended client is class Unsafe.
+ * All fields in this class must be static final constants.
+ *
+ * @since 13
+ *
+ * @implNote
+ *
+ * The JVM injects hardware-specific values into all the static fields
+ * of this class during JVM initialization. The static initialization
+ * block is executed when the class is initialized then JVM injection
+ * updates the fields with the correct constants. The static block
+ * is required to prevent the fields from being considered constant
+ * variables, so the field values will be not be compiled directly into
+ * any class that uses them.
+ */
+
+final class UnsafeConstants {
+
+ /**
+ * This constructor is private because the class is not meant to
+ * be instantiated.
+ */
+ private UnsafeConstants() {}
+
+ /**
+ * The size in bytes of a native pointer, as stored via {@link
+ * #putAddress}. This value will be either 4 or 8. Note that the
+ * sizes of other primitive types (as stored in native memory
+ * blocks) is determined fully by their information content.
+ *
+ * @implNote
+ * The actual value for this field is injected by the JVM.
+ */
+
+ static final int ADDRESS_SIZE0;
+
+ /**
+ * The size in bytes of a native memory page (whatever that is).
+ * This value will always be a power of two.
+ *
+ * @implNote
+ * The actual value for this field is injected by the JVM.
+ */
+
+ static final int PAGE_SIZE;
+
+ /**
+ * Flag whose value is true if and only if the native endianness
+ * of this platform is big.
+ *
+ * @implNote
+ * The actual value for this field is injected by the JVM.
+ */
+
+ static final boolean BIG_ENDIAN;
+
+ /**
+ * Flag whose value is true if and only if the platform can
+ * perform unaligned accesses
+ *
+ * @implNote
+ * The actual value for this field is injected by the JVM.
+ */
+
+ static final boolean UNALIGNED_ACCESS;
+
+ static {
+ ADDRESS_SIZE0 = 0;
+ PAGE_SIZE = 0;
+ BIG_ENDIAN = false;
+ UNALIGNED_ACCESS = false;
+ }
+}
--- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -122,6 +122,9 @@
Class<?> targetClass,
int modifiers)
{
+ Objects.requireNonNull(currentClass);
+ Objects.requireNonNull(memberClass);
+
if (currentClass == memberClass) {
// Always succeeds
return true;
@@ -201,6 +204,22 @@
return true;
}
+ /*
+ * Verify if a member is public and memberClass is a public type
+ * in a package that is unconditionally exported and
+ * return {@code true}if it is granted.
+ *
+ * @param memberClass the declaring class of the member being accessed
+ * @param modifiers the member's access modifiers
+ * @return {@code true} if the member is public and in a publicly accessible type
+ */
+ public static boolean verifyPublicMemberAccess(Class<?> memberClass, int modifiers) {
+ Module m = memberClass.getModule();
+ return Modifier.isPublic(modifiers)
+ && m.isExported(memberClass.getPackageName())
+ && Modifier.isPublic(Reflection.getClassAccessFlags(memberClass));
+ }
+
/**
* Returns {@code true} if memberClass's module exports memberClass's
* package to currentModule.
@@ -325,8 +344,10 @@
Class<?> memberClass,
Class<?> targetClass,
int modifiers)
- throws IllegalAccessException
{
+ if (currentClass == null)
+ return newIllegalAccessException(memberClass, modifiers);
+
String currentSuffix = "";
String memberSuffix = "";
Module m1 = currentClass.getModule();
@@ -356,6 +377,36 @@
}
/**
+ * Returns an IllegalAccessException with an exception message where
+ * there is no caller frame.
+ */
+ private static IllegalAccessException newIllegalAccessException(Class<?> memberClass,
+ int modifiers)
+ {
+ String memberSuffix = "";
+ Module m2 = memberClass.getModule();
+ if (m2.isNamed())
+ memberSuffix = " (in " + m2 + ")";
+
+ String memberPackageName = memberClass.getPackageName();
+
+ String msg = "JNI attached native thread (null caller frame) cannot access ";
+ if (m2.isExported(memberPackageName)) {
+
+ // module access okay so include the modifiers in the message
+ msg += "a member of " + memberClass + memberSuffix +
+ " with modifiers \"" + Modifier.toString(modifiers) + "\"";
+
+ } else {
+ // module access failed
+ msg += memberClass + memberSuffix+ " because "
+ + m2 + " does not export " + memberPackageName;
+ }
+
+ return new IllegalAccessException(msg);
+ }
+
+ /**
* Returns true if {@code currentClass} and {@code memberClass}
* are nestmates - that is, if they have the same nesthost as
* determined by the VM.
--- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -57,8 +57,7 @@
public class HttpsURLConnectionImpl
extends javax.net.ssl.HttpsURLConnection {
- // NOTE: made protected for plugin so that subclass can set it.
- protected DelegateHttpsURLConnection delegate;
+ private final DelegateHttpsURLConnection delegate;
HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
this(u, null, handler);
@@ -78,13 +77,6 @@
delegate = new DelegateHttpsURLConnection(url, p, handler, this);
}
- // NOTE: introduced for plugin
- // subclass needs to overwrite this to set delegate to
- // the appropriate delegatee
- protected HttpsURLConnectionImpl(URL u) throws IOException {
- super(u);
- }
-
/**
* Create a new HttpClient object, bypassing the cache of
* HTTP client objects/connections.
@@ -219,11 +211,11 @@
* - get input, [read input,] get output, [write output]
*/
- public synchronized OutputStream getOutputStream() throws IOException {
+ public OutputStream getOutputStream() throws IOException {
return delegate.getOutputStream();
}
- public synchronized InputStream getInputStream() throws IOException {
+ public InputStream getInputStream() throws IOException {
return delegate.getInputStream();
}
--- a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -447,15 +447,13 @@
Signature sig = Signature.getInstance(algname);
- sig.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selections occur when key is set
AlgorithmParameters ap =
digestEncryptionAlgorithmId.getParameters();
try {
- SignatureUtil.specialSetParameter(sig, ap);
- } catch (ProviderException | InvalidAlgorithmParameterException e) {
+ SignatureUtil.initVerifyWithParam(sig, key,
+ SignatureUtil.getParamSpec(algname, ap));
+ } catch (ProviderException | InvalidAlgorithmParameterException |
+ InvalidKeyException e) {
throw new SignatureException(e.getMessage(), e);
}
@@ -466,8 +464,6 @@
} catch (IOException e) {
throw new SignatureException("IO error verifying signature:\n" +
e.getMessage());
- } catch (InvalidKeyException e) {
- throw new SignatureException("InvalidKey: " + e.getMessage());
}
return null;
}
--- a/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Wed Apr 10 10:46:53 2019 +0530
@@ -167,12 +167,8 @@
try {
sigAlg = id.getName();
sig = Signature.getInstance(sigAlg);
-
- sig.initVerify(subjectPublicKeyInfo);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selections occur when key is set
- SignatureUtil.specialSetParameter(sig, id.getParameters());
+ SignatureUtil.initVerifyWithParam(sig, subjectPublicKeyInfo,
+ SignatureUtil.getParamSpec(sigAlg, id.getParameters()));
sig.update(data);
if (!sig.verify(sigData)) {
--- a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -632,7 +632,7 @@
}
@Override
- public synchronized void setSoTimeout(int timeout) throws SocketException {
+ public void setSoTimeout(int timeout) throws SocketException {
if (self == this) {
super.setSoTimeout(timeout);
} else {
--- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Wed Apr 10 10:46:53 2019 +0530
@@ -565,7 +565,7 @@
ClientHandshakeContext chc = (ClientHandshakeContext)context;
this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
chc.peerRequestedSignatureSchemes,
- x509Possession.popPrivateKey,
+ x509Possession,
chc.negotiatedProtocol);
if (signatureScheme == null) {
// Unlikely, the credentials generator should have
@@ -866,7 +866,7 @@
this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
context.peerRequestedSignatureSchemes,
- x509Possession.popPrivateKey,
+ x509Possession,
context.negotiatedProtocol);
if (signatureScheme == null) {
// Unlikely, the credentials generator should have
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -56,20 +56,22 @@
// the following criteria:
// 1. Prefer Suite B compliant cipher suites, see RFC6460 (To be
// changed later, see below).
- // 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
+ // 2. Prefer forward secrecy cipher suites.
+ // 3. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
// AES_128(GCM), AES_256, AES_128, 3DES-EDE.
- // 3. Prefer the stronger MAC algorithm, in the order of SHA384,
+ // 4. Prefer the stronger MAC algorithm, in the order of SHA384,
// SHA256, SHA, MD5.
- // 4. Prefer the better performance of key exchange and digital
+ // 5. Prefer the better performance of key exchange and digital
// signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
- // RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
+ // DHE-RSA, DHE-DSS, ECDH-ECDSA, ECDH-RSA, RSA.
+ // TLS 1.3 cipher suites.
+ TLS_AES_256_GCM_SHA384(
+ 0x1302, true, "TLS_AES_256_GCM_SHA384",
+ ProtocolVersion.PROTOCOLS_OF_13, B_AES_256_GCM_IV, H_SHA384),
TLS_AES_128_GCM_SHA256(
0x1301, true, "TLS_AES_128_GCM_SHA256",
ProtocolVersion.PROTOCOLS_OF_13, B_AES_128_GCM_IV, H_SHA256),
- TLS_AES_256_GCM_SHA384(
- 0x1302, true, "TLS_AES_256_GCM_SHA384",
- ProtocolVersion.PROTOCOLS_OF_13, B_AES_256_GCM_IV, H_SHA384),
TLS_CHACHA20_POLY1305_SHA256(
0x1303, true, "TLS_CHACHA20_POLY1305_SHA256",
ProtocolVersion.PROTOCOLS_OF_13, B_CC20_P1305, H_SHA256),
@@ -97,7 +99,11 @@
ProtocolVersion.PROTOCOLS_OF_12,
K_ECDHE_ECDSA, B_CC20_P1305, M_NULL, H_SHA256),
- // AES_256(GCM)
+ //
+ // Forward screcy cipher suites.
+ //
+
+ // AES_256(GCM) - ECDHE
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(
0xC030, true, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "",
ProtocolVersion.PROTOCOLS_OF_12,
@@ -106,18 +112,14 @@
0xCCA8, true, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
K_ECDHE_RSA, B_CC20_P1305, M_NULL, H_SHA256),
- TLS_RSA_WITH_AES_256_GCM_SHA384(
- 0x009D, true, "TLS_RSA_WITH_AES_256_GCM_SHA384", "",
+
+ // AES_128(GCM) - ECDHE
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(
+ 0xC02F, true, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
- K_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
- TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(
- 0xC02E, true, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_ECDSA, B_AES_256_GCM, M_NULL, H_SHA384),
- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(
- 0xC032, true, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
+ K_ECDHE_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
+
+ // AES_256(GCM) - DHE
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(
0x009F, true, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "",
ProtocolVersion.PROTOCOLS_OF_12,
@@ -131,23 +133,7 @@
ProtocolVersion.PROTOCOLS_OF_12,
K_DHE_DSS, B_AES_256_GCM, M_NULL, H_SHA384),
- // AES_128(GCM)
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(
- 0xC02F, true, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDHE_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
- TLS_RSA_WITH_AES_128_GCM_SHA256(
- 0x009C, true, "TLS_RSA_WITH_AES_128_GCM_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
- TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(
- 0xC02D, true, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_ECDSA, B_AES_128_GCM, M_NULL, H_SHA256),
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(
- 0xC031, true, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
+ // AES_128(GCM) - DHE
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(
0x009E, true, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
@@ -157,7 +143,7 @@
ProtocolVersion.PROTOCOLS_OF_12,
K_DHE_DSS, B_AES_128_GCM, M_NULL, H_SHA256),
- // AES_256(CBC)
+ // AES_256(CBC) - ECDHE
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(
0xC024, true, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "",
ProtocolVersion.PROTOCOLS_OF_12,
@@ -166,18 +152,18 @@
0xC028, true, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "",
ProtocolVersion.PROTOCOLS_OF_12,
K_ECDHE_RSA, B_AES_256, M_SHA384, H_SHA384),
- TLS_RSA_WITH_AES_256_CBC_SHA256(
- 0x003D, true, "TLS_RSA_WITH_AES_256_CBC_SHA256", "",
+
+ // AES_128(CBC) - ECDHE
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(
+ 0xC023, true, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
- K_RSA, B_AES_256, M_SHA256, H_SHA256),
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(
- 0xC026, true, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", "",
+ K_ECDHE_ECDSA, B_AES_128, M_SHA256, H_SHA256),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(
+ 0xC027, true, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_ECDSA, B_AES_256, M_SHA384, H_SHA384),
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(
- 0xC02A, true, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_RSA, B_AES_256, M_SHA384, H_SHA384),
+ K_ECDHE_RSA, B_AES_128, M_SHA256, H_SHA256),
+
+ // AES_256(CBC) - DHE
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(
0x006B, true, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "",
ProtocolVersion.PROTOCOLS_OF_12,
@@ -187,6 +173,65 @@
ProtocolVersion.PROTOCOLS_OF_12,
K_DHE_DSS, B_AES_256, M_SHA256, H_SHA256),
+ // AES_128(CBC) - DHE
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(
+ 0x0067, true, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_DHE_RSA, B_AES_128, M_SHA256, H_SHA256),
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(
+ 0x0040, true, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_DHE_DSS, B_AES_128, M_SHA256, H_SHA256),
+
+ //
+ // not forward screcy cipher suites.
+ //
+
+ // AES_256(GCM)
+ TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(
+ 0xC02E, true, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_ECDSA, B_AES_256_GCM, M_NULL, H_SHA384),
+ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(
+ 0xC032, true, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
+
+ // AES_128(GCM)
+ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(
+ 0xC02D, true, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_ECDSA, B_AES_128_GCM, M_NULL, H_SHA256),
+ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(
+ 0xC031, true, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
+
+ // AES_256(CBC)
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(
+ 0xC026, true, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_ECDSA, B_AES_256, M_SHA384, H_SHA384),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(
+ 0xC02A, true, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_RSA, B_AES_256, M_SHA384, H_SHA384),
+
+ // AES_128(CBC)
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(
+ 0xC025, true, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_ECDSA, B_AES_128, M_SHA256, H_SHA256),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(
+ 0xC029, true, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_ECDH_RSA, B_AES_128, M_SHA256, H_SHA256),
+
+ //
+ // Legacy, used for compatibility
+ //
+
+ // AES_256(CBC) - ECDHE - Using SHA
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(
0xC00A, true, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
@@ -195,18 +240,18 @@
0xC014, true, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
K_ECDHE_RSA, B_AES_256, M_SHA, H_SHA256),
- TLS_RSA_WITH_AES_256_CBC_SHA(
- 0x0035, true, "TLS_RSA_WITH_AES_256_CBC_SHA", "",
+
+ // AES_128(CBC) - ECDHE - using SHA
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(
+ 0xC009, true, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
- K_RSA, B_AES_256, M_SHA, H_SHA256),
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(
- 0xC005, true, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "",
+ K_ECDHE_ECDSA, B_AES_128, M_SHA, H_SHA256),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(
+ 0xC013, true, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_ECDSA, B_AES_256, M_SHA, H_SHA256),
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(
- 0xC00F, true, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_RSA, B_AES_256, M_SHA, H_SHA256),
+ K_ECDHE_RSA, B_AES_128, M_SHA, H_SHA256),
+
+ // AES_256(CBC) - DHE - Using SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA(
0x0039, true, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
@@ -216,56 +261,7 @@
ProtocolVersion.PROTOCOLS_TO_12,
K_DHE_DSS, B_AES_256, M_SHA, H_SHA256),
- // AES_128(CBC)
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(
- 0xC023, true, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDHE_ECDSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(
- 0xC027, true, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDHE_RSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_RSA_WITH_AES_128_CBC_SHA256(
- 0x003C, true, "TLS_RSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_RSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(
- 0xC025, true, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_ECDSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(
- 0xC029, true, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_ECDH_RSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(
- 0x0067, true, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_DHE_RSA, B_AES_128, M_SHA256, H_SHA256),
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(
- 0x0040, true, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "",
- ProtocolVersion.PROTOCOLS_OF_12,
- K_DHE_DSS, B_AES_128, M_SHA256, H_SHA256),
-
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(
- 0xC009, true, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDHE_ECDSA, B_AES_128, M_SHA, H_SHA256),
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(
- 0xC013, true, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDHE_RSA, B_AES_128, M_SHA, H_SHA256),
- TLS_RSA_WITH_AES_128_CBC_SHA(
- 0x002F, true, "TLS_RSA_WITH_AES_128_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_RSA, B_AES_128, M_SHA, H_SHA256),
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(
- 0xC004, true, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_ECDSA, B_AES_128, M_SHA, H_SHA256),
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(
- 0xC00E, true, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_RSA, B_AES_128, M_SHA, H_SHA256),
+ // AES_128(CBC) - DHE - using SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA(
0x0033, true, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
@@ -275,7 +271,67 @@
ProtocolVersion.PROTOCOLS_TO_12,
K_DHE_DSS, B_AES_128, M_SHA, H_SHA256),
- // 3DES_EDE
+ // AES_256(CBC) - using SHA, not forward screcy
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(
+ 0xC005, true, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_ECDSA, B_AES_256, M_SHA, H_SHA256),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(
+ 0xC00F, true, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_RSA, B_AES_256, M_SHA, H_SHA256),
+
+ // AES_128(CBC) - using SHA, not forward screcy
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(
+ 0xC004, true, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_ECDSA, B_AES_128, M_SHA, H_SHA256),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(
+ 0xC00E, true, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_RSA, B_AES_128, M_SHA, H_SHA256),
+
+ //
+ // deprecated, used for compatibility
+ //
+
+ // RSA, AES_256(GCM)
+ TLS_RSA_WITH_AES_256_GCM_SHA384(
+ 0x009D, true, "TLS_RSA_WITH_AES_256_GCM_SHA384", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
+
+ // RSA, AES_128(GCM)
+ TLS_RSA_WITH_AES_128_GCM_SHA256(
+ 0x009C, true, "TLS_RSA_WITH_AES_128_GCM_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_RSA, B_AES_128_GCM, M_NULL, H_SHA256),
+
+ // RSA, AES_256(CBC)
+ TLS_RSA_WITH_AES_256_CBC_SHA256(
+ 0x003D, true, "TLS_RSA_WITH_AES_256_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_RSA, B_AES_256, M_SHA256, H_SHA256),
+
+ // RSA, AES_128(CBC)
+ TLS_RSA_WITH_AES_128_CBC_SHA256(
+ 0x003C, true, "TLS_RSA_WITH_AES_128_CBC_SHA256", "",
+ ProtocolVersion.PROTOCOLS_OF_12,
+ K_RSA, B_AES_128, M_SHA256, H_SHA256),
+
+ // RSA, AES_256(CBC) - using SHA, not forward screcy
+ TLS_RSA_WITH_AES_256_CBC_SHA(
+ 0x0035, true, "TLS_RSA_WITH_AES_256_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_RSA, B_AES_256, M_SHA, H_SHA256),
+
+ // RSA, AES_128(CBC) - using SHA, not forward screcy
+ TLS_RSA_WITH_AES_128_CBC_SHA(
+ 0x002F, true, "TLS_RSA_WITH_AES_128_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_RSA, B_AES_128, M_SHA, H_SHA256),
+
+ // 3DES_EDE, forward secrecy.
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA(
0xC008, true, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
@@ -284,19 +340,6 @@
0xC012, true, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "",
ProtocolVersion.PROTOCOLS_TO_12,
K_ECDHE_RSA, B_3DES, M_SHA, H_SHA256),
- SSL_RSA_WITH_3DES_EDE_CBC_SHA(
- 0x000A, true, "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
- "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_RSA, B_3DES, M_SHA, H_SHA256),
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(
- 0xC003, true, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_ECDSA, B_3DES, M_SHA, H_SHA256),
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(
- 0xC00D, true, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "",
- ProtocolVersion.PROTOCOLS_TO_12,
- K_ECDH_RSA, B_3DES, M_SHA, H_SHA256),
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA(
0x0016, true, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -308,6 +351,21 @@
ProtocolVersion.PROTOCOLS_TO_12,
K_DHE_DSS, B_3DES, M_SHA, H_SHA256),
+ // 3DES_EDE, not forward secrecy.
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(
+ 0xC003, true, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_ECDSA, B_3DES, M_SHA, H_SHA256),
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(
+ 0xC00D, true, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_ECDH_RSA, B_3DES, M_SHA, H_SHA256),
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA(
+ 0x000A, true, "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ ProtocolVersion.PROTOCOLS_TO_12,
+ K_RSA, B_3DES, M_SHA, H_SHA256),
+
// Renegotiation protection request Signalling Cipher Suite Value (SCSV).
TLS_EMPTY_RENEGOTIATION_INFO_SCSV( // RFC 5746, TLS 1.2 and prior
0x00FF, true, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", "",
--- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Wed Apr 10 10:46:53 2019 +0530
@@ -127,7 +127,7 @@
if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm(
shc.peerRequestedSignatureSchemes,
- x509Possession.popPrivateKey,
+ x509Possession,
shc.negotiatedProtocol);
if (signatureScheme == null) {
// Unlikely, the credentials generator should have
--- a/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -58,7 +58,7 @@
}
@Override
- public synchronized void close() throws IOException {
+ public void close() throws IOException {
if (!isClosed) {
super.close();
}
--- a/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -58,13 +58,18 @@
}
@Override
- public synchronized void close() throws IOException {
- if (!isClosed) {
- if (fragmenter != null && fragmenter.hasAlert()) {
- isCloseWaiting = true;
- } else {
- super.close();
+ public void close() throws IOException {
+ recordLock.lock();
+ try {
+ if (!isClosed) {
+ if (fragmenter != null && fragmenter.hasAlert()) {
+ isCloseWaiting = true;
+ } else {
+ super.close();
+ }
}
+ } finally {
+ recordLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Wed Apr 10 10:46:53 2019 +0530
@@ -31,9 +31,7 @@
import java.security.CryptoPrimitive;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
-import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
@@ -285,14 +283,13 @@
"No expected EC server cert for ECDH client key exchange");
}
- PrivateKey privateKey = x509Possession.popPrivateKey;
- if (!privateKey.getAlgorithm().equals("EC")) {
+ ECParameterSpec params = x509Possession.getECParameterSpec();
+ if (params == null) {
// unlikely, have been checked during cipher suite negotiation.
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Not EC server cert for ECDH client key exchange");
}
- ECParameterSpec params = ((ECPrivateKey)privateKey).getParams();
NamedGroup namedGroup = NamedGroup.valueOf(params);
if (namedGroup == null) {
// unlikely, have been checked during cipher suite negotiation.
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Wed Apr 10 10:46:53 2019 +0530
@@ -35,7 +35,6 @@
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
-import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
@@ -265,12 +264,12 @@
continue;
}
- PrivateKey privateKey = ((X509Possession)poss).popPrivateKey;
- if (!privateKey.getAlgorithm().equals("EC")) {
+ ECParameterSpec params =
+ ((X509Possession)poss).getECParameterSpec();
+ if (params == null) {
continue;
}
- ECParameterSpec params = ((ECPrivateKey)privateKey).getParams();
NamedGroup ng = NamedGroup.valueOf(params);
if (ng == null) {
// unlikely, have been checked during cipher suite negotiation.
--- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Wed Apr 10 10:46:53 2019 +0530
@@ -142,7 +142,7 @@
if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm(
shc.peerRequestedSignatureSchemes,
- x509Possession.popPrivateKey,
+ x509Possession,
shc.negotiatedProtocol);
if (signatureScheme == null) {
// Unlikely, the credentials generator should have
--- a/src/java.base/share/classes/sun/security/ssl/EphemeralKeyManager.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/EphemeralKeyManager.java Wed Apr 10 10:46:53 2019 +0530
@@ -26,6 +26,7 @@
package sun.security.ssl;
import java.security.*;
+import java.util.concurrent.locks.ReentrantLock;
/**
* The "KeyManager" for ephemeral RSA keys. Ephemeral DH and ECDH keys
@@ -48,6 +49,8 @@
new EphemeralKeyPair(null),
};
+ private final ReentrantLock cachedKeysLock = new ReentrantLock();
+
EphemeralKeyManager() {
// empty
}
@@ -65,20 +68,32 @@
index = INDEX_RSA1024;
}
- synchronized (keys) {
- KeyPair kp = keys[index].getKeyPair();
- if (kp == null) {
- try {
- KeyPairGenerator kgen = KeyPairGenerator.getInstance("RSA");
- kgen.initialize(length, random);
- keys[index] = new EphemeralKeyPair(kgen.genKeyPair());
- kp = keys[index].getKeyPair();
- } catch (Exception e) {
- // ignore
- }
- }
+ KeyPair kp = keys[index].getKeyPair();
+ if (kp != null) {
return kp;
}
+
+ cachedKeysLock.lock();
+ try {
+ // double check
+ kp = keys[index].getKeyPair();
+ if (kp != null) {
+ return kp;
+ }
+
+ try {
+ KeyPairGenerator kgen = KeyPairGenerator.getInstance("RSA");
+ kgen.initialize(length, random);
+ keys[index] = new EphemeralKeyPair(kgen.genKeyPair());
+ kp = keys[index].getKeyPair();
+ } catch (Exception e) {
+ // ignore
+ }
+ } finally {
+ cachedKeysLock.unlock();
+ }
+
+ return kp;
}
/**
--- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java Wed Apr 10 10:46:53 2019 +0530
@@ -30,6 +30,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
+import java.util.concurrent.locks.ReentrantLock;
import static sun.security.ssl.ClientHello.ClientHelloMessage;
/**
@@ -45,6 +46,8 @@
private volatile D13HelloCookieManager d13HelloCookieManager;
private volatile T13HelloCookieManager t13HelloCookieManager;
+ private final ReentrantLock managerLock = new ReentrantLock();
+
Builder(SecureRandom secureRandom) {
this.secureRandom = secureRandom;
}
@@ -56,11 +59,14 @@
return d13HelloCookieManager;
}
- synchronized (this) {
+ managerLock.lock();
+ try {
if (d13HelloCookieManager == null) {
d13HelloCookieManager =
new D13HelloCookieManager(secureRandom);
}
+ } finally {
+ managerLock.unlock();
}
return d13HelloCookieManager;
@@ -69,11 +75,14 @@
return d10HelloCookieManager;
}
- synchronized (this) {
+ managerLock.lock();
+ try {
if (d10HelloCookieManager == null) {
d10HelloCookieManager =
new D10HelloCookieManager(secureRandom);
}
+ } finally {
+ managerLock.unlock();
}
return d10HelloCookieManager;
@@ -84,11 +93,14 @@
return t13HelloCookieManager;
}
- synchronized (this) {
+ managerLock.lock();
+ try {
if (t13HelloCookieManager == null) {
t13HelloCookieManager =
new T13HelloCookieManager(secureRandom);
}
+ } finally {
+ managerLock.unlock();
}
return t13HelloCookieManager;
@@ -114,6 +126,8 @@
private byte[] cookieSecret;
private byte[] legacySecret;
+ private final ReentrantLock d10ManagerLock = new ReentrantLock();
+
D10HelloCookieManager(SecureRandom secureRandom) {
this.secureRandom = secureRandom;
@@ -131,7 +145,8 @@
int version;
byte[] secret;
- synchronized (this) {
+ d10ManagerLock.lock();
+ try {
version = cookieVersion;
secret = cookieSecret;
@@ -142,6 +157,8 @@
}
cookieVersion++;
+ } finally {
+ d10ManagerLock.unlock();
}
MessageDigest md;
@@ -168,12 +185,15 @@
}
byte[] secret;
- synchronized (this) {
+ d10ManagerLock.lock();
+ try {
if (((cookieVersion >> 24) & 0xFF) == cookie[0]) {
secret = cookieSecret;
} else {
secret = legacySecret; // including out of window cookies
}
+ } finally {
+ d10ManagerLock.unlock();
}
MessageDigest md;
@@ -218,6 +238,8 @@
private final byte[] cookieSecret;
private final byte[] legacySecret;
+ private final ReentrantLock t13ManagerLock = new ReentrantLock();
+
T13HelloCookieManager(SecureRandom secureRandom) {
this.secureRandom = secureRandom;
this.cookieVersion = secureRandom.nextInt();
@@ -234,7 +256,8 @@
int version;
byte[] secret;
- synchronized (this) {
+ t13ManagerLock.lock();
+ try {
version = cookieVersion;
secret = cookieSecret;
@@ -245,6 +268,8 @@
}
cookieVersion++; // allow wrapped version number
+ } finally {
+ t13ManagerLock.unlock();
}
MessageDigest md;
@@ -313,12 +338,15 @@
Arrays.copyOfRange(cookie, 3 + hashLen, cookie.length);
byte[] secret;
- synchronized (this) {
+ t13ManagerLock.lock();
+ try {
if ((byte)((cookieVersion >> 24) & 0xFF) == cookie[2]) {
secret = cookieSecret;
} else {
secret = legacySecret; // including out of window cookies
}
+ } finally {
+ t13ManagerLock.unlock();
}
MessageDigest md;
--- a/src/java.base/share/classes/sun/security/ssl/InputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/InputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -31,6 +31,7 @@
import java.io.OutputStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
+import java.util.concurrent.locks.ReentrantLock;
import javax.crypto.BadPaddingException;
import sun.security.ssl.SSLCipher.SSLReadCipher;
@@ -43,10 +44,10 @@
abstract class InputRecord implements Record, Closeable {
SSLReadCipher readCipher;
// Needed for KeyUpdate, used after Handshake.Finished
- TransportContext tc;
+ TransportContext tc;
final HandshakeHash handshakeHash;
- boolean isClosed;
+ volatile boolean isClosed;
// The ClientHello version to accept. If set to ProtocolVersion.SSL20Hello
// and the first message we read is a ClientHello in V2 format, we convert
@@ -56,6 +57,8 @@
// fragment size
int fragmentSize;
+ final ReentrantLock recordLock = new ReentrantLock();
+
InputRecord(HandshakeHash handshakeHash, SSLReadCipher readCipher) {
this.readCipher = readCipher;
this.helloVersion = ProtocolVersion.TLS10;
@@ -92,14 +95,19 @@
* and flag the record as holding no data.
*/
@Override
- public synchronized void close() throws IOException {
- if (!isClosed) {
- isClosed = true;
- readCipher.dispose();
+ public void close() throws IOException {
+ recordLock.lock();
+ try {
+ if (!isClosed) {
+ isClosed = true;
+ readCipher.dispose();
+ }
+ } finally {
+ recordLock.unlock();
}
}
- synchronized boolean isClosed() {
+ boolean isClosed() {
return isClosed;
}
--- a/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -30,6 +30,7 @@
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.concurrent.locks.ReentrantLock;
import sun.security.ssl.SSLCipher.SSLWriteCipher;
/**
@@ -68,6 +69,8 @@
// closed or not?
volatile boolean isClosed;
+ final ReentrantLock recordLock = new ReentrantLock();
+
/*
* Mappings from V3 cipher suite encodings to their pure V2 equivalents.
* This is taken from the SSL V3 specification, Appendix E.
@@ -89,15 +92,25 @@
// Please set packetSize and protocolVersion in the implementation.
}
- synchronized void setVersion(ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
+ void setVersion(ProtocolVersion protocolVersion) {
+ recordLock.lock();
+ try {
+ this.protocolVersion = protocolVersion;
+ } finally {
+ recordLock.unlock();
+ }
}
/*
* Updates helloVersion of this record.
*/
- synchronized void setHelloVersion(ProtocolVersion helloVersion) {
- this.helloVersion = helloVersion;
+ void setHelloVersion(ProtocolVersion helloVersion) {
+ recordLock.lock();
+ try {
+ this.helloVersion = helloVersion;
+ } finally {
+ recordLock.unlock();
+ }
}
/*
@@ -108,9 +121,14 @@
return false;
}
- synchronized boolean seqNumIsHuge() {
- return (writeCipher.authenticator != null) &&
+ boolean seqNumIsHuge() {
+ recordLock.lock();
+ try {
+ return (writeCipher.authenticator != null) &&
writeCipher.authenticator.seqNumIsHuge();
+ } finally {
+ recordLock.unlock();
+ }
}
// SSLEngine and SSLSocket
@@ -148,68 +166,93 @@
}
// Change write ciphers, may use change_cipher_spec record.
- synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
+ void changeWriteCiphers(SSLWriteCipher writeCipher,
boolean useChangeCipherSpec) throws IOException {
- if (isClosed()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("outbound has closed, ignore outbound " +
- "change_cipher_spec message");
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
+ return;
+ }
+
+ if (useChangeCipherSpec) {
+ encodeChangeCipherSpec();
}
- return;
- }
- if (useChangeCipherSpec) {
- encodeChangeCipherSpec();
+ /*
+ * Dispose of any intermediate state in the underlying cipher.
+ * For PKCS11 ciphers, this will release any attached sessions,
+ * and thus make finalization faster.
+ *
+ * Since MAC's doFinal() is called for every SSL/TLS packet, it's
+ * not necessary to do the same with MAC's.
+ */
+ writeCipher.dispose();
+
+ this.writeCipher = writeCipher;
+ this.isFirstAppOutputRecord = true;
+ } finally {
+ recordLock.unlock();
}
-
- /*
- * Dispose of any intermediate state in the underlying cipher.
- * For PKCS11 ciphers, this will release any attached sessions,
- * and thus make finalization faster.
- *
- * Since MAC's doFinal() is called for every SSL/TLS packet, it's
- * not necessary to do the same with MAC's.
- */
- writeCipher.dispose();
-
- this.writeCipher = writeCipher;
- this.isFirstAppOutputRecord = true;
}
// Change write ciphers using key_update handshake message.
- synchronized void changeWriteCiphers(SSLWriteCipher writeCipher,
+ void changeWriteCiphers(SSLWriteCipher writeCipher,
byte keyUpdateRequest) throws IOException {
- if (isClosed()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("outbound has closed, ignore outbound " +
- "key_update handshake message");
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "key_update handshake message");
+ }
+ return;
}
- return;
- }
- // encode the handshake message, KeyUpdate
- byte[] hm = HANDSHAKE_MESSAGE_KEY_UPDATE.clone();
- hm[hm.length - 1] = keyUpdateRequest;
- encodeHandshake(hm, 0, hm.length);
- flush();
+ // encode the handshake message, KeyUpdate
+ byte[] hm = HANDSHAKE_MESSAGE_KEY_UPDATE.clone();
+ hm[hm.length - 1] = keyUpdateRequest;
+ encodeHandshake(hm, 0, hm.length);
+ flush();
- // Dispose of any intermediate state in the underlying cipher.
- writeCipher.dispose();
+ // Dispose of any intermediate state in the underlying cipher.
+ writeCipher.dispose();
- this.writeCipher = writeCipher;
- this.isFirstAppOutputRecord = true;
+ this.writeCipher = writeCipher;
+ this.isFirstAppOutputRecord = true;
+ } finally {
+ recordLock.unlock();
+ }
}
- synchronized void changePacketSize(int packetSize) {
- this.packetSize = packetSize;
+ void changePacketSize(int packetSize) {
+ recordLock.lock();
+ try {
+ this.packetSize = packetSize;
+ } finally {
+ recordLock.unlock();
+ }
}
- synchronized void changeFragmentSize(int fragmentSize) {
- this.fragmentSize = fragmentSize;
+ void changeFragmentSize(int fragmentSize) {
+ recordLock.lock();
+ try {
+ this.fragmentSize = fragmentSize;
+ } finally {
+ recordLock.unlock();
+ }
}
- synchronized int getMaxPacketSize() {
- return packetSize;
+ int getMaxPacketSize() {
+ recordLock.lock();
+ try {
+ return packetSize;
+ } finally {
+ recordLock.unlock();
+ }
}
// apply to DTLS SSLEngine
@@ -228,13 +271,18 @@
}
@Override
- public synchronized void close() throws IOException {
- if (isClosed) {
- return;
+ public void close() throws IOException {
+ recordLock.lock();
+ try {
+ if (isClosed) {
+ return;
+ }
+
+ isClosed = true;
+ writeCipher.dispose();
+ } finally {
+ recordLock.unlock();
}
-
- isClosed = true;
- writeCipher.dispose();
}
boolean isClosed() {
--- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -30,6 +30,7 @@
import java.security.*;
import java.security.cert.*;
import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
import javax.net.ssl.*;
import sun.security.action.GetPropertyAction;
import sun.security.provider.certpath.AlgorithmChecker;
@@ -69,6 +70,8 @@
private volatile StatusResponseManager statusResponseManager;
+ private final ReentrantLock contextLock = new ReentrantLock();
+
SSLContextImpl() {
ephemeralKeyManager = new EphemeralKeyManager();
clientCache = new SSLSessionContextImpl();
@@ -230,11 +233,14 @@
// Used for DTLS in server mode only.
HelloCookieManager getHelloCookieManager(ProtocolVersion protocolVersion) {
if (helloCookieManagerBuilder == null) {
- synchronized (this) {
+ contextLock.lock();
+ try {
if (helloCookieManagerBuilder == null) {
helloCookieManagerBuilder =
new HelloCookieManager.Builder(secureRandom);
}
+ } finally {
+ contextLock.unlock();
}
}
@@ -243,7 +249,8 @@
StatusResponseManager getStatusResponseManager() {
if (serverEnableStapling && statusResponseManager == null) {
- synchronized (this) {
+ contextLock.lock();
+ try {
if (statusResponseManager == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
SSLLogger.finest(
@@ -251,6 +258,8 @@
}
statusResponseManager = new StatusResponseManager();
}
+ } finally {
+ contextLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -33,6 +33,7 @@
import java.security.PrivilegedExceptionAction;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiFunction;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
@@ -54,6 +55,7 @@
final class SSLEngineImpl extends SSLEngine implements SSLTransport {
private final SSLContextImpl sslContext;
final TransportContext conContext;
+ private final ReentrantLock engineLock = new ReentrantLock();
/**
* Constructor for an SSLEngine from SSLContext, without
@@ -93,57 +95,68 @@
}
@Override
- public synchronized void beginHandshake() throws SSLException {
- if (conContext.isUnsureMode) {
- throw new IllegalStateException(
- "Client/Server mode has not yet been set.");
- }
-
+ public void beginHandshake() throws SSLException {
+ engineLock.lock();
try {
- conContext.kickstart();
- } catch (IOException ioe) {
- throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
- "Couldn't kickstart handshaking", ioe);
- } catch (Exception ex) { // including RuntimeException
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "Fail to begin handshake", ex);
+ if (conContext.isUnsureMode) {
+ throw new IllegalStateException(
+ "Client/Server mode has not yet been set.");
+ }
+
+ try {
+ conContext.kickstart();
+ } catch (IOException ioe) {
+ throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "Couldn't kickstart handshaking", ioe);
+ } catch (Exception ex) { // including RuntimeException
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "Fail to begin handshake", ex);
+ }
+ } finally {
+ engineLock.unlock();
}
}
@Override
- public synchronized SSLEngineResult wrap(ByteBuffer[] appData,
+ public SSLEngineResult wrap(ByteBuffer[] appData,
int offset, int length, ByteBuffer netData) throws SSLException {
return wrap(appData, offset, length, new ByteBuffer[]{ netData }, 0, 1);
}
// @Override
- public synchronized SSLEngineResult wrap(
+ public SSLEngineResult wrap(
ByteBuffer[] srcs, int srcsOffset, int srcsLength,
ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
- if (conContext.isUnsureMode) {
- throw new IllegalStateException(
- "Client/Server mode has not yet been set.");
- }
-
- // See if the handshaker needs to report back some SSLException.
- checkTaskThrown();
-
- // check parameters
- checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
-
+ engineLock.lock();
try {
- return writeRecord(
- srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
- } catch (SSLProtocolException spe) {
- // may be an unexpected handshake message
- throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, spe);
- } catch (IOException ioe) {
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "problem wrapping app data", ioe);
- } catch (Exception ex) { // including RuntimeException
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "Fail to wrap application data", ex);
+ if (conContext.isUnsureMode) {
+ throw new IllegalStateException(
+ "Client/Server mode has not yet been set.");
+ }
+
+ // See if the handshaker needs to report back some SSLException.
+ checkTaskThrown();
+
+ // check parameters
+ checkParams(srcs, srcsOffset, srcsLength,
+ dsts, dstsOffset, dstsLength);
+
+ try {
+ return writeRecord(
+ srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
+ } catch (SSLProtocolException spe) {
+ // may be an unexpected handshake message
+ throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, spe);
+ } catch (IOException ioe) {
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "problem wrapping app data", ioe);
+ } catch (Exception ex) { // including RuntimeException
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "Fail to wrap application data", ex);
+ }
+ } finally {
+ engineLock.unlock();
}
}
@@ -428,47 +441,53 @@
}
@Override
- public synchronized SSLEngineResult unwrap(ByteBuffer src,
+ public SSLEngineResult unwrap(ByteBuffer src,
ByteBuffer[] dsts, int offset, int length) throws SSLException {
return unwrap(
new ByteBuffer[]{src}, 0, 1, dsts, offset, length);
}
// @Override
- public synchronized SSLEngineResult unwrap(
+ public SSLEngineResult unwrap(
ByteBuffer[] srcs, int srcsOffset, int srcsLength,
ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
- if (conContext.isUnsureMode) {
- throw new IllegalStateException(
- "Client/Server mode has not yet been set.");
- }
-
- // See if the handshaker needs to report back some SSLException.
- checkTaskThrown();
-
- // check parameters
- checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
-
+ engineLock.lock();
try {
- return readRecord(
- srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
- } catch (SSLProtocolException spe) {
- // may be an unexpected handshake message
- throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- spe.getMessage(), spe);
- } catch (IOException ioe) {
- /*
- * Don't reset position so it looks like we didn't
- * consume anything. We did consume something, and it
- * got us into this situation, so report that much back.
- * Our days of consuming are now over anyway.
- */
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "problem unwrapping net record", ioe);
- } catch (Exception ex) { // including RuntimeException
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "Fail to unwrap network record", ex);
+ if (conContext.isUnsureMode) {
+ throw new IllegalStateException(
+ "Client/Server mode has not yet been set.");
+ }
+
+ // See if the handshaker needs to report back some SSLException.
+ checkTaskThrown();
+
+ // check parameters
+ checkParams(srcs, srcsOffset, srcsLength,
+ dsts, dstsOffset, dstsLength);
+
+ try {
+ return readRecord(
+ srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
+ } catch (SSLProtocolException spe) {
+ // may be an unexpected handshake message
+ throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+ spe.getMessage(), spe);
+ } catch (IOException ioe) {
+ /*
+ * Don't reset position so it looks like we didn't
+ * consume anything. We did consume something, and it
+ * got us into this situation, so report that much back.
+ * Our days of consuming are now over anyway.
+ */
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "problem unwrapping net record", ioe);
+ } catch (Exception ex) { // including RuntimeException
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "Fail to unwrap network record", ex);
+ }
+ } finally {
+ engineLock.unlock();
}
}
@@ -703,61 +722,87 @@
}
@Override
- public synchronized Runnable getDelegatedTask() {
- if (conContext.handshakeContext != null && // PRE or POST handshake
- !conContext.handshakeContext.taskDelegated &&
- !conContext.handshakeContext.delegatedActions.isEmpty()) {
- conContext.handshakeContext.taskDelegated = true;
- return new DelegatedTask(this);
+ public Runnable getDelegatedTask() {
+ engineLock.lock();
+ try {
+ if (conContext.handshakeContext != null && // PRE or POST handshake
+ !conContext.handshakeContext.taskDelegated &&
+ !conContext.handshakeContext.delegatedActions.isEmpty()) {
+ conContext.handshakeContext.taskDelegated = true;
+ return new DelegatedTask(this);
+ }
+ } finally {
+ engineLock.unlock();
}
return null;
}
@Override
- public synchronized void closeInbound() throws SSLException {
- if (isInboundDone()) {
- return;
- }
+ public void closeInbound() throws SSLException {
+ engineLock.lock();
+ try {
+ if (isInboundDone()) {
+ return;
+ }
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.finest("Closing inbound of SSLEngine");
- }
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.finest("Closing inbound of SSLEngine");
+ }
- // Is it ready to close inbound?
- //
- // No need to throw exception if the initial handshake is not started.
- if (!conContext.isInputCloseNotified &&
- (conContext.isNegotiated || conContext.handshakeContext != null)) {
+ // Is it ready to close inbound?
+ //
+ // No exception if the initial handshake is not started.
+ if (!conContext.isInputCloseNotified &&
+ (conContext.isNegotiated ||
+ conContext.handshakeContext != null)) {
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "closing inbound before receiving peer's close_notify");
+ throw conContext.fatal(Alert.INTERNAL_ERROR,
+ "closing inbound before receiving peer's close_notify");
+ }
+
+ conContext.closeInbound();
+ } finally {
+ engineLock.unlock();
}
-
- conContext.closeInbound();
}
@Override
- public synchronized boolean isInboundDone() {
- return conContext.isInboundClosed();
+ public boolean isInboundDone() {
+ engineLock.lock();
+ try {
+ return conContext.isInboundClosed();
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized void closeOutbound() {
- if (conContext.isOutboundClosed()) {
- return;
- }
+ public void closeOutbound() {
+ engineLock.lock();
+ try {
+ if (conContext.isOutboundClosed()) {
+ return;
+ }
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.finest("Closing outbound of SSLEngine");
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.finest("Closing outbound of SSLEngine");
+ }
+
+ conContext.closeOutbound();
+ } finally {
+ engineLock.unlock();
}
-
- conContext.closeOutbound();
}
@Override
- public synchronized boolean isOutboundDone() {
- return conContext.isOutboundDone();
+ public boolean isOutboundDone() {
+ engineLock.lock();
+ try {
+ return conContext.isOutboundDone();
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
@@ -766,14 +811,24 @@
}
@Override
- public synchronized String[] getEnabledCipherSuites() {
- return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
+ public String[] getEnabledCipherSuites() {
+ engineLock.lock();
+ try {
+ return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized void setEnabledCipherSuites(String[] suites) {
- conContext.sslConfig.enabledCipherSuites =
- CipherSuite.validValuesOf(suites);
+ public void setEnabledCipherSuites(String[] suites) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.enabledCipherSuites =
+ CipherSuite.validValuesOf(suites);
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
@@ -783,119 +838,214 @@
}
@Override
- public synchronized String[] getEnabledProtocols() {
- return ProtocolVersion.toStringArray(
- conContext.sslConfig.enabledProtocols);
- }
-
- @Override
- public synchronized void setEnabledProtocols(String[] protocols) {
- if (protocols == null) {
- throw new IllegalArgumentException("Protocols cannot be null");
+ public String[] getEnabledProtocols() {
+ engineLock.lock();
+ try {
+ return ProtocolVersion.toStringArray(
+ conContext.sslConfig.enabledProtocols);
+ } finally {
+ engineLock.unlock();
}
-
- conContext.sslConfig.enabledProtocols =
- ProtocolVersion.namesOf(protocols);
}
@Override
- public synchronized SSLSession getSession() {
- return conContext.conSession;
- }
+ public void setEnabledProtocols(String[] protocols) {
+ engineLock.lock();
+ try {
+ if (protocols == null) {
+ throw new IllegalArgumentException("Protocols cannot be null");
+ }
- @Override
- public synchronized SSLSession getHandshakeSession() {
- return conContext.handshakeContext == null ?
- null : conContext.handshakeContext.handshakeSession;
+ conContext.sslConfig.enabledProtocols =
+ ProtocolVersion.namesOf(protocols);
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
- return conContext.getHandshakeStatus();
+ public SSLSession getSession() {
+ engineLock.lock();
+ try {
+ return conContext.conSession;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized void setUseClientMode(boolean mode) {
- conContext.setUseClientMode(mode);
- }
-
- @Override
- public synchronized boolean getUseClientMode() {
- return conContext.sslConfig.isClientMode;
+ public SSLSession getHandshakeSession() {
+ engineLock.lock();
+ try {
+ return conContext.handshakeContext == null ?
+ null : conContext.handshakeContext.handshakeSession;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized void setNeedClientAuth(boolean need) {
- conContext.sslConfig.clientAuthType =
- (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
- ClientAuthType.CLIENT_AUTH_NONE);
+ public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
+ engineLock.lock();
+ try {
+ return conContext.getHandshakeStatus();
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized boolean getNeedClientAuth() {
- return (conContext.sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUIRED);
- }
-
- @Override
- public synchronized void setWantClientAuth(boolean want) {
- conContext.sslConfig.clientAuthType =
- (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
- ClientAuthType.CLIENT_AUTH_NONE);
+ public void setUseClientMode(boolean mode) {
+ engineLock.lock();
+ try {
+ conContext.setUseClientMode(mode);
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized boolean getWantClientAuth() {
- return (conContext.sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUESTED);
- }
-
- @Override
- public synchronized void setEnableSessionCreation(boolean flag) {
- conContext.sslConfig.enableSessionCreation = flag;
+ public boolean getUseClientMode() {
+ engineLock.lock();
+ try {
+ return conContext.sslConfig.isClientMode;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized boolean getEnableSessionCreation() {
- return conContext.sslConfig.enableSessionCreation;
+ public void setNeedClientAuth(boolean need) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.clientAuthType =
+ (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized SSLParameters getSSLParameters() {
- return conContext.sslConfig.getSSLParameters();
- }
-
- @Override
- public synchronized void setSSLParameters(SSLParameters params) {
- conContext.sslConfig.setSSLParameters(params);
-
- if (conContext.sslConfig.maximumPacketSize != 0) {
- conContext.outputRecord.changePacketSize(
- conContext.sslConfig.maximumPacketSize);
+ public boolean getNeedClientAuth() {
+ engineLock.lock();
+ try {
+ return (conContext.sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUIRED);
+ } finally {
+ engineLock.unlock();
}
}
@Override
- public synchronized String getApplicationProtocol() {
- return conContext.applicationProtocol;
+ public void setWantClientAuth(boolean want) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.clientAuthType =
+ (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean getWantClientAuth() {
+ engineLock.lock();
+ try {
+ return (conContext.sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUESTED);
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public void setEnableSessionCreation(boolean flag) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.enableSessionCreation = flag;
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean getEnableSessionCreation() {
+ engineLock.lock();
+ try {
+ return conContext.sslConfig.enableSessionCreation;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized String getHandshakeApplicationProtocol() {
- return conContext.handshakeContext == null ?
- null : conContext.handshakeContext.applicationProtocol;
+ public SSLParameters getSSLParameters() {
+ engineLock.lock();
+ try {
+ return conContext.sslConfig.getSSLParameters();
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public void setSSLParameters(SSLParameters params) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.setSSLParameters(params);
+
+ if (conContext.sslConfig.maximumPacketSize != 0) {
+ conContext.outputRecord.changePacketSize(
+ conContext.sslConfig.maximumPacketSize);
+ }
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public String getApplicationProtocol() {
+ engineLock.lock();
+ try {
+ return conContext.applicationProtocol;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized void setHandshakeApplicationProtocolSelector(
- BiFunction<SSLEngine, List<String>, String> selector) {
- conContext.sslConfig.engineAPSelector = selector;
+ public String getHandshakeApplicationProtocol() {
+ engineLock.lock();
+ try {
+ return conContext.handshakeContext == null ?
+ null : conContext.handshakeContext.applicationProtocol;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
- public synchronized BiFunction<SSLEngine, List<String>, String>
+ public void setHandshakeApplicationProtocolSelector(
+ BiFunction<SSLEngine, List<String>, String> selector) {
+ engineLock.lock();
+ try {
+ conContext.sslConfig.engineAPSelector = selector;
+ } finally {
+ engineLock.unlock();
+ }
+ }
+
+ @Override
+ public BiFunction<SSLEngine, List<String>, String>
getHandshakeApplicationProtocolSelector() {
- return conContext.sslConfig.engineAPSelector;
+ engineLock.lock();
+ try {
+ return conContext.sslConfig.engineAPSelector;
+ } finally {
+ engineLock.unlock();
+ }
}
@Override
@@ -909,38 +1059,42 @@
* null, report back the Exception that happened in the delegated
* task(s).
*/
- private synchronized void checkTaskThrown() throws SSLException {
+ private void checkTaskThrown() throws SSLException {
Exception exc = null;
-
- // First check the handshake context.
- HandshakeContext hc = conContext.handshakeContext;
- if ((hc != null) && (hc.delegatedThrown != null)) {
- exc = hc.delegatedThrown;
- hc.delegatedThrown = null;
- }
+ engineLock.lock();
+ try {
+ // First check the handshake context.
+ HandshakeContext hc = conContext.handshakeContext;
+ if ((hc != null) && (hc.delegatedThrown != null)) {
+ exc = hc.delegatedThrown;
+ hc.delegatedThrown = null;
+ }
- /*
- * hc.delegatedThrown and conContext.delegatedThrown are most likely
- * the same, but it's possible we could have had a non-fatal
- * exception and thus the new HandshakeContext is still valid
- * (alert warning). If so, then we may have a secondary exception
- * waiting to be reported from the TransportContext, so we will
- * need to clear that on a successive call. Otherwise, clear it now.
- */
- if (conContext.delegatedThrown != null) {
- if (exc != null) {
- // hc object comparison
- if (conContext.delegatedThrown == exc) {
- // clear if/only if both are the same
+ /*
+ * hc.delegatedThrown and conContext.delegatedThrown are most
+ * likely the same, but it's possible we could have had a non-fatal
+ * exception and thus the new HandshakeContext is still valid
+ * (alert warning). If so, then we may have a secondary exception
+ * waiting to be reported from the TransportContext, so we will
+ * need to clear that on a successive call. Otherwise, clear it now.
+ */
+ if (conContext.delegatedThrown != null) {
+ if (exc != null) {
+ // hc object comparison
+ if (conContext.delegatedThrown == exc) {
+ // clear if/only if both are the same
+ conContext.delegatedThrown = null;
+ } // otherwise report the hc delegatedThrown
+ } else {
+ // Nothing waiting in HandshakeContext, but one is in the
+ // TransportContext.
+ exc = conContext.delegatedThrown;
conContext.delegatedThrown = null;
- } // otherwise report the hc delegatedThrown
- } else {
- // Nothing waiting in HandshakeContext, but one is in the
- // TransportContext.
- exc = conContext.delegatedThrown;
- conContext.delegatedThrown = null;
+ }
}
+ } finally {
+ engineLock.unlock();
}
// Anything to report?
@@ -998,7 +1152,8 @@
@Override
public void run() {
- synchronized (engine) {
+ engine.engineLock.lock();
+ try {
HandshakeContext hc = engine.conContext.handshakeContext;
if (hc == null || hc.delegatedActions.isEmpty()) {
return;
@@ -1055,6 +1210,8 @@
if (hc != null) {
hc.taskDelegated = false;
}
+ } finally {
+ engine.engineLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -51,13 +51,18 @@
}
@Override
- public synchronized void close() throws IOException {
- if (!isClosed) {
- if (fragmenter != null && fragmenter.hasAlert()) {
- isCloseWaiting = true;
- } else {
- super.close();
+ public void close() throws IOException {
+ recordLock.lock();
+ try {
+ if (!isClosed) {
+ if (fragmenter != null && fragmenter.hasAlert()) {
+ isCloseWaiting = true;
+ } else {
+ super.close();
+ }
}
+ } finally {
+ recordLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
+import java.util.concurrent.locks.ReentrantLock;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
@@ -56,6 +57,7 @@
final class SSLServerSocketImpl extends SSLServerSocket {
private final SSLContextImpl sslContext;
private final SSLConfiguration sslConfig;
+ private final ReentrantLock serverSocketLock = new ReentrantLock();
SSLServerSocketImpl(SSLContextImpl sslContext) throws IOException {
@@ -84,14 +86,24 @@
}
@Override
- public synchronized String[] getEnabledCipherSuites() {
- return CipherSuite.namesOf(sslConfig.enabledCipherSuites);
+ public String[] getEnabledCipherSuites() {
+ serverSocketLock.lock();
+ try {
+ return CipherSuite.namesOf(sslConfig.enabledCipherSuites);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized void setEnabledCipherSuites(String[] suites) {
- sslConfig.enabledCipherSuites =
- CipherSuite.validValuesOf(suites);
+ public void setEnabledCipherSuites(String[] suites) {
+ serverSocketLock.lock();
+ try {
+ sslConfig.enabledCipherSuites =
+ CipherSuite.validValuesOf(suites);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
@@ -106,93 +118,153 @@
}
@Override
- public synchronized String[] getEnabledProtocols() {
- return ProtocolVersion.toStringArray(sslConfig.enabledProtocols);
+ public String[] getEnabledProtocols() {
+ serverSocketLock.lock();
+ try {
+ return ProtocolVersion.toStringArray(sslConfig.enabledProtocols);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized void setEnabledProtocols(String[] protocols) {
- if (protocols == null) {
- throw new IllegalArgumentException("Protocols cannot be null");
- }
-
- sslConfig.enabledProtocols = ProtocolVersion.namesOf(protocols);
- }
+ public void setEnabledProtocols(String[] protocols) {
+ serverSocketLock.lock();
+ try {
+ if (protocols == null) {
+ throw new IllegalArgumentException("Protocols cannot be null");
+ }
- @Override
- public synchronized void setNeedClientAuth(boolean need) {
- sslConfig.clientAuthType =
- (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
- ClientAuthType.CLIENT_AUTH_NONE);
- }
-
- @Override
- public synchronized boolean getNeedClientAuth() {
- return (sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUIRED);
+ sslConfig.enabledProtocols = ProtocolVersion.namesOf(protocols);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized void setWantClientAuth(boolean want) {
- sslConfig.clientAuthType =
- (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
- ClientAuthType.CLIENT_AUTH_NONE);
- }
-
- @Override
- public synchronized boolean getWantClientAuth() {
- return (sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUESTED);
+ public void setNeedClientAuth(boolean need) {
+ serverSocketLock.lock();
+ try {
+ sslConfig.clientAuthType =
+ (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized void setUseClientMode(boolean useClientMode) {
- /*
- * If we need to change the client mode and the enabled
- * protocols and cipher suites haven't specifically been
- * set by the user, change them to the corresponding
- * default ones.
- */
- if (sslConfig.isClientMode != useClientMode) {
- if (sslContext.isDefaultProtocolVesions(
- sslConfig.enabledProtocols)) {
- sslConfig.enabledProtocols =
- sslContext.getDefaultProtocolVersions(!useClientMode);
- }
+ public boolean getNeedClientAuth() {
+ serverSocketLock.lock();
+ try {
+ return (sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUIRED);
+ } finally {
+ serverSocketLock.unlock();
+ }
+ }
- if (sslContext.isDefaultCipherSuiteList(
- sslConfig.enabledCipherSuites)) {
- sslConfig.enabledCipherSuites =
- sslContext.getDefaultCipherSuites(!useClientMode);
- }
+ @Override
+ public void setWantClientAuth(boolean want) {
+ serverSocketLock.lock();
+ try {
+ sslConfig.clientAuthType =
+ (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ serverSocketLock.unlock();
+ }
+ }
- sslConfig.isClientMode = useClientMode;
+ @Override
+ public boolean getWantClientAuth() {
+ serverSocketLock.lock();
+ try {
+ return (sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUESTED);
+ } finally {
+ serverSocketLock.unlock();
}
}
@Override
- public synchronized boolean getUseClientMode() {
- return sslConfig.isClientMode;
- }
+ public void setUseClientMode(boolean useClientMode) {
+ serverSocketLock.lock();
+ try {
+ /*
+ * If we need to change the client mode and the enabled
+ * protocols and cipher suites haven't specifically been
+ * set by the user, change them to the corresponding
+ * default ones.
+ */
+ if (sslConfig.isClientMode != useClientMode) {
+ if (sslContext.isDefaultProtocolVesions(
+ sslConfig.enabledProtocols)) {
+ sslConfig.enabledProtocols =
+ sslContext.getDefaultProtocolVersions(!useClientMode);
+ }
- @Override
- public synchronized void setEnableSessionCreation(boolean flag) {
- sslConfig.enableSessionCreation = flag;
+ if (sslContext.isDefaultCipherSuiteList(
+ sslConfig.enabledCipherSuites)) {
+ sslConfig.enabledCipherSuites =
+ sslContext.getDefaultCipherSuites(!useClientMode);
+ }
+
+ sslConfig.isClientMode = useClientMode;
+ }
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized boolean getEnableSessionCreation() {
- return sslConfig.enableSessionCreation;
+ public boolean getUseClientMode() {
+ serverSocketLock.lock();
+ try {
+ return sslConfig.isClientMode;
+ } finally {
+ serverSocketLock.unlock();
+ }
+ }
+
+ @Override
+ public void setEnableSessionCreation(boolean flag) {
+ serverSocketLock.lock();
+ try {
+ sslConfig.enableSessionCreation = flag;
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized SSLParameters getSSLParameters() {
- return sslConfig.getSSLParameters();
+ public boolean getEnableSessionCreation() {
+ serverSocketLock.lock();
+ try {
+ return sslConfig.enableSessionCreation;
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
- public synchronized void setSSLParameters(SSLParameters params) {
- sslConfig.setSSLParameters(params);
+ public SSLParameters getSSLParameters() {
+ serverSocketLock.lock();
+ try {
+ return sslConfig.getSSLParameters();
+ } finally {
+ serverSocketLock.unlock();
+ }
+ }
+
+ @Override
+ public void setSSLParameters(SSLParameters params) {
+ serverSocketLock.lock();
+ try {
+ sslConfig.setSSLParameters(params);
+ } finally {
+ serverSocketLock.unlock();
+ }
}
@Override
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,6 +38,7 @@
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.ReentrantLock;
import javax.crypto.SecretKey;
import javax.net.ssl.ExtendedSSLSession;
import javax.net.ssl.SNIServerName;
@@ -133,7 +134,9 @@
// The endpoint identification algorithm used to check certificates
// in this session.
- private final String identificationProtocol;
+ private final String identificationProtocol;
+
+ private final ReentrantLock sessionLock = new ReentrantLock();
/*
* Create a new non-rejoinable session, using the default (null)
@@ -289,15 +292,22 @@
return resumptionMasterSecret;
}
- synchronized SecretKey getPreSharedKey() {
- return preSharedKey;
+ SecretKey getPreSharedKey() {
+ sessionLock.lock();
+ try {
+ return preSharedKey;
+ } finally {
+ sessionLock.unlock();
+ }
}
- synchronized SecretKey consumePreSharedKey() {
+ SecretKey consumePreSharedKey() {
+ sessionLock.lock();
try {
return preSharedKey;
} finally {
preSharedKey = null;
+ sessionLock.unlock();
}
}
@@ -313,11 +323,13 @@
* be used once. This method will return the identity and then clear it
* so it cannot be used again.
*/
- synchronized byte[] consumePskIdentity() {
+ byte[] consumePskIdentity() {
+ sessionLock.lock();
try {
return pskIdentity;
} finally {
pskIdentity = null;
+ sessionLock.unlock();
}
}
@@ -393,8 +405,13 @@
}
@Override
- public synchronized boolean isValid() {
- return isRejoinable();
+ public boolean isValid() {
+ sessionLock.lock();
+ try {
+ return isRejoinable();
+ } finally {
+ sessionLock.unlock();
+ }
}
/**
@@ -777,29 +794,35 @@
* no connections will be able to rejoin this session.
*/
@Override
- public synchronized void invalidate() {
- //
- // Can't invalidate the NULL session -- this would be
- // attempted when we get a handshaking error on a brand
- // new connection, with no "real" session yet.
- //
- if (this == nullSession) {
- return;
- }
+ public void invalidate() {
+ sessionLock.lock();
+ try {
+ //
+ // Can't invalidate the NULL session -- this would be
+ // attempted when we get a handshaking error on a brand
+ // new connection, with no "real" session yet.
+ //
+ if (this == nullSession) {
+ return;
+ }
- if (context != null) {
- context.remove(sessionId);
- context = null;
- }
- if (invalidated) {
- return;
- }
- invalidated = true;
- if (SSLLogger.isOn && SSLLogger.isOn("session")) {
- SSLLogger.finest("Invalidated session: " + this);
- }
- for (SSLSessionImpl child : childSessions) {
- child.invalidate();
+ if (context != null) {
+ context.remove(sessionId);
+ context = null;
+ }
+
+ if (invalidated) {
+ return;
+ }
+ invalidated = true;
+ if (SSLLogger.isOn && SSLLogger.isOn("session")) {
+ SSLLogger.finest("Invalidated session: " + this);
+ }
+ for (SSLSessionImpl child : childSessions) {
+ child.invalidate();
+ }
+ } finally {
+ sessionLock.unlock();
}
}
@@ -912,8 +935,13 @@
* Expand the buffer size of both SSL/TLS network packet and
* application data.
*/
- protected synchronized void expandBufferSizes() {
- acceptLargeFragments = true;
+ protected void expandBufferSizes() {
+ sessionLock.lock();
+ try {
+ acceptLargeFragments = true;
+ } finally {
+ sessionLock.unlock();
+ }
}
/**
@@ -921,30 +949,35 @@
* when using this session.
*/
@Override
- public synchronized int getPacketBufferSize() {
- // Use the bigger packet size calculated from maximumPacketSize
- // and negotiatedMaxFragLen.
- int packetSize = 0;
- if (negotiatedMaxFragLen > 0) {
- packetSize = cipherSuite.calculatePacketSize(
- negotiatedMaxFragLen, protocolVersion,
- protocolVersion.isDTLS);
- }
+ public int getPacketBufferSize() {
+ sessionLock.lock();
+ try {
+ // Use the bigger packet size calculated from maximumPacketSize
+ // and negotiatedMaxFragLen.
+ int packetSize = 0;
+ if (negotiatedMaxFragLen > 0) {
+ packetSize = cipherSuite.calculatePacketSize(
+ negotiatedMaxFragLen, protocolVersion,
+ protocolVersion.isDTLS);
+ }
- if (maximumPacketSize > 0) {
- return (maximumPacketSize > packetSize) ?
- maximumPacketSize : packetSize;
- }
+ if (maximumPacketSize > 0) {
+ return (maximumPacketSize > packetSize) ?
+ maximumPacketSize : packetSize;
+ }
+
+ if (packetSize != 0) {
+ return packetSize;
+ }
- if (packetSize != 0) {
- return packetSize;
- }
-
- if (protocolVersion.isDTLS) {
- return DTLSRecord.maxRecordSize;
- } else {
- return acceptLargeFragments ?
- SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
+ if (protocolVersion.isDTLS) {
+ return DTLSRecord.maxRecordSize;
+ } else {
+ return acceptLargeFragments ?
+ SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
+ }
+ } finally {
+ sessionLock.unlock();
}
}
@@ -953,31 +986,36 @@
* expected when using this session.
*/
@Override
- public synchronized int getApplicationBufferSize() {
- // Use the bigger fragment size calculated from maximumPacketSize
- // and negotiatedMaxFragLen.
- int fragmentSize = 0;
- if (maximumPacketSize > 0) {
- fragmentSize = cipherSuite.calculateFragSize(
- maximumPacketSize, protocolVersion,
- protocolVersion.isDTLS);
- }
+ public int getApplicationBufferSize() {
+ sessionLock.lock();
+ try {
+ // Use the bigger fragment size calculated from maximumPacketSize
+ // and negotiatedMaxFragLen.
+ int fragmentSize = 0;
+ if (maximumPacketSize > 0) {
+ fragmentSize = cipherSuite.calculateFragSize(
+ maximumPacketSize, protocolVersion,
+ protocolVersion.isDTLS);
+ }
- if (negotiatedMaxFragLen > 0) {
- return (negotiatedMaxFragLen > fragmentSize) ?
- negotiatedMaxFragLen : fragmentSize;
- }
+ if (negotiatedMaxFragLen > 0) {
+ return (negotiatedMaxFragLen > fragmentSize) ?
+ negotiatedMaxFragLen : fragmentSize;
+ }
+
+ if (fragmentSize != 0) {
+ return fragmentSize;
+ }
- if (fragmentSize != 0) {
- return fragmentSize;
- }
-
- if (protocolVersion.isDTLS) {
- return Record.maxDataSize;
- } else {
- int maxPacketSize = acceptLargeFragments ?
- SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
- return (maxPacketSize - SSLRecord.headerSize);
+ if (protocolVersion.isDTLS) {
+ return Record.maxDataSize;
+ } else {
+ int maxPacketSize = acceptLargeFragments ?
+ SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
+ return (maxPacketSize - SSLRecord.headerSize);
+ }
+ } finally {
+ sessionLock.unlock();
}
}
@@ -989,10 +1027,14 @@
* the negotiated maximum fragment length, or {@code -1} if
* no such length has been negotiated.
*/
- synchronized void setNegotiatedMaxFragSize(
+ void setNegotiatedMaxFragSize(
int negotiatedMaxFragLen) {
-
- this.negotiatedMaxFragLen = negotiatedMaxFragLen;
+ sessionLock.lock();
+ try {
+ this.negotiatedMaxFragLen = negotiatedMaxFragLen;
+ } finally {
+ sessionLock.unlock();
+ }
}
/**
@@ -1002,16 +1044,31 @@
* @return the negotiated maximum fragment length, or {@code -1} if
* no such length has been negotiated.
*/
- synchronized int getNegotiatedMaxFragSize() {
- return negotiatedMaxFragLen;
+ int getNegotiatedMaxFragSize() {
+ sessionLock.lock();
+ try {
+ return negotiatedMaxFragLen;
+ } finally {
+ sessionLock.unlock();
+ }
}
- synchronized void setMaximumPacketSize(int maximumPacketSize) {
- this.maximumPacketSize = maximumPacketSize;
+ void setMaximumPacketSize(int maximumPacketSize) {
+ sessionLock.lock();
+ try {
+ this.maximumPacketSize = maximumPacketSize;
+ } finally {
+ sessionLock.unlock();
+ }
}
- synchronized int getMaximumPacketSize() {
- return maximumPacketSize;
+ int getMaximumPacketSize() {
+ sessionLock.lock();
+ try {
+ return maximumPacketSize;
+ } finally {
+ sessionLock.unlock();
+ }
}
/**
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,6 +38,7 @@
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiFunction;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLException;
@@ -84,6 +85,9 @@
private boolean isConnected = false;
private volatile boolean tlsIsClosed = false;
+ private final ReentrantLock socketLock = new ReentrantLock();
+ private final ReentrantLock handshakeLock = new ReentrantLock();
+
/*
* Is the local name service trustworthy?
*
@@ -292,14 +296,25 @@
}
@Override
- public synchronized String[] getEnabledCipherSuites() {
- return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
+ public String[] getEnabledCipherSuites() {
+ socketLock.lock();
+ try {
+ return CipherSuite.namesOf(
+ conContext.sslConfig.enabledCipherSuites);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized void setEnabledCipherSuites(String[] suites) {
- conContext.sslConfig.enabledCipherSuites =
- CipherSuite.validValuesOf(suites);
+ public void setEnabledCipherSuites(String[] suites) {
+ socketLock.lock();
+ try {
+ conContext.sslConfig.enabledCipherSuites =
+ CipherSuite.validValuesOf(suites);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
@@ -309,19 +324,29 @@
}
@Override
- public synchronized String[] getEnabledProtocols() {
- return ProtocolVersion.toStringArray(
- conContext.sslConfig.enabledProtocols);
+ public String[] getEnabledProtocols() {
+ socketLock.lock();
+ try {
+ return ProtocolVersion.toStringArray(
+ conContext.sslConfig.enabledProtocols);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized void setEnabledProtocols(String[] protocols) {
+ public void setEnabledProtocols(String[] protocols) {
if (protocols == null) {
throw new IllegalArgumentException("Protocols cannot be null");
}
- conContext.sslConfig.enabledProtocols =
- ProtocolVersion.namesOf(protocols);
+ socketLock.lock();
+ try {
+ conContext.sslConfig.enabledProtocols =
+ ProtocolVersion.namesOf(protocols);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
@@ -341,29 +366,44 @@
}
@Override
- public synchronized SSLSession getHandshakeSession() {
- return conContext.handshakeContext == null ?
- null : conContext.handshakeContext.handshakeSession;
+ public SSLSession getHandshakeSession() {
+ socketLock.lock();
+ try {
+ return conContext.handshakeContext == null ?
+ null : conContext.handshakeContext.handshakeSession;
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized void addHandshakeCompletedListener(
+ public void addHandshakeCompletedListener(
HandshakeCompletedListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener is null");
}
- conContext.sslConfig.addHandshakeCompletedListener(listener);
+ socketLock.lock();
+ try {
+ conContext.sslConfig.addHandshakeCompletedListener(listener);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized void removeHandshakeCompletedListener(
+ public void removeHandshakeCompletedListener(
HandshakeCompletedListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener is null");
}
- conContext.sslConfig.removeHandshakeCompletedListener(listener);
+ socketLock.lock();
+ try {
+ conContext.sslConfig.removeHandshakeCompletedListener(listener);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
@@ -377,7 +417,8 @@
throw new SocketException("Socket has been closed or broken");
}
- synchronized (conContext) { // handshake lock
+ handshakeLock.lock();
+ try {
// double check the context status
if (conContext.isBroken || conContext.isInboundClosed() ||
conContext.isOutboundClosed()) {
@@ -400,53 +441,95 @@
} catch (Exception oe) { // including RuntimeException
handleException(oe);
}
+ } finally {
+ handshakeLock.unlock();
+ }
+ }
+
+ @Override
+ public void setUseClientMode(boolean mode) {
+ socketLock.lock();
+ try {
+ conContext.setUseClientMode(mode);
+ } finally {
+ socketLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean getUseClientMode() {
+ socketLock.lock();
+ try {
+ return conContext.sslConfig.isClientMode;
+ } finally {
+ socketLock.unlock();
+ }
+ }
+
+ @Override
+ public void setNeedClientAuth(boolean need) {
+ socketLock.lock();
+ try {
+ conContext.sslConfig.clientAuthType =
+ (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ socketLock.unlock();
}
}
@Override
- public synchronized void setUseClientMode(boolean mode) {
- conContext.setUseClientMode(mode);
+ public boolean getNeedClientAuth() {
+ socketLock.lock();
+ try {
+ return (conContext.sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUIRED);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized boolean getUseClientMode() {
- return conContext.sslConfig.isClientMode;
- }
-
- @Override
- public synchronized void setNeedClientAuth(boolean need) {
- conContext.sslConfig.clientAuthType =
- (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
- ClientAuthType.CLIENT_AUTH_NONE);
+ public void setWantClientAuth(boolean want) {
+ socketLock.lock();
+ try {
+ conContext.sslConfig.clientAuthType =
+ (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
+ ClientAuthType.CLIENT_AUTH_NONE);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized boolean getNeedClientAuth() {
- return (conContext.sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUIRED);
- }
-
- @Override
- public synchronized void setWantClientAuth(boolean want) {
- conContext.sslConfig.clientAuthType =
- (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
- ClientAuthType.CLIENT_AUTH_NONE);
+ public boolean getWantClientAuth() {
+ socketLock.lock();
+ try {
+ return (conContext.sslConfig.clientAuthType ==
+ ClientAuthType.CLIENT_AUTH_REQUESTED);
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized boolean getWantClientAuth() {
- return (conContext.sslConfig.clientAuthType ==
- ClientAuthType.CLIENT_AUTH_REQUESTED);
+ public void setEnableSessionCreation(boolean flag) {
+ socketLock.lock();
+ try {
+ conContext.sslConfig.enableSessionCreation = flag;
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized void setEnableSessionCreation(boolean flag) {
- conContext.sslConfig.enableSessionCreation = flag;
- }
-
- @Override
- public synchronized boolean getEnableSessionCreation() {
- return conContext.sslConfig.enableSessionCreation;
+ public boolean getEnableSessionCreation() {
+ socketLock.lock();
+ try {
+ return conContext.sslConfig.enableSessionCreation;
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
@@ -535,8 +618,9 @@
// Need a lock here so that the user_canceled alert and the
// close_notify alert can be delivered together.
+ conContext.outputRecord.recordLock.lock();
try {
- synchronized (conContext.outputRecord) {
+ try {
// send a user_canceled alert if needed.
if (useUserCanceled) {
conContext.warning(Alert.USER_CANCELED);
@@ -544,15 +628,17 @@
// send a close_notify alert
conContext.warning(Alert.CLOSE_NOTIFY);
+ } finally {
+ if (!conContext.isOutboundClosed()) {
+ conContext.outputRecord.close();
+ }
+
+ if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
+ super.shutdownOutput();
+ }
}
} finally {
- if (!conContext.isOutboundClosed()) {
- conContext.outputRecord.close();
- }
-
- if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
- super.shutdownOutput();
- }
+ conContext.outputRecord.recordLock.unlock();
}
if (!isInputShutdown()) {
@@ -681,20 +767,25 @@
}
@Override
- public synchronized InputStream getInputStream() throws IOException {
- if (isClosed()) {
- throw new SocketException("Socket is closed");
- }
+ public InputStream getInputStream() throws IOException {
+ socketLock.lock();
+ try {
+ if (isClosed()) {
+ throw new SocketException("Socket is closed");
+ }
- if (!isConnected) {
- throw new SocketException("Socket is not connected");
- }
+ if (!isConnected) {
+ throw new SocketException("Socket is not connected");
+ }
- if (conContext.isInboundClosed() || isInputShutdown()) {
- throw new SocketException("Socket input is already shutdown");
+ if (conContext.isInboundClosed() || isInputShutdown()) {
+ throw new SocketException("Socket input is already shutdown");
+ }
+
+ return appInput;
+ } finally {
+ socketLock.unlock();
}
-
- return appInput;
}
private void ensureNegotiated() throws IOException {
@@ -703,7 +794,8 @@
return;
}
- synchronized (conContext) { // handshake lock
+ handshakeLock.lock();
+ try {
// double check the context status
if (conContext.isNegotiated || conContext.isBroken ||
conContext.isInboundClosed() ||
@@ -712,6 +804,8 @@
}
startHandshake();
+ } finally {
+ handshakeLock.unlock();
}
}
@@ -729,6 +823,9 @@
// Is application data available in the stream?
private volatile boolean appDataIsAvailable;
+ // reading lock
+ private final ReentrantLock readLock = new ReentrantLock();
+
AppInputStream() {
this.appDataIsAvailable = false;
this.buffer = ByteBuffer.allocate(4096);
@@ -807,7 +904,8 @@
//
// Note that the receiving and processing of post-handshake message
// are also synchronized with the read lock.
- synchronized (this) {
+ readLock.lock();
+ try {
int remains = available();
if (remains > 0) {
int howmany = Math.min(remains, len);
@@ -839,6 +937,8 @@
// dummy for compiler
return -1;
}
+ } finally {
+ readLock.unlock();
}
}
@@ -850,19 +950,24 @@
* things simpler.
*/
@Override
- public synchronized long skip(long n) throws IOException {
+ public long skip(long n) throws IOException {
// dummy array used to implement skip()
byte[] skipArray = new byte[256];
+ long skipped = 0;
- long skipped = 0;
- while (n > 0) {
- int len = (int)Math.min(n, skipArray.length);
- int r = read(skipArray, 0, len);
- if (r <= 0) {
- break;
+ readLock.lock();
+ try {
+ while (n > 0) {
+ int len = (int)Math.min(n, skipArray.length);
+ int r = read(skipArray, 0, len);
+ if (r <= 0) {
+ break;
+ }
+ n -= r;
+ skipped += r;
}
- n -= r;
- skipped += r;
+ } finally {
+ readLock.unlock();
}
return skipped;
@@ -910,8 +1015,18 @@
* Try the best to use up the input records so as to close the
* socket gracefully, without impact the performance too much.
*/
- private synchronized void deplete() {
- if (!conContext.isInboundClosed()) {
+ private void deplete() {
+ if (conContext.isInboundClosed()) {
+ return;
+ }
+
+ readLock.lock();
+ try {
+ // double check
+ if (conContext.isInboundClosed()) {
+ return;
+ }
+
if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
return;
}
@@ -927,25 +1042,32 @@
"input stream close depletion failed", ioe);
}
}
+ } finally {
+ readLock.unlock();
}
}
}
@Override
- public synchronized OutputStream getOutputStream() throws IOException {
- if (isClosed()) {
- throw new SocketException("Socket is closed");
- }
+ public OutputStream getOutputStream() throws IOException {
+ socketLock.lock();
+ try {
+ if (isClosed()) {
+ throw new SocketException("Socket is closed");
+ }
- if (!isConnected) {
- throw new SocketException("Socket is not connected");
- }
+ if (!isConnected) {
+ throw new SocketException("Socket is not connected");
+ }
- if (conContext.isOutboundDone() || isOutputShutdown()) {
- throw new SocketException("Socket output is already shutdown");
+ if (conContext.isOutboundDone() || isOutputShutdown()) {
+ throw new SocketException("Socket output is already shutdown");
+ }
+
+ return appOutput;
+ } finally {
+ socketLock.unlock();
}
-
- return appOutput;
}
@@ -1035,44 +1157,74 @@
}
@Override
- public synchronized SSLParameters getSSLParameters() {
- return conContext.sslConfig.getSSLParameters();
- }
-
- @Override
- public synchronized void setSSLParameters(SSLParameters params) {
- conContext.sslConfig.setSSLParameters(params);
-
- if (conContext.sslConfig.maximumPacketSize != 0) {
- conContext.outputRecord.changePacketSize(
- conContext.sslConfig.maximumPacketSize);
+ public SSLParameters getSSLParameters() {
+ socketLock.lock();
+ try {
+ return conContext.sslConfig.getSSLParameters();
+ } finally {
+ socketLock.unlock();
}
}
@Override
- public synchronized String getApplicationProtocol() {
- return conContext.applicationProtocol;
+ public void setSSLParameters(SSLParameters params) {
+ socketLock.lock();
+ try {
+ conContext.sslConfig.setSSLParameters(params);
+
+ if (conContext.sslConfig.maximumPacketSize != 0) {
+ conContext.outputRecord.changePacketSize(
+ conContext.sslConfig.maximumPacketSize);
+ }
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized String getHandshakeApplicationProtocol() {
- if (conContext.handshakeContext != null) {
- return conContext.handshakeContext.applicationProtocol;
+ public String getApplicationProtocol() {
+ socketLock.lock();
+ try {
+ return conContext.applicationProtocol;
+ } finally {
+ socketLock.unlock();
+ }
+ }
+
+ @Override
+ public String getHandshakeApplicationProtocol() {
+ socketLock.lock();
+ try {
+ if (conContext.handshakeContext != null) {
+ return conContext.handshakeContext.applicationProtocol;
+ }
+ } finally {
+ socketLock.unlock();
}
return null;
}
@Override
- public synchronized void setHandshakeApplicationProtocolSelector(
+ public void setHandshakeApplicationProtocolSelector(
BiFunction<SSLSocket, List<String>, String> selector) {
- conContext.sslConfig.socketAPSelector = selector;
+ socketLock.lock();
+ try {
+ conContext.sslConfig.socketAPSelector = selector;
+ } finally {
+ socketLock.unlock();
+ }
}
@Override
- public synchronized BiFunction<SSLSocket, List<String>, String>
+ public BiFunction<SSLSocket, List<String>, String>
getHandshakeApplicationProtocolSelector() {
- return conContext.sslConfig.socketAPSelector;
+ socketLock.lock();
+ try {
+ return conContext.sslConfig.socketAPSelector;
+ } finally {
+ socketLock.unlock();
+ }
}
/**
@@ -1142,8 +1294,11 @@
try {
Plaintext plainText;
- synchronized (this) {
+ socketLock.lock();
+ try {
plainText = decode(buffer);
+ } finally {
+ socketLock.unlock();
}
if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
buffer.position() > 0) {
@@ -1222,27 +1377,33 @@
*
* Called by connect, the layered constructor, and SSLServerSocket.
*/
- synchronized void doneConnect() throws IOException {
- // In server mode, it is not necessary to set host and serverNames.
- // Otherwise, would require a reverse DNS lookup to get the hostname.
- if (peerHost == null || peerHost.isEmpty()) {
- boolean useNameService =
- trustNameService && conContext.sslConfig.isClientMode;
- useImplicitHost(useNameService);
- } else {
- conContext.sslConfig.serverNames =
- Utilities.addToSNIServerNameList(
- conContext.sslConfig.serverNames, peerHost);
+ void doneConnect() throws IOException {
+ socketLock.lock();
+ try {
+ // In server mode, it is not necessary to set host and serverNames.
+ // Otherwise, would require a reverse DNS lookup to get
+ // the hostname.
+ if (peerHost == null || peerHost.isEmpty()) {
+ boolean useNameService =
+ trustNameService && conContext.sslConfig.isClientMode;
+ useImplicitHost(useNameService);
+ } else {
+ conContext.sslConfig.serverNames =
+ Utilities.addToSNIServerNameList(
+ conContext.sslConfig.serverNames, peerHost);
+ }
+
+ InputStream sockInput = super.getInputStream();
+ conContext.inputRecord.setReceiverStream(sockInput);
+
+ OutputStream sockOutput = super.getOutputStream();
+ conContext.inputRecord.setDeliverStream(sockOutput);
+ conContext.outputRecord.setDeliverStream(sockOutput);
+
+ this.isConnected = true;
+ } finally {
+ socketLock.unlock();
}
-
- InputStream sockInput = super.getInputStream();
- conContext.inputRecord.setReceiverStream(sockInput);
-
- OutputStream sockOutput = super.getOutputStream();
- conContext.inputRecord.setDeliverStream(sockOutput);
- conContext.outputRecord.setDeliverStream(sockOutput);
-
- this.isConnected = true;
}
private void useImplicitHost(boolean useNameService) {
@@ -1288,11 +1449,16 @@
// Please NOTE that this method MUST be called before calling to
// SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
// may override SNIHostName in the customized server name indication.
- public synchronized void setHost(String host) {
- this.peerHost = host;
- this.conContext.sslConfig.serverNames =
- Utilities.addToSNIServerNameList(
- conContext.sslConfig.serverNames, host);
+ public void setHost(String host) {
+ socketLock.lock();
+ try {
+ this.peerHost = host;
+ this.conContext.sslConfig.serverNames =
+ Utilities.addToSNIServerNameList(
+ conContext.sslConfig.serverNames, host);
+ } finally {
+ socketLock.unlock();
+ }
}
/**
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -51,123 +51,206 @@
}
@Override
- synchronized void encodeAlert(
- byte level, byte description) throws IOException {
- if (isClosed()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("outbound has closed, ignore outbound " +
- "alert message: " + Alert.nameOf(description));
+ void encodeAlert(byte level, byte description) throws IOException {
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "alert message: " + Alert.nameOf(description));
+ }
+ return;
}
- return;
- }
- // use the buf of ByteArrayOutputStream
- int position = headerSize + writeCipher.getExplicitNonceSize();
- count = position;
+ // use the buf of ByteArrayOutputStream
+ int position = headerSize + writeCipher.getExplicitNonceSize();
+ count = position;
- write(level);
- write(description);
- if (SSLLogger.isOn && SSLLogger.isOn("record")) {
- SSLLogger.fine("WRITE: " + protocolVersion +
- " " + ContentType.ALERT.name +
- "(" + Alert.nameOf(description) + ")" +
- ", length = " + (count - headerSize));
- }
+ write(level);
+ write(description);
+ if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+ SSLLogger.fine("WRITE: " + protocolVersion +
+ " " + ContentType.ALERT.name +
+ "(" + Alert.nameOf(description) + ")" +
+ ", length = " + (count - headerSize));
+ }
- // Encrypt the fragment and wrap up a record.
- encrypt(writeCipher, ContentType.ALERT.id, headerSize);
+ // Encrypt the fragment and wrap up a record.
+ encrypt(writeCipher, ContentType.ALERT.id, headerSize);
- // deliver this message
- deliverStream.write(buf, 0, count); // may throw IOException
- deliverStream.flush(); // may throw IOException
+ // deliver this message
+ deliverStream.write(buf, 0, count); // may throw IOException
+ deliverStream.flush(); // may throw IOException
- if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
- SSLLogger.fine("Raw write",
- (new ByteArrayInputStream(buf, 0, count)));
+ if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+ SSLLogger.fine("Raw write",
+ (new ByteArrayInputStream(buf, 0, count)));
+ }
+
+ // reset the internal buffer
+ count = 0;
+ } finally {
+ recordLock.unlock();
}
-
- // reset the internal buffer
- count = 0;
}
@Override
- synchronized void encodeHandshake(byte[] source,
+ void encodeHandshake(byte[] source,
int offset, int length) throws IOException {
- if (isClosed()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("outbound has closed, ignore outbound " +
- "handshake message",
- ByteBuffer.wrap(source, offset, length));
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "handshake message",
+ ByteBuffer.wrap(source, offset, length));
+ }
+ return;
}
- return;
- }
+
+ if (firstMessage) {
+ firstMessage = false;
- if (firstMessage) {
- firstMessage = false;
-
- if ((helloVersion == ProtocolVersion.SSL20Hello) &&
- (source[offset] == SSLHandshake.CLIENT_HELLO.id) &&
+ if ((helloVersion == ProtocolVersion.SSL20Hello) &&
+ (source[offset] == SSLHandshake.CLIENT_HELLO.id) &&
// 5: recode header size
- (source[offset + 4 + 2 + 32] == 0)) {
+ (source[offset + 4 + 2 + 32] == 0)) {
// V3 session ID is empty
// 4: handshake header size
// 2: client_version in ClientHello
// 32: random in ClientHello
- ByteBuffer v2ClientHello = encodeV2ClientHello(
- source, (offset + 4), (length - 4));
+ ByteBuffer v2ClientHello = encodeV2ClientHello(
+ source, (offset + 4), (length - 4));
+
+ // array offset is zero
+ byte[] record = v2ClientHello.array();
+ int limit = v2ClientHello.limit();
+ handshakeHash.deliver(record, 2, (limit - 2));
+
+ if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+ SSLLogger.fine(
+ "WRITE: SSLv2 ClientHello message" +
+ ", length = " + limit);
+ }
+
+ // deliver this message
+ //
+ // Version 2 ClientHello message should be plaintext.
+ //
+ // No max fragment length negotiation.
+ deliverStream.write(record, 0, limit);
+ deliverStream.flush();
+
+ if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+ SSLLogger.fine("Raw write",
+ (new ByteArrayInputStream(record, 0, limit)));
+ }
- byte[] record = v2ClientHello.array(); // array offset is zero
- int limit = v2ClientHello.limit();
- handshakeHash.deliver(record, 2, (limit - 2));
+ return;
+ }
+ }
+
+ byte handshakeType = source[0];
+ if (handshakeHash.isHashable(handshakeType)) {
+ handshakeHash.deliver(source, offset, length);
+ }
+
+ int fragLimit = getFragLimit();
+ int position = headerSize + writeCipher.getExplicitNonceSize();
+ if (count == 0) {
+ count = position;
+ }
+
+ if ((count - position) < (fragLimit - length)) {
+ write(source, offset, length);
+ return;
+ }
+
+ for (int limit = (offset + length); offset < limit;) {
+
+ int remains = (limit - offset) + (count - position);
+ int fragLen = Math.min(fragLimit, remains);
+
+ // use the buf of ByteArrayOutputStream
+ write(source, offset, fragLen);
+ if (remains < fragLimit) {
+ return;
+ }
if (SSLLogger.isOn && SSLLogger.isOn("record")) {
SSLLogger.fine(
- "WRITE: SSLv2 ClientHello message" +
- ", length = " + limit);
+ "WRITE: " + protocolVersion +
+ " " + ContentType.HANDSHAKE.name +
+ ", length = " + (count - headerSize));
}
+ // Encrypt the fragment and wrap up a record.
+ encrypt(writeCipher, ContentType.HANDSHAKE.id, headerSize);
+
// deliver this message
- //
- // Version 2 ClientHello message should be plaintext.
- //
- // No max fragment length negotiation.
- deliverStream.write(record, 0, limit);
- deliverStream.flush();
+ deliverStream.write(buf, 0, count); // may throw IOException
+ deliverStream.flush(); // may throw IOException
if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
SSLLogger.fine("Raw write",
- (new ByteArrayInputStream(record, 0, limit)));
+ (new ByteArrayInputStream(buf, 0, count)));
}
+ // reset the offset
+ offset += fragLen;
+
+ // reset the internal buffer
+ count = position;
+ }
+ } finally {
+ recordLock.unlock();
+ }
+ }
+
+ @Override
+ void encodeChangeCipherSpec() throws IOException {
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.warning("outbound has closed, ignore outbound " +
+ "change_cipher_spec message");
+ }
return;
}
- }
-
- byte handshakeType = source[0];
- if (handshakeHash.isHashable(handshakeType)) {
- handshakeHash.deliver(source, offset, length);
- }
-
- int fragLimit = getFragLimit();
- int position = headerSize + writeCipher.getExplicitNonceSize();
- if (count == 0) {
- count = position;
- }
-
- if ((count - position) < (fragLimit - length)) {
- write(source, offset, length);
- return;
- }
-
- for (int limit = (offset + length); offset < limit;) {
-
- int remains = (limit - offset) + (count - position);
- int fragLen = Math.min(fragLimit, remains);
// use the buf of ByteArrayOutputStream
- write(source, offset, fragLen);
- if (remains < fragLimit) {
+ int position = headerSize + writeCipher.getExplicitNonceSize();
+ count = position;
+
+ write((byte)1); // byte 1: change_cipher_spec(
+
+ // Encrypt the fragment and wrap up a record.
+ encrypt(writeCipher, ContentType.CHANGE_CIPHER_SPEC.id, headerSize);
+
+ // deliver this message
+ deliverStream.write(buf, 0, count); // may throw IOException
+ // deliverStream.flush(); // flush in Finished
+
+ if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+ SSLLogger.fine("Raw write",
+ (new ByteArrayInputStream(buf, 0, count)));
+ }
+
+ // reset the internal buffer
+ count = 0;
+ } finally {
+ recordLock.unlock();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ recordLock.lock();
+ try {
+ int position = headerSize + writeCipher.getExplicitNonceSize();
+ if (count <= position) {
return;
}
@@ -190,155 +273,103 @@
(new ByteArrayInputStream(buf, 0, count)));
}
- // reset the offset
- offset += fragLen;
-
// reset the internal buffer
- count = position;
+ count = 0; // DON'T use position
+ } finally {
+ recordLock.unlock();
}
}
@Override
- synchronized void encodeChangeCipherSpec() throws IOException {
- if (isClosed()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.warning("outbound has closed, ignore outbound " +
- "change_cipher_spec message");
+ void deliver(byte[] source, int offset, int length) throws IOException {
+ recordLock.lock();
+ try {
+ if (isClosed()) {
+ throw new SocketException(
+ "Connection or outbound has been closed");
}
- return;
- }
-
- // use the buf of ByteArrayOutputStream
- int position = headerSize + writeCipher.getExplicitNonceSize();
- count = position;
-
- write((byte)1); // byte 1: change_cipher_spec(
-
- // Encrypt the fragment and wrap up a record.
- encrypt(writeCipher, ContentType.CHANGE_CIPHER_SPEC.id, headerSize);
-
- // deliver this message
- deliverStream.write(buf, 0, count); // may throw IOException
- // deliverStream.flush(); // flush in Finished
-
- if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
- SSLLogger.fine("Raw write",
- (new ByteArrayInputStream(buf, 0, count)));
- }
-
- // reset the internal buffer
- count = 0;
- }
- @Override
- public synchronized void flush() throws IOException {
- int position = headerSize + writeCipher.getExplicitNonceSize();
- if (count <= position) {
- return;
- }
-
- if (SSLLogger.isOn && SSLLogger.isOn("record")) {
- SSLLogger.fine(
- "WRITE: " + protocolVersion +
- " " + ContentType.HANDSHAKE.name +
- ", length = " + (count - headerSize));
- }
-
- // Encrypt the fragment and wrap up a record.
- encrypt(writeCipher, ContentType.HANDSHAKE.id, headerSize);
-
- // deliver this message
- deliverStream.write(buf, 0, count); // may throw IOException
- deliverStream.flush(); // may throw IOException
+ if (writeCipher.authenticator.seqNumOverflow()) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+ SSLLogger.fine(
+ "sequence number extremely close to overflow " +
+ "(2^64-1 packets). Closing connection.");
+ }
- if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
- SSLLogger.fine("Raw write",
- (new ByteArrayInputStream(buf, 0, count)));
- }
-
- // reset the internal buffer
- count = 0; // DON'T use position
- }
-
- @Override
- synchronized void deliver(
- byte[] source, int offset, int length) throws IOException {
- if (isClosed()) {
- throw new SocketException("Connection or outbound has been closed");
- }
-
- if (writeCipher.authenticator.seqNumOverflow()) {
- if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
- SSLLogger.fine(
- "sequence number extremely close to overflow " +
- "(2^64-1 packets). Closing connection.");
+ throw new SSLHandshakeException("sequence number overflow");
}
- throw new SSLHandshakeException("sequence number overflow");
- }
+ boolean isFirstRecordOfThePayload = true;
+ for (int limit = (offset + length); offset < limit;) {
+ int fragLen;
+ if (packetSize > 0) {
+ fragLen = Math.min(maxRecordSize, packetSize);
+ fragLen = writeCipher.calculateFragmentSize(
+ fragLen, headerSize);
- boolean isFirstRecordOfThePayload = true;
- for (int limit = (offset + length); offset < limit;) {
- int fragLen;
- if (packetSize > 0) {
- fragLen = Math.min(maxRecordSize, packetSize);
- fragLen =
- writeCipher.calculateFragmentSize(fragLen, headerSize);
+ fragLen = Math.min(fragLen, Record.maxDataSize);
+ } else {
+ fragLen = Record.maxDataSize;
+ }
- fragLen = Math.min(fragLen, Record.maxDataSize);
- } else {
- fragLen = Record.maxDataSize;
- }
+ if (fragmentSize > 0) {
+ fragLen = Math.min(fragLen, fragmentSize);
+ }
- if (fragmentSize > 0) {
- fragLen = Math.min(fragLen, fragmentSize);
- }
+ if (isFirstRecordOfThePayload && needToSplitPayload()) {
+ fragLen = 1;
+ isFirstRecordOfThePayload = false;
+ } else {
+ fragLen = Math.min(fragLen, (limit - offset));
+ }
- if (isFirstRecordOfThePayload && needToSplitPayload()) {
- fragLen = 1;
- isFirstRecordOfThePayload = false;
- } else {
- fragLen = Math.min(fragLen, (limit - offset));
- }
+ // use the buf of ByteArrayOutputStream
+ int position = headerSize + writeCipher.getExplicitNonceSize();
+ count = position;
+ write(source, offset, fragLen);
- // use the buf of ByteArrayOutputStream
- int position = headerSize + writeCipher.getExplicitNonceSize();
- count = position;
- write(source, offset, fragLen);
+ if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+ SSLLogger.fine(
+ "WRITE: " + protocolVersion +
+ " " + ContentType.APPLICATION_DATA.name +
+ ", length = " + (count - position));
+ }
- if (SSLLogger.isOn && SSLLogger.isOn("record")) {
- SSLLogger.fine(
- "WRITE: " + protocolVersion +
- " " + ContentType.APPLICATION_DATA.name +
- ", length = " + (count - position));
- }
+ // Encrypt the fragment and wrap up a record.
+ encrypt(writeCipher,
+ ContentType.APPLICATION_DATA.id, headerSize);
- // Encrypt the fragment and wrap up a record.
- encrypt(writeCipher, ContentType.APPLICATION_DATA.id, headerSize);
+ // deliver this message
+ deliverStream.write(buf, 0, count); // may throw IOException
+ deliverStream.flush(); // may throw IOException
- // deliver this message
- deliverStream.write(buf, 0, count); // may throw IOException
- deliverStream.flush(); // may throw IOException
+ if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+ SSLLogger.fine("Raw write",
+ (new ByteArrayInputStream(buf, 0, count)));
+ }
- if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
- SSLLogger.fine("Raw write",
- (new ByteArrayInputStream(buf, 0, count)));
- }
+ // reset the internal buffer
+ count = 0;
- // reset the internal buffer
- count = 0;
+ if (isFirstAppOutputRecord) {
+ isFirstAppOutputRecord = false;
+ }
- if (isFirstAppOutputRecord) {
- isFirstAppOutputRecord = false;
+ offset += fragLen;
}
-
- offset += fragLen;
+ } finally {
+ recordLock.unlock();
}
}
@Override
- synchronized void setDeliverStream(OutputStream outputStream) {
- this.deliverStream = outputStream;
+ void setDeliverStream(OutputStream outputStream) {
+ recordLock.lock();
+ try {
+ this.deliverStream = outputStream;
+ } finally {
+ recordLock.unlock();
+ }
}
/*
--- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Wed Apr 10 10:46:53 2019 +0530
@@ -41,7 +41,9 @@
import java.util.Set;
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
+import sun.security.util.SignatureUtil;
enum SignatureScheme {
// EdDSA algorithms
@@ -415,9 +417,10 @@
static SignatureScheme getPreferableAlgorithm(
List<SignatureScheme> schemes,
- PrivateKey signingKey,
+ X509Possession x509Possession,
ProtocolVersion version) {
+ PrivateKey signingKey = x509Possession.popPrivateKey;
String keyAlgorithm = signingKey.getAlgorithm();
int keySize;
// Only need to check RSA algorithm at present.
@@ -434,8 +437,9 @@
if (ss.namedGroup != null &&
ss.namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
ECParameterSpec params =
- ((ECPrivateKey)signingKey).getParams();
- if (ss.namedGroup == NamedGroup.valueOf(params)) {
+ x509Possession.getECParameterSpec();
+ if (params != null &&
+ ss.namedGroup == NamedGroup.valueOf(params)) {
return ss;
}
} else {
@@ -468,16 +472,11 @@
Signature signer = Signature.getInstance(algorithm);
if (key instanceof PublicKey) {
- signer.initVerify((PublicKey)(key));
+ SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
+ signAlgParameter);
} else {
- signer.initSign((PrivateKey)key);
- }
-
- // Important note: Please don't set the parameters before signature
- // or verification initialization, so that the crypto provider can
- // be selected properly.
- if (signAlgParameter != null) {
- signer.setParameter(signAlgParameter);
+ SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
+ signAlgParameter, null);
}
return signer;
--- a/src/java.base/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -102,25 +102,21 @@
* Basic container for credentials implemented as an inner class.
*/
private static class X509Credentials {
- PrivateKey privateKey;
- X509Certificate[] certificates;
- private Set<X500Principal> issuerX500Principals;
+ final PrivateKey privateKey;
+ final X509Certificate[] certificates;
+ private final Set<X500Principal> issuerX500Principals;
X509Credentials(PrivateKey privateKey, X509Certificate[] certificates) {
// assert privateKey and certificates != null
this.privateKey = privateKey;
this.certificates = certificates;
+ this.issuerX500Principals = new HashSet<>(certificates.length);
+ for (X509Certificate certificate : certificates) {
+ issuerX500Principals.add(certificate.getIssuerX500Principal());
+ }
}
- synchronized Set<X500Principal> getIssuerX500Principals() {
- // lazy initialization
- if (issuerX500Principals == null) {
- issuerX500Principals = new HashSet<X500Principal>();
- for (int i = 0; i < certificates.length; i++) {
- issuerX500Principals.add(
- certificates[i].getIssuerX500Principal());
- }
- }
+ Set<X500Principal> getIssuerX500Principals() {
return issuerX500Principals;
}
}
--- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -496,13 +496,16 @@
}
if (needCloseNotify) {
- synchronized (outputRecord) {
+ outputRecord.recordLock.lock();
+ try {
try {
// send a close_notify alert
warning(Alert.CLOSE_NOTIFY);
} finally {
outputRecord.close();
}
+ } finally {
+ outputRecord.recordLock.unlock();
}
}
}
@@ -541,7 +544,8 @@
// Need a lock here so that the user_canceled alert and the
// close_notify alert can be delivered together.
- synchronized (outputRecord) {
+ outputRecord.recordLock.lock();
+ try {
try {
// send a user_canceled alert if needed.
if (useUserCanceled) {
@@ -553,6 +557,8 @@
} finally {
outputRecord.close();
}
+ } finally {
+ outputRecord.recordLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java Wed Apr 10 10:46:53 2019 +0530
@@ -30,6 +30,7 @@
import java.security.*;
import java.security.cert.*;
import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
import sun.security.action.*;
import sun.security.validator.TrustStoreUtil;
@@ -244,6 +245,8 @@
// objects can be atomically cleared, and reloaded if needed.
private WeakReference<Set<X509Certificate>> csRef;
+ private final ReentrantLock tamLock = new ReentrantLock();
+
private TrustAnchorManager() {
this.descriptor = null;
this.ksRef = new WeakReference<>(null);
@@ -255,7 +258,7 @@
*
* @return null if the underlying KeyStore is not available.
*/
- synchronized KeyStore getKeyStore(
+ KeyStore getKeyStore(
TrustStoreDescriptor descriptor) throws Exception {
TrustStoreDescriptor temporaryDesc = this.descriptor;
@@ -264,15 +267,26 @@
return ks;
}
- // Reload a new key store.
- if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
- SSLLogger.fine("Reload the trust store");
+ tamLock.lock();
+ try {
+ // double check
+ ks = ksRef.get();
+ if ((ks != null) && descriptor.equals(temporaryDesc)) {
+ return ks;
+ }
+
+ // Reload a new key store.
+ if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
+ SSLLogger.fine("Reload the trust store");
+ }
+
+ ks = loadKeyStore(descriptor);
+ this.descriptor = descriptor;
+ this.ksRef = new WeakReference<>(ks);
+ } finally {
+ tamLock.unlock();
}
- ks = loadKeyStore(descriptor);
- this.descriptor = descriptor;
- this.ksRef = new WeakReference<>(ks);
-
return ks;
}
@@ -282,51 +296,62 @@
*
* @return empty collection if the underlying KeyStore is not available.
*/
- synchronized Set<X509Certificate> getTrustedCerts(
+ Set<X509Certificate> getTrustedCerts(
TrustStoreDescriptor descriptor) throws Exception {
KeyStore ks = null;
TrustStoreDescriptor temporaryDesc = this.descriptor;
Set<X509Certificate> certs = csRef.get();
- if (certs != null) {
- if (descriptor.equals(temporaryDesc)) {
- return certs;
- } else {
- // Use the new descriptor.
- this.descriptor = descriptor;
- }
- } else {
- // Try to use the cached store at first.
- if (descriptor.equals(temporaryDesc)) {
- ks = ksRef.get();
- } else {
- // Use the new descriptor.
- this.descriptor = descriptor;
- }
+ if ((certs != null) && descriptor.equals(temporaryDesc)) {
+ return certs;
}
- // Reload the trust store if needed.
- if (ks == null) {
- if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
- SSLLogger.fine("Reload the trust store");
+ tamLock.lock();
+ try {
+ // double check
+ temporaryDesc = this.descriptor;
+ certs = csRef.get();
+ if (certs != null) {
+ if (descriptor.equals(temporaryDesc)) {
+ return certs;
+ } else {
+ // Use the new descriptor.
+ this.descriptor = descriptor;
+ }
+ } else {
+ // Try to use the cached store at first.
+ if (descriptor.equals(temporaryDesc)) {
+ ks = ksRef.get();
+ } else {
+ // Use the new descriptor.
+ this.descriptor = descriptor;
+ }
}
- ks = loadKeyStore(descriptor);
- }
- // Reload trust certs from the key store.
- if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
- SSLLogger.fine("Reload trust certs");
- }
+ // Reload the trust store if needed.
+ if (ks == null) {
+ if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
+ SSLLogger.fine("Reload the trust store");
+ }
+ ks = loadKeyStore(descriptor);
+ this.ksRef = new WeakReference<>(ks);
+ }
- certs = loadTrustedCerts(ks);
- if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
- SSLLogger.fine("Reloaded " + certs.size() + " trust certs");
+ // Reload trust certs from the key store.
+ if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
+ SSLLogger.fine("Reload trust certs");
+ }
+
+ certs = loadTrustedCerts(ks);
+ if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) {
+ SSLLogger.fine("Reloaded " + certs.size() + " trust certs");
+ }
+
+ this.csRef = new WeakReference<>(certs);
+ } finally {
+ tamLock.unlock();
}
- // Note that as ks is a local variable, it is not
- // necessary to add it to the ksRef weak reference.
- this.csRef = new WeakReference<>(certs);
-
return certs;
}
--- a/src/java.base/share/classes/sun/security/ssl/X509Authentication.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/X509Authentication.java Wed Apr 10 10:46:53 2019 +0530
@@ -28,6 +28,7 @@
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.util.AbstractMap.SimpleImmutableEntry;
@@ -127,6 +128,26 @@
this.popCerts = popCerts;
this.popPrivateKey = popPrivateKey;
}
+
+ ECParameterSpec getECParameterSpec() {
+ if (popPrivateKey == null ||
+ !"EC".equals(popPrivateKey.getAlgorithm())) {
+ return null;
+ }
+
+ if (popPrivateKey instanceof ECKey) {
+ return ((ECKey)popPrivateKey).getParams();
+ } else if (popCerts != null && popCerts.length != 0) {
+ // The private key not extractable, get the parameters from
+ // the X.509 certificate.
+ PublicKey publicKey = popCerts[0].getPublicKey();
+ if (publicKey instanceof ECKey) {
+ return ((ECKey)publicKey).getParams();
+ }
+ }
+
+ return null;
+ }
}
static final class X509Credentials implements SSLCredentials {
--- a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -29,6 +29,7 @@
import java.security.*;
import java.security.cert.*;
import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
import javax.net.ssl.*;
import sun.security.util.AnchorCertificates;
import sun.security.util.HostnameChecker;
@@ -63,6 +64,8 @@
// the different extension checks. They are initialized lazily on demand.
private volatile Validator clientValidator, serverValidator;
+ private final ReentrantLock validatorLock = new ReentrantLock();
+
X509TrustManagerImpl(String validatorType,
Collection<X509Certificate> trustedCerts) {
@@ -157,12 +160,15 @@
if (isClient) {
v = clientValidator;
if (v == null) {
- synchronized (this) {
+ validatorLock.lock();
+ try {
v = clientValidator;
if (v == null) {
v = getValidator(Validator.VAR_TLS_CLIENT);
clientValidator = v;
}
+ } finally {
+ validatorLock.unlock();
}
}
} else {
@@ -170,12 +176,15 @@
// (guaranteed under the new Tiger memory model)
v = serverValidator;
if (v == null) {
- synchronized (this) {
+ validatorLock.lock();
+ try {
v = serverValidator;
if (v == null) {
v = getValidator(Validator.VAR_TLS_SERVER);
serverValidator = v;
}
+ } finally {
+ validatorLock.unlock();
}
}
}
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Apr 10 10:46:53 2019 +0530
@@ -84,6 +84,7 @@
import sun.security.util.Password;
import sun.security.util.SecurityProperties;
import sun.security.util.SecurityProviderConstants;
+import sun.security.util.SignatureUtil;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@@ -175,6 +176,8 @@
private Set<char[]> passwords = new HashSet<>();
private String startDate = null;
+ private boolean tlsInfo = false;
+
private List<String> ids = new ArrayList<>(); // used in GENCRL
private List<String> v3ext = new ArrayList<>();
@@ -260,6 +263,8 @@
STOREPASSWD("Changes.the.store.password.of.a.keystore",
NEW, KEYSTORE, CACERTS, STOREPASS, STORETYPE, PROVIDERNAME,
ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V),
+ SHOWINFO("showinfo.command.help",
+ TLS, V),
// Undocumented start here, KEYCLONE is used a marker in -help;
@@ -365,6 +370,7 @@
STARTDATE("startdate", "<date>", "certificate.validity.start.date.time"),
STOREPASS("storepass", "<arg>", "keystore.password"),
STORETYPE("storetype", "<type>", "keystore.type"),
+ TLS("tls", null, "tls.option.help"),
TRUSTCACERTS("trustcacerts", null, "trust.certificates.from.cacerts"),
V("v", null, "verbose.output"),
VALIDITY("validity", "<days>", "validity.number.of.days");
@@ -678,6 +684,8 @@
protectedPath = true;
} else if (collator.compare(flags, "-srcprotected") == 0) {
srcprotectedPath = true;
+ } else if (collator.compare(flags, "-tls") == 0) {
+ tlsInfo = true;
} else {
System.err.println(rb.getString("Illegal.option.") + flags);
tinyHelp();
@@ -705,7 +713,7 @@
}
boolean isKeyStoreRelated(Command cmd) {
- return cmd != PRINTCERT && cmd != PRINTCERTREQ;
+ return cmd != PRINTCERT && cmd != PRINTCERTREQ && cmd != SHOWINFO;
}
/**
@@ -874,8 +882,7 @@
// Check if keystore exists.
// If no keystore has been specified at the command line, try to use
// the default, which is located in $HOME/.keystore.
- // If the command is "genkey", "identitydb", "import", or "printcert",
- // it is OK not to have a keystore.
+ // No need to check if isKeyStoreRelated(command) is false.
// DO NOT open the existing keystore if this is an in-place import.
// The keystore should be created as brand new.
@@ -889,6 +896,9 @@
}
ksStream = new FileInputStream(ksfile);
} catch (FileNotFoundException e) {
+ // These commands do not need the keystore to be existing.
+ // Either it will create a new one or the keystore is
+ // optional (i.e. PRINTCRL).
if (command != GENKEYPAIR &&
command != GENSECKEY &&
command != IDENTITYDB &&
@@ -1311,6 +1321,8 @@
}
} else if (command == PRINTCRL) {
doPrintCRL(filename, out);
+ } else if (command == SHOWINFO) {
+ doShowInfo();
}
// If we need to save the keystore, do so.
@@ -1430,11 +1442,12 @@
sigAlgName = getCompatibleSigAlgName(privateKey);
}
Signature signature = Signature.getInstance(sigAlgName);
- signature.initSign(privateKey);
+ AlgorithmParameterSpec params = AlgorithmId
+ .getDefaultAlgorithmParameterSpec(sigAlgName, privateKey);
+
+ SignatureUtil.initSignWithParam(signature, privateKey, params, null);
X509CertInfo info = new X509CertInfo();
- AlgorithmParameterSpec params = AlgorithmId
- .getDefaultAlgorithmParameterSpec(sigAlgName, privateKey);
AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlgName, params);
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER,
@@ -1588,12 +1601,9 @@
}
Signature signature = Signature.getInstance(sigAlgName);
- signature.initSign(privKey);
AlgorithmParameterSpec params = AlgorithmId
.getDefaultAlgorithmParameterSpec(sigAlgName, privKey);
- if (params != null) {
- signature.setParameter(params);
- }
+ SignatureUtil.initSignWithParam(signature, privKey, params, null);
X500Name subject = dname == null?
new X500Name(((X509Certificate)cert).getSubjectDN().toString()):
@@ -2707,6 +2717,14 @@
}
}
+ private void doShowInfo() throws Exception {
+ if (tlsInfo) {
+ ShowInfo.tls(verbose);
+ } else {
+ System.out.println(rb.getString("showinfo.no.option"));
+ }
+ }
+
private Collection<? extends Certificate> generateCertificates(InputStream in)
throws CertificateException, IOException {
byte[] data = in.readAllBytes();
--- a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java Wed Apr 10 10:46:53 2019 +0530
@@ -96,6 +96,8 @@
"Generates a self-signed certificate"}, //-selfcert
{"Changes.the.store.password.of.a.keystore",
"Changes the store password of a keystore"}, //-storepasswd
+ {"showinfo.command.help", "Displays security-related information"},
+
// keytool: help: options
{"alias.name.of.the.entry.to.process",
"alias name of the entry to process"}, //-alias
@@ -141,6 +143,7 @@
"do not prompt"}, //-noprompt
{"password.through.protected.mechanism",
"password through protected mechanism"}, //-protected
+ {"tls.option.help", "Displays TLS configuration information"},
// The following 2 values should span 2 lines, the first for the
// option itself, the second for its -providerArg value.
@@ -472,6 +475,8 @@
{"backup.keystore.warning", "The original keystore \"%1$s\" is backed up as \"%3$s\"..."},
{"importing.keystore.status", "Importing keystore %1$s to %2$s..."},
{"keyalg.option.1.missing.warning", "No -keyalg option. The default key algorithm (%s) is a legacy algorithm and is no longer recommended. In a subsequent release of the JDK, the default will be removed and the -keyalg option must be specified."},
+
+ {"showinfo.no.option", "Missing option for -showinfo. Try \"keytool -showinfo -tls\"."},
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/tools/keytool/ShowInfo.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.keytool;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+
+class ShowInfo {
+
+ // verbose is not used yet.
+ static void tls(boolean verbose) throws Exception {
+
+ SSLSocket ssls = (SSLSocket)
+ SSLContext.getDefault().getSocketFactory().createSocket();
+
+ System.out.println("Enabled Protocols");
+ System.out.println("-----------------");
+ for (String s : ssls.getEnabledProtocols()) {
+ System.out.println(s);
+ }
+
+ System.out.println();
+
+ System.out.println("Enabled Cipher Suites");
+ System.out.println("---------------------");
+ for (String s : ssls.getEnabledCipherSuites()) {
+ System.out.println(s);
+ }
+ }
+}
--- a/src/java.base/share/classes/sun/security/util/SignatureUtil.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/util/SignatureUtil.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -29,6 +29,7 @@
import java.security.*;
import java.security.spec.*;
import sun.security.rsa.RSAUtil;
+import jdk.internal.access.SharedSecrets;
/**
* Utility class for Signature related operations. Currently used by various
@@ -39,12 +40,25 @@
*/
public class SignatureUtil {
+ private static String checkName(String algName) throws ProviderException {
+ if (algName.indexOf(".") == -1) {
+ return algName;
+ }
+ // convert oid to String
+ try {
+ return Signature.getInstance(algName).getAlgorithm();
+ } catch (Exception e) {
+ throw new ProviderException("Error mapping algorithm name", e);
+ }
+ }
+
// Utility method of creating an AlgorithmParameters object with
// the specified algorithm name and encoding
private static AlgorithmParameters createAlgorithmParameters(String algName,
byte[] paramBytes) throws ProviderException {
try {
+ algName = checkName(algName);
AlgorithmParameters result =
AlgorithmParameters.getInstance(algName);
result.init(paramBytes);
@@ -54,52 +68,81 @@
}
}
- private static AlgorithmParameterSpec getParamSpec(String sigName,
+ // Utility method for converting the specified AlgorithmParameters object
+ // into an AlgorithmParameterSpec object.
+ public static AlgorithmParameterSpec getParamSpec(String sigName,
AlgorithmParameters params)
- throws InvalidAlgorithmParameterException, ProviderException {
+ throws ProviderException {
- if (params == null) return null;
-
- if (sigName.toUpperCase().indexOf("RSA") == -1) {
- throw new ProviderException
- ("Unrecognized algorithm for signature parameters " +
- sigName);
+ sigName = checkName(sigName);
+ AlgorithmParameterSpec paramSpec = null;
+ if (params != null) {
+ if (sigName.toUpperCase().indexOf("RSA") == -1) {
+ throw new ProviderException
+ ("Unrecognized algorithm for signature parameters " +
+ sigName);
+ }
+ // AlgorithmParameters.getAlgorithm() may returns oid if it's
+ // created during DER decoding. Convert to use the standard name
+ // before passing it to RSAUtil
+ if (params.getAlgorithm().indexOf(".") != -1) {
+ try {
+ params = createAlgorithmParameters(sigName,
+ params.getEncoded());
+ } catch (IOException e) {
+ throw new ProviderException(e);
+ }
+ }
+ paramSpec = RSAUtil.getParamSpec(params);
}
- // AlgorithmParameters.getAlgorithm() may returns oid if it's
- // created during DER decoding. Convert to use the standard name
- // before passing it to RSAUtil
- String alg = params.getAlgorithm();
- if (alg.equalsIgnoreCase(sigName) || alg.indexOf(".") != -1) {
- try {
- params = createAlgorithmParameters(sigName,
- params.getEncoded());
- } catch (IOException e) {
- throw new ProviderException(e);
- }
- }
- return RSAUtil.getParamSpec(params);
+ return paramSpec;
}
- // Special method for setting the specified parameter bytes into the
- // specified Signature object as signature parameters.
- public static void specialSetParameter(Signature sig, byte[] paramBytes)
- throws InvalidAlgorithmParameterException, ProviderException {
+ // Utility method for converting the specified parameter bytes into an
+ // AlgorithmParameterSpec object.
+ public static AlgorithmParameterSpec getParamSpec(String sigName,
+ byte[] paramBytes)
+ throws ProviderException {
+ sigName = checkName(sigName);
+ AlgorithmParameterSpec paramSpec = null;
if (paramBytes != null) {
- String sigName = sig.getAlgorithm();
+ if (sigName.toUpperCase().indexOf("RSA") == -1) {
+ throw new ProviderException
+ ("Unrecognized algorithm for signature parameters " +
+ sigName);
+ }
AlgorithmParameters params =
createAlgorithmParameters(sigName, paramBytes);
- specialSetParameter(sig, params);
+ paramSpec = RSAUtil.getParamSpec(params);
}
+ return paramSpec;
}
- // Special method for setting the specified AlgorithmParameter object
- // into the specified Signature object as signature parameters.
- public static void specialSetParameter(Signature sig,
- AlgorithmParameters params)
- throws InvalidAlgorithmParameterException, ProviderException {
- if (params != null) {
- String sigName = sig.getAlgorithm();
- sig.setParameter(getParamSpec(sigName, params));
- }
+ // Utility method for initializing the specified Signature object
+ // for verification with the specified key and params (may be null)
+ public static void initVerifyWithParam(Signature s, PublicKey key,
+ AlgorithmParameterSpec params)
+ throws ProviderException, InvalidAlgorithmParameterException,
+ InvalidKeyException {
+ SharedSecrets.getJavaSecuritySignatureAccess().initVerify(s, key, params);
+ }
+
+ // Utility method for initializing the specified Signature object
+ // for verification with the specified Certificate and params (may be null)
+ public static void initVerifyWithParam(Signature s,
+ java.security.cert.Certificate cert,
+ AlgorithmParameterSpec params)
+ throws ProviderException, InvalidAlgorithmParameterException,
+ InvalidKeyException {
+ SharedSecrets.getJavaSecuritySignatureAccess().initVerify(s, cert, params);
+ }
+
+ // Utility method for initializing the specified Signature object
+ // for signing with the specified key and params (may be null)
+ public static void initSignWithParam(Signature s, PrivateKey key,
+ AlgorithmParameterSpec params, SecureRandom sr)
+ throws ProviderException, InvalidAlgorithmParameterException,
+ InvalidKeyException {
+ SharedSecrets.getJavaSecuritySignatureAccess().initSign(s, key, params, sr);
}
}
--- a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -370,18 +370,16 @@
throw new CRLException("Uninitialized CRL");
}
Signature sigVerf = null;
+ String sigName = sigAlgId.getName();
if (sigProvider.isEmpty()) {
- sigVerf = Signature.getInstance(sigAlgId.getName());
+ sigVerf = Signature.getInstance(sigName);
} else {
- sigVerf = Signature.getInstance(sigAlgId.getName(), sigProvider);
+ sigVerf = Signature.getInstance(sigName, sigProvider);
}
- sigVerf.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selection happens when key is set
try {
- SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
+ SignatureUtil.initVerifyWithParam(sigVerf, key,
+ SignatureUtil.getParamSpec(sigName, getSigAlgParams()));
} catch (ProviderException e) {
throw new CRLException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
@@ -425,18 +423,16 @@
throw new CRLException("Uninitialized CRL");
}
Signature sigVerf = null;
+ String sigName = sigAlgId.getName();
if (sigProvider == null) {
- sigVerf = Signature.getInstance(sigAlgId.getName());
+ sigVerf = Signature.getInstance(sigName);
} else {
- sigVerf = Signature.getInstance(sigAlgId.getName(), sigProvider);
+ sigVerf = Signature.getInstance(sigName, sigProvider);
}
- sigVerf.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selection happens when key is set
try {
- SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
+ SignatureUtil.initVerifyWithParam(sigVerf, key,
+ SignatureUtil.getParamSpec(sigName, getSigAlgParams()));
} catch (ProviderException e) {
throw new CRLException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
@@ -502,7 +498,7 @@
sigEngine.initSign(key);
- // in case the name is reset
+ // in case the name is reset
sigAlgId = AlgorithmId.get(sigEngine.getAlgorithm());
infoSigAlgId = sigAlgId;
--- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Apr 10 10:46:53 2019 +0530
@@ -422,18 +422,16 @@
}
// Verify the signature ...
Signature sigVerf = null;
+ String sigName = algId.getName();
if (sigProvider.isEmpty()) {
- sigVerf = Signature.getInstance(algId.getName());
+ sigVerf = Signature.getInstance(sigName);
} else {
- sigVerf = Signature.getInstance(algId.getName(), sigProvider);
+ sigVerf = Signature.getInstance(sigName, sigProvider);
}
- sigVerf.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selection happens when key is set
try {
- SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
+ SignatureUtil.initVerifyWithParam(sigVerf, key,
+ SignatureUtil.getParamSpec(sigName, getSigAlgParams()));
} catch (ProviderException e) {
throw new CertificateException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
@@ -478,18 +476,16 @@
}
// Verify the signature ...
Signature sigVerf = null;
+ String sigName = algId.getName();
if (sigProvider == null) {
- sigVerf = Signature.getInstance(algId.getName());
+ sigVerf = Signature.getInstance(sigName);
} else {
- sigVerf = Signature.getInstance(algId.getName(), sigProvider);
+ sigVerf = Signature.getInstance(sigName, sigProvider);
}
- sigVerf.initVerify(key);
-
- // set parameters after Signature.initSign/initVerify call,
- // so the deferred provider selection happens when key is set
try {
- SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
+ SignatureUtil.initVerifyWithParam(sigVerf, key,
+ SignatureUtil.getParamSpec(sigName, getSigAlgParams()));
} catch (ProviderException e) {
throw new CertificateException(e.getMessage(), e.getCause());
} catch (InvalidAlgorithmParameterException e) {
@@ -587,22 +583,19 @@
InvalidKeyException, InvalidAlgorithmParameterException,
NoSuchProviderException, SignatureException {
try {
- if (readOnly)
+ if (readOnly) {
throw new CertificateEncodingException(
- "cannot over-write existing certificate");
+ "cannot over-write existing certificate");
+ }
Signature sigEngine = null;
- if (provider == null || provider.isEmpty())
+ if (provider == null || provider.isEmpty()) {
sigEngine = Signature.getInstance(algorithm);
- else
+ } else {
sigEngine = Signature.getInstance(algorithm, provider);
-
- sigEngine.initSign(key);
+ }
- if (signingParams != null) {
- // set parameters after Signature.initSign/initVerify call, so
- // the deferred provider selection happens when the key is set
- sigEngine.setParameter(signingParams);
- }
+ SignatureUtil.initSignWithParam(sigEngine, key, signingParams,
+ null);
// in case the name is reset
if (signingParams != null) {
--- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java Wed Apr 10 10:46:53 2019 +0530
@@ -32,14 +32,64 @@
package sun.util.locale;
+import jdk.internal.misc.VM;
+import jdk.internal.vm.annotation.Stable;
+
import java.lang.ref.SoftReference;
import java.util.StringJoiner;
public final class BaseLocale {
- public static final String SEP = "_";
+ public static @Stable BaseLocale[] constantBaseLocales;
+ public static final byte ENGLISH = 0,
+ FRENCH = 1,
+ GERMAN = 2,
+ ITALIAN = 3,
+ JAPANESE = 4,
+ KOREAN = 5,
+ CHINESE = 6,
+ SIMPLIFIED_CHINESE = 7,
+ TRADITIONAL_CHINESE = 8,
+ FRANCE = 9,
+ GERMANY = 10,
+ ITALY = 11,
+ JAPAN = 12,
+ KOREA = 13,
+ UK = 14,
+ US = 15,
+ CANADA = 16,
+ CANADA_FRENCH = 17,
+ ROOT = 18,
+ NUM_CONSTANTS = 19;
+ static {
+ VM.initializeFromArchive(BaseLocale.class);
+ BaseLocale[] baseLocales = constantBaseLocales;
+ if (baseLocales == null) {
+ baseLocales = new BaseLocale[NUM_CONSTANTS];
+ baseLocales[ENGLISH] = createInstance("en", "");
+ baseLocales[FRENCH] = createInstance("fr", "");
+ baseLocales[GERMAN] = createInstance("de", "");
+ baseLocales[ITALIAN] = createInstance("it", "");
+ baseLocales[JAPANESE] = createInstance("ja", "");
+ baseLocales[KOREAN] = createInstance("ko", "");
+ baseLocales[CHINESE] = createInstance("zh", "");
+ baseLocales[SIMPLIFIED_CHINESE] = createInstance("zh", "CN");
+ baseLocales[TRADITIONAL_CHINESE] = createInstance("zh", "TW");
+ baseLocales[FRANCE] = createInstance("fr", "FR");
+ baseLocales[GERMANY] = createInstance("de", "DE");
+ baseLocales[ITALY] = createInstance("it", "IT");
+ baseLocales[JAPAN] = createInstance("ja", "JP");
+ baseLocales[KOREA] = createInstance("ko", "KR");
+ baseLocales[UK] = createInstance("en", "GB");
+ baseLocales[US] = createInstance("en", "US");
+ baseLocales[CANADA] = createInstance("en", "CA");
+ baseLocales[CANADA_FRENCH] = createInstance("fr", "CA");
+ baseLocales[ROOT] = createInstance("", "");
+ constantBaseLocales = baseLocales;
+ }
+ }
- private static final Cache CACHE = new Cache();
+ public static final String SEP = "_";
private final String language;
private final String script;
@@ -67,28 +117,53 @@
// Called for creating the Locale.* constants. No argument
// validation is performed.
- public static BaseLocale createInstance(String language, String region) {
- BaseLocale base = new BaseLocale(language, "", region, "", false);
- CACHE.put(new Key(base), base);
- return base;
+ private static BaseLocale createInstance(String language, String region) {
+ return new BaseLocale(language, "", region, "", false);
}
public static BaseLocale getInstance(String language, String script,
String region, String variant) {
+
+ if (script == null) {
+ script = "";
+ }
+ if (region == null) {
+ region = "";
+ }
+ if (language == null) {
+ language = null;
+ }
+ if (variant == null) {
+ variant = "";
+ }
+
+ // Non-allocating for most uses
+ language = LocaleUtils.toLowerString(language);
+ region = LocaleUtils.toUpperString(region);
+
+ // Check for constant base locales first
+ if (script.isEmpty() && variant.isEmpty()) {
+ for (BaseLocale baseLocale : constantBaseLocales) {
+ if (baseLocale.getLanguage().equals(language)
+ && baseLocale.getRegion().equals(region)) {
+ return baseLocale;
+ }
+ }
+ }
+
// JDK uses deprecated ISO639.1 language codes for he, yi and id
- if (language != null) {
- if (LocaleUtils.caseIgnoreMatch(language, "he")) {
+ if (!language.isEmpty()) {
+ if (language.equals("he")) {
language = "iw";
- } else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
+ } else if (language.equals("yi")) {
language = "ji";
- } else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
+ } else if (language.equals("id")) {
language = "in";
}
}
Key key = new Key(language, script, region, variant, false);
- BaseLocale baseLocale = CACHE.get(key);
- return baseLocale;
+ return Cache.CACHE.get(key);
}
public String getLanguage() {
@@ -171,46 +246,8 @@
private final boolean normalized;
private final int hash;
- /**
- * Creates a Key. language and region must be normalized
- * (intern'ed in the proper case).
- */
- private Key(BaseLocale locale) {
- this.holder = locale;
- this.holderRef = null;
- this.normalized = true;
- String language = locale.getLanguage();
- String region = locale.getRegion();
- assert LocaleUtils.toLowerString(language).intern() == language
- && LocaleUtils.toUpperString(region).intern() == region
- && locale.getVariant() == ""
- && locale.getScript() == "";
-
- int h = language.hashCode();
- if (region != "") {
- int len = region.length();
- for (int i = 0; i < len; i++) {
- h = 31 * h + LocaleUtils.toLower(region.charAt(i));
- }
- }
- hash = h;
- }
-
private Key(String language, String script, String region,
String variant, boolean normalize) {
- if (language == null) {
- language = "";
- }
- if (script == null) {
- script = "";
- }
- if (region == null) {
- region = "";
- }
- if (variant == null) {
- variant = "";
- }
-
BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
this.normalized = normalize;
if (normalized) {
@@ -291,6 +328,8 @@
private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
+ private static final Cache CACHE = new Cache();
+
public Cache() {
}
--- a/src/java.base/share/classes/sun/util/locale/LocaleUtils.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/util/locale/LocaleUtils.java Wed Apr 10 10:46:53 2019 +0530
@@ -206,19 +206,19 @@
return true;
}
- static boolean isEmpty(String str) {
+ public static boolean isEmpty(String str) {
return str == null || str.isEmpty();
}
- static boolean isEmpty(Set<?> set) {
+ public static boolean isEmpty(Set<?> set) {
return set == null || set.isEmpty();
}
- static boolean isEmpty(Map<?, ?> map) {
+ public static boolean isEmpty(Map<?, ?> map) {
return map == null || map.isEmpty();
}
- static boolean isEmpty(List<?> list) {
+ public static boolean isEmpty(List<?> list) {
return list == null || list.isEmpty();
}
}
--- a/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Apr 10 10:46:53 2019 +0530
@@ -491,8 +491,7 @@
*/
private static class AvailableJRELocales {
private static final Locale[] localeList = createAvailableLocales();
- private AvailableJRELocales() {
- }
+ private AvailableJRELocales() {}
}
private static Locale[] createAvailableLocales() {
@@ -535,7 +534,7 @@
public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
if (Locale.ROOT.equals(locale)) {
return true;
-}
+ }
locale = locale.stripExtensions();
if (langtags.contains(locale.toLanguageTag())) {
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Wed Apr 10 10:46:53 2019 +0530
@@ -44,6 +44,7 @@
import java.lang.ref.SoftReference;
import java.text.MessageFormat;
import java.text.NumberFormat;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -325,7 +326,7 @@
Set<String> keyset = getZoneIDs();
// Use a LinkedHashSet to preseve the order
Set<String[]> value = new LinkedHashSet<>();
- Set<String> tzIds = new HashSet<>(Set.of(TimeZone.getAvailableIDs()));
+ Set<String> tzIds = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
for (String key : keyset) {
if (!key.startsWith(TZNB_EXCITY_PREFIX)) {
value.add(rb.getStringArray(key));
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -75,6 +75,7 @@
public static final int IO_REPARSE_TAG_SYMLINK = 0xA000000C;
public static final int MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024;
public static final int SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1;
+ public static final int SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2;
// volume flags
public static final int FILE_CASE_SENSITIVE_SEARCH = 0x00000001;
@@ -104,6 +105,7 @@
public static final int ERROR_MORE_DATA = 234;
public static final int ERROR_DIRECTORY = 267;
public static final int ERROR_NOTIFY_ENUM_DIR = 1022;
+ public static final int ERROR_PRIVILEGE_NOT_HELD = 1314;
public static final int ERROR_NONE_MAPPED = 1332;
public static final int ERROR_NOT_A_REPARSE_POINT = 4390;
public static final int ERROR_INVALID_REPARSE_DATA = 4392;
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -29,6 +29,8 @@
import java.security.PrivilegedAction;
import jdk.internal.misc.Unsafe;
+import static sun.nio.fs.WindowsConstants.*;
+
/**
* Win32 and library calls.
*/
@@ -920,6 +922,12 @@
* LPCWSTR lpTargetFileName,
* DWORD dwFlags
* )
+ *
+ * Creates a symbolic link, conditionally retrying with the addition of
+ * the flag SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE if the initial
+ * attempt fails with ERROR_PRIVILEGE_NOT_HELD. If the retry fails, throw
+ * the original exception due to ERROR_PRIVILEGE_NOT_HELD. The retry will
+ * succeed only on Windows build 14972 or later if Developer Mode is on.
*/
static void CreateSymbolicLink(String link, String target, int flags)
throws WindowsException
@@ -929,6 +937,19 @@
try {
CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(),
flags);
+ } catch (WindowsException x) {
+ if (x.lastError() == ERROR_PRIVILEGE_NOT_HELD) {
+ flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+ try {
+ CreateSymbolicLink0(linkBuffer.address(),
+ targetBuffer.address(), flags);
+ return;
+ } catch (WindowsException ignored) {
+ // Will fail with ERROR_INVALID_PARAMETER for Windows
+ // builds older than 14972.
+ }
+ }
+ throw x;
} finally {
targetBuffer.release();
linkBuffer.release();
--- a/src/java.base/windows/native/libjli/java_md.c Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/windows/native/libjli/java_md.c Wed Apr 10 10:46:53 2019 +0530
@@ -41,8 +41,6 @@
#define JVM_DLL "jvm.dll"
#define JAVA_DLL "java.dll"
-#define ELP_PREFIX L"\\\\?\\"
-
/*
* Prototypes.
*/
@@ -497,57 +495,67 @@
return rc;
}
-/* On Windows, if _open fails, retry again with CreateFileW and
- * "\\?\" prefix ( extended-length paths) - this allows to open paths with larger file names;
- * otherwise we run into the MAX_PATH limitation */
-int JLI_Open(const char* name, int flags) {
- int fd = _open(name, flags);
- if (fd == -1 && errno == ENOENT) {
- wchar_t* wname = NULL;
- wchar_t* wfullname = NULL;
- wchar_t* wfullname_w_prefix = NULL;
- size_t wnamelen, wfullnamelen, elplen;
- HANDLE h;
-
- wnamelen = strlen(name) + 1;
- wname = (wchar_t*) malloc(wnamelen*sizeof(wchar_t));
- if (wname == NULL) {
- goto end;
- }
- if (mbstowcs(wname, name, wnamelen - 1) == -1) {
- goto end;
+/* taken from hotspot and slightly adjusted for jli lib;
+ * creates a UNC/ELP path from input 'path'
+ * the return buffer is allocated in C heap and needs to be freed using
+ * JLI_MemFree by the caller.
+ */
+static wchar_t* create_unc_path(const char* path, errno_t* err) {
+ wchar_t* wpath = NULL;
+ size_t converted_chars = 0;
+ size_t path_len = strlen(path) + 1; /* includes the terminating NULL */
+ if (path[0] == '\\' && path[1] == '\\') {
+ if (path[2] == '?' && path[3] == '\\') {
+ /* if it already has a \\?\ don't do the prefix */
+ wpath = (wchar_t*) JLI_MemAlloc(path_len * sizeof(wchar_t));
+ if (wpath != NULL) {
+ *err = mbstowcs_s(&converted_chars, wpath, path_len, path, path_len);
+ } else {
+ *err = ENOMEM;
+ }
+ } else {
+ /* only UNC pathname includes double slashes here */
+ wpath = (wchar_t*) JLI_MemAlloc((path_len + 7) * sizeof(wchar_t));
+ if (wpath != NULL) {
+ wcscpy(wpath, L"\\\\?\\UNC\0");
+ *err = mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len);
+ } else {
+ *err = ENOMEM;
+ }
}
- wname[wnamelen - 1] = L'\0';
- wfullname = _wfullpath(wfullname, wname, 0);
- if (wfullname == NULL) {
- goto end;
+ } else {
+ wpath = (wchar_t*) JLI_MemAlloc((path_len + 4) * sizeof(wchar_t));
+ if (wpath != NULL) {
+ wcscpy(wpath, L"\\\\?\\\0");
+ *err = mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len);
+ } else {
+ *err = ENOMEM;
}
-
- wfullnamelen = wcslen(wfullname);
- if (wfullnamelen > 247) {
- elplen = wcslen(ELP_PREFIX);
- wfullname_w_prefix = (wchar_t*) malloc((elplen+wfullnamelen+1)*sizeof(wchar_t));
- wcscpy(wfullname_w_prefix, ELP_PREFIX);
- wcscpy(wfullname_w_prefix+elplen, wfullname);
+ }
+ return wpath;
+}
- h = CreateFileW(wfullname_w_prefix, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- goto end;
- }
- /* associates fd with handle */
- fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
+int JLI_Open(const char* name, int flags) {
+ int fd;
+ if (strlen(name) < MAX_PATH) {
+ fd = _open(name, flags);
+ } else {
+ errno_t err = ERROR_SUCCESS;
+ wchar_t* wpath = create_unc_path(name, &err);
+ if (err != ERROR_SUCCESS) {
+ if (wpath != NULL) JLI_MemFree(wpath);
+ errno = err;
+ return -1;
}
-end:
- free(wname);
- free(wfullname);
- free(wfullname_w_prefix);
+ fd = _wopen(wpath, flags);
+ if (fd == -1) {
+ errno = GetLastError();
+ }
+ JLI_MemFree(wpath);
}
return fd;
}
-
-
JNIEXPORT void JNICALL
JLI_ReportErrorMessage(const char* fmt, ...) {
va_list vl;
--- a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c Wed Apr 10 10:32:43 2019 +0530
+++ b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c Wed Apr 10 10:46:53 2019 +0530
@@ -1063,17 +1063,7 @@
LPCWSTR link = jlong_to_ptr(linkAddress);
LPCWSTR target = jlong_to_ptr(targetAddress);
- // Allow creation of symbolic links when the process is not elevated.
- // Developer Mode must be enabled for this option to function, otherwise
- // it will be ignored. Check that symbol is available in current build SDK.
- DWORD dwFlags = (DWORD)flags;
-#ifdef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
- dwFlags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
-#endif
-
- // On Windows 64-bit this appears to succeed even when there are
- // insufficient privileges
- if (CreateSymbolicLinkW(link, target, dwFlags) == 0)
+ if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0)
throwWindowsException(env, GetLastError());
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -172,7 +172,7 @@
return 2;
}
public static int cellOffset(int index) {
- return MethodData.cellSize + index * MethodData.cellSize;
+ return (headerSizeInCells() + index) * MethodData.cellSize;
}
// // Return a value which, when or-ed as a byte into _flags, sets the flag.
// static int flagNumberToByteConstant(int flagNumber) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java Wed Apr 10 10:46:53 2019 +0530
@@ -62,7 +62,7 @@
* <p>
*
* <a id="terminology"></a>
- * <h3>Terminology</h3>
+ * <h2>Terminology</h2>
*
* <dl>
* <dt><a id="selected"></a>Selected</dt>
@@ -88,7 +88,7 @@
* </dl>
* <p>
* <a id="options"></a>
- * <h3>Options</h3>
+ * <h2>Options</h2>
* Javadoc <em>selection control</em> can be specified with these options
* as follows:
* <ul>
@@ -132,7 +132,7 @@
* </ul>
* <p>
* <a id="legacy-interactions"></a>
- * <h4>Interactions with older options.</h4>
+ * <h3>Interactions with older options.</h3>
*
* The new {@code --show-*} options provide a more detailed replacement
* for the older options {@code -public}, {@code -protected}, {@code -package}, {@code -private}.
@@ -181,7 +181,7 @@
* <p>
*
* <a id="example"></a>
- * <h3>Example</h3>
+ * <h2>Example</h2>
*
* The following is an example doclet that displays information of a class
* and its members, supporting an option.
@@ -300,7 +300,7 @@
* source-location/Example.java
* </pre>
*
- * <h3><a id="migration">Migration Guide</a></h3>
+ * <h2><a id="migration">Migration Guide</a></h2>
*
* <p>Many of the types in the old {@code com.sun.javadoc} API do not have equivalents in this
* package. Instead, types in the {@code javax.lang.model} and {@code com.sun.source} APIs
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Wed Apr 10 10:46:53 2019 +0530
@@ -722,9 +722,7 @@
* @return an HtmlTree object for the SECTION tag
*/
public static HtmlTree SECTION() {
- HtmlTree htmltree = new HtmlTree(HtmlTag.SECTION);
- htmltree.setRole(Role.REGION);
- return htmltree;
+ return new HtmlTree(HtmlTag.SECTION);
}
/**
@@ -734,9 +732,7 @@
* @return an HtmlTree object for the SECTION tag
*/
public static HtmlTree SECTION(Content body) {
- HtmlTree htmltree = new HtmlTree(HtmlTag.SECTION, nullCheck(body));
- htmltree.setRole(Role.REGION);
- return htmltree;
+ return new HtmlTree(HtmlTag.SECTION, nullCheck(body));
}
/**
--- a/src/jdk.jcmd/linux/classes/sun/tools/ProcessHelper.java Wed Apr 10 10:32:43 2019 +0530
+++ b/src/jdk.jcmd/linux/classes/sun/tools/ProcessHelper.java Wed Apr 10 10:46:53 2019 +0530
@@ -31,7 +31,6 @@
import java.nio.file.Paths;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
-import java.util.jar.Manifest;
import java.util.stream.Stream;
/**
@@ -50,9 +49,12 @@
/**
* Gets the main class name for the given Java process by parsing the
- * process command line.
+ * process command line. If the application was started with the <em>-jar</em>
+ * option this method returns the name of the jar file. If the application
+ * was started with <em>-m</em> or <em>--module</em> option, the method returns
+ * the module name and the main class name.
* @param pid - process ID (pid)
- * @return main class name or null if the process no longer exists or
+ * @return the main class name or null if the process no longer exists or
* was started with a native launcher (e.g. jcmd etc)
*/
@@ -81,20 +83,16 @@
}
}
- // If -jar option is used then read the main class name from the manifest file.
- // Otherwise, the main class name is either specified in -m or --module options or it
- // is the first part that is not a Java option (doesn't start with '-' and is not a
- // classpath or a module path).
+ // To be consistent with the behavior on other platforms, if -jar, -m, or --module
+ // options are used then just return the value (the path to the jar file or module
+ // name with a main class). Otherwise, the main class name is the first part that
+ // is not a Java option (doesn't start with '-' and is not a classpath or a module
+ // path).
for (int i = 1; i < parts.length && mainClass == null; i++) {
if (i < parts.length - 1) {
- // Check if the module is executed with explicitly specified main class
- if ((parts[i].equals("-m") || parts[i].equals("--module"))) {
- return getMainClassFromModuleArg(parts[i + 1]);
- }
- // Check if the main class needs to be read from the manifest.mf in a JAR file
- if (parts[i].equals("-jar")) {
- return getMainClassFromJar(parts[i + 1], pid);
+ if (parts[i].equals("-m") || parts[i].equals("--module") || parts[i].equals("-jar")) {
+ return parts[i + 1];
}
}
// If this is a classpath or a module path option then skip the next part
@@ -114,34 +112,6 @@
}
- private String getMainClassFromModuleArg(String moduleArg) {
- int pos = moduleArg.lastIndexOf("/");
- return (pos > 0 && pos < moduleArg.length()-1) ? moduleArg.substring(pos + 1) : null;
- }
-
- private String getMainClassFromJar(String jar, String pid) {
- if (!jar.startsWith("/")) {
- String cwd = getCurrentWorkingDir(pid);
- if (cwd != null) {
- jar = cwd + "/" + jar;
- }
- }
- try (JarFile jarFile = new JarFile(jar)) {
- Manifest mf = jarFile.getManifest();
- if (mf != null) {
- Attributes mainAttributes = mf.getMainAttributes();
- return mainAttributes.getValue("Main-Class");
- }
- } catch (IOException e) {
- return null;
- }
- return null;
- }
-
- private static String getCurrentWorkingDir(String pid) {
- return ("/proc/" + pid + "/cwd");
- }
-
private static String getCommandLine(String pid) {
try (Stream<String> lines =
Files.lines(Paths.get("/proc/" + pid + "/cmdline"))) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/memory/test_is_metaspace_obj.cpp Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, 2018 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.
+ */
+
+#include "precompiled.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/metaspace.hpp"
+#include "memory/metaspace/virtualSpaceList.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/os.hpp"
+#include "unittest.hpp"
+
+using namespace metaspace;
+
+
+// Test the cheerful multitude of metaspace-contains-functions.
+class MetaspaceIsMetaspaceObjTest : public ::testing::Test {
+ Mutex* _lock;
+ ClassLoaderMetaspace* _ms;
+
+public:
+
+ MetaspaceIsMetaspaceObjTest() : _lock(NULL), _ms(NULL) {}
+
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ delete _ms;
+ delete _lock;
+ }
+
+ void do_test(Metaspace::MetadataType mdType) {
+ _lock = new Mutex(Monitor::native, "gtest-IsMetaspaceObjTest-lock", false, Monitor::_safepoint_check_never);
+ {
+ MutexLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+ _ms = new ClassLoaderMetaspace(_lock, Metaspace::StandardMetaspaceType);
+ }
+
+ const MetaspaceObj* p = (MetaspaceObj*) _ms->allocate(42, mdType);
+
+ // Test MetaspaceObj::is_metaspace_object
+ ASSERT_TRUE(MetaspaceObj::is_valid(p));
+
+ // A misaligned object shall not be recognized
+ const MetaspaceObj* p_misaligned = (MetaspaceObj*)((address)p) + 1;
+ ASSERT_FALSE(MetaspaceObj::is_valid(p_misaligned));
+
+ // Test VirtualSpaceList::contains and find_enclosing_space
+ VirtualSpaceList* list = Metaspace::space_list();
+ if (mdType == Metaspace::ClassType && Metaspace::using_class_space()) {
+ list = Metaspace::class_space_list();
+ }
+ ASSERT_TRUE(list->contains(p));
+ VirtualSpaceNode* const n = list->find_enclosing_space(p);
+ ASSERT_TRUE(n != NULL);
+ ASSERT_TRUE(n->contains(p));
+
+ // A misaligned pointer shall be recognized by list::contains
+ ASSERT_TRUE(list->contains((address)p) + 1);
+
+ // Now for some bogus values
+ ASSERT_FALSE(MetaspaceObj::is_valid((MetaspaceObj*)NULL));
+
+ // Should exercise various paths in MetaspaceObj::is_valid()
+ ASSERT_FALSE(MetaspaceObj::is_valid((MetaspaceObj*)1024));
+ ASSERT_FALSE(MetaspaceObj::is_valid((MetaspaceObj*)8192));
+
+ MetaspaceObj* p_stack = (MetaspaceObj*) &_lock;
+ ASSERT_FALSE(MetaspaceObj::is_valid(p_stack));
+
+ MetaspaceObj* p_heap = (MetaspaceObj*) os::malloc(41, mtInternal);
+ ASSERT_FALSE(MetaspaceObj::is_valid(p_heap));
+ os::free(p_heap);
+
+ // Test Metaspace::contains_xxx
+ ASSERT_TRUE(Metaspace::contains(p));
+ ASSERT_TRUE(Metaspace::contains_non_shared(p));
+
+ delete _ms;
+ _ms = NULL;
+ delete _lock;
+ _lock = NULL;
+ }
+
+};
+
+TEST_VM_F(MetaspaceIsMetaspaceObjTest, non_class_space) {
+ do_test(Metaspace::NonClassType);
+}
+
+TEST_VM_F(MetaspaceIsMetaspaceObjTest, class_space) {
+ do_test(Metaspace::ClassType);
+}
+
--- a/test/hotspot/gtest/threadHelper.inline.hpp Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/gtest/threadHelper.inline.hpp Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -66,7 +66,7 @@
// Override as JavaThread::post_run() calls JavaThread::exit which
// expects a valid thread object oop.
virtual void post_run() {
- Threads::remove(this);
+ Threads::remove(this, false);
this->smr_delete();
}
@@ -118,7 +118,7 @@
// Override as JavaThread::post_run() calls JavaThread::exit which
// expects a valid thread object oop. And we need to call signal.
void post_run() {
- Threads::remove(this);
+ Threads::remove(this, false);
_post->signal();
this->smr_delete();
}
--- a/test/hotspot/jtreg/ProblemList-graal.txt Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Wed Apr 10 10:46:53 2019 +0530
@@ -53,8 +53,16 @@
gc/arguments/TestNewSizeFlags.java 8196611 generic-all
gc/arguments/TestVerifyBeforeAndAfterGCFlags.java 8196611 generic-all
+gc/g1/mixedgc/TestOldGenCollectionUsage.java 8196611 generic-all
gc/g1/TestConcurrentSystemGC.java 8196611 generic-all
+gc/g1/TestPeriodicCollection.java 8196611 generic-all
+gc/parallel/TestPrintGCDetailsVerbose.java 8196611 generic-all
vmTestbase/gc/lock/malloc/malloclock03/TestDescription.java 8196611 macosx-all
+vmTestbase/nsk/stress/except/except004.java 8196611 generic-all
+vmTestbase/nsk/stress/except/except007.java 8196611 generic-all
+vmTestbase/nsk/stress/except/except008.java 8196611 generic-all
+vmTestbase/nsk/stress/except/except011.java 8196611 generic-all
+serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java 8196611 generic-all
gc/g1/ihop/TestIHOPErgo.java 8191048 generic-all
gc/g1/plab/TestPLABEvacuationFailure.java 8191048 generic-all
@@ -65,8 +73,6 @@
compiler/compilercontrol/directives/LogTest.java 8181753 generic-all
-gc/parallel/TestPrintGCDetailsVerbose.java 8196611 macosx-all
-
compiler/jvmci/compilerToVM/ReprofileTest.java 8201333 generic-all
compiler/tiered/LevelTransitionTest.java 8202124 generic-all
@@ -212,6 +218,8 @@
vmTestbase/nsk/jdb/clear/clear003/clear003.java 8218701 generic-all
+compiler/jsr292/InvokerSignatureMismatch.java 8221577 generic-all
+
# Graal unit tests
org.graalvm.compiler.core.test.CheckGraalInvariants 8205081
org.graalvm.compiler.core.test.OptionsVerifierTest 8205081
@@ -222,4 +230,3 @@
org.graalvm.compiler.core.test.deopt.CompiledMethodTest 8202955
org.graalvm.compiler.hotspot.test.ReservedStackAccessTest 8213567 windows-all
-
--- a/test/hotspot/jtreg/ProblemList.txt Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/ProblemList.txt Wed Apr 10 10:46:53 2019 +0530
@@ -67,8 +67,6 @@
gc/epsilon/TestMemoryMXBeans.java 8206434 generic-all
gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all
-gc/survivorAlignment/TestPromotionToSurvivor.java 8218049 generic-all
-gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8218049 generic-all
gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
@@ -80,9 +78,9 @@
# :hotspot_runtime
-runtime/NMT/CheckForProperDetailStackTrace.java 8218458 generic-all
runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all
runtime/containers/docker/TestCPUSets.java 8220672 generic-all
+runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64
#############################################################################
@@ -172,6 +170,9 @@
vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java 6606767 generic-all
vmTestbase/nsk/jvmti/scenarios/extension/EX03/ex03t001/TestDescription.java 8173658 generic-all
vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8202971 generic-all
+vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/TestDescription.java 8219652 aix-ppc64
+vmTestbase/nsk/jvmti/scenarios/jni_interception/JI06/ji06t001/TestDescription.java 8219652 aix-ppc64
+vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/TestDescription.java 8219652 aix-ppc64
vmTestbase/gc/lock/jni/jnilock002/TestDescription.java 8208243,8192647 generic-all
--- a/test/hotspot/jtreg/compiler/graalunit/ApiDirectivesTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/ApiDirectivesTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.api.directives.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.api.directives.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/ApiTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/ApiTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.api.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.api.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/AsmAarch64Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/AsmAarch64Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.aarch64.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.aarch64.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/AsmAmd64Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/AsmAmd64Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.amd64.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.amd64.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/AsmSparcTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/AsmSparcTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.sparc.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.asm.sparc.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/CollectionsTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/CollectionsTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix jdk.internal.vm.compiler.collections.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix jdk.internal.vm.compiler.collections.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/CoreAmd64Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreAmd64Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.amd64.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.amd64.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/CoreTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/DebugTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/DebugTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.debug.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.debug.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/EA9Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/EA9Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test.ea -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test.ea -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/EATest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/EATest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.test.ea -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.test.ea -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/GraphTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/GraphTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.graph.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.graph.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/HotspotAmd64Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotAmd64Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.amd64.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.amd64.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/HotspotJdk9Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotJdk9Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.jdk9.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.jdk9.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/HotspotLirTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotLirTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.lir.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.lir.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/HotspotSparcTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotSparcTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.sparc.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.sparc.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/HotspotTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/Jtt.MicroTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/Jtt.MicroTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.micro -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.micro -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttBackendTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttBackendTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.backend -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.backend -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttBytecodeTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttBytecodeTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.bytecode -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.bytecode -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttExceptTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttExceptTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.except -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.except -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttHotpathTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttHotpathTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.hotpath -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.hotpath -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttHotspotTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttHotspotTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.hotspot -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.hotspot -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttJdkTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttJdkTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.jdk -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.jdk -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttLangALTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttLangALTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.[a-lA-L] -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.[a-lA-L] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,6 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher
- * -prefix org.graalvm.compiler.jtt.lang.Math_[a-lA-L] -exclude ExcludeList.txt
+ * @run main/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.Math_[a-lA-L] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,6 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher
- * -prefix org.graalvm.compiler.jtt.lang.Math_[m-zM-Z] -exclude ExcludeList.txt
+ * @run main/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.Math_[m-zM-Z] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttLangNZTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttLangNZTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.[n-zN-Z] -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.[n-zN-Z] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttLoopTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttLoopTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.loop -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.loop -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttOptimizeTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttOptimizeTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.optimize -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.optimize -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttReflectAETest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttReflectAETest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.[a-eA-E] -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.[a-eA-E] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttReflectFieldGetTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttReflectFieldGetTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.Field_get -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.Field_get -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttReflectFieldSetTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttReflectFieldSetTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.Field_set -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.Field_set -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttReflectGZTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttReflectGZTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.[g-zG-Z] -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.reflect.[g-zG-Z] -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/JttThreadsTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/JttThreadsTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.threads -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.threads -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/LirJttTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/LirJttTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.lir.jtt -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.lir.jtt -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/LirTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/LirTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.lir.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.lir.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/LoopTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/LoopTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.loop.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.loop.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/NodesTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/NodesTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.nodes.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.nodes.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/OptionsTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/OptionsTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.options.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.options.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/PhasesCommonTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/PhasesCommonTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.phases.common.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.phases.common.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/Replacements12Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/Replacements12Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.jdk12.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.jdk12.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/Replacements9Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/Replacements9Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.jdk9.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.jdk9.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/ReplacementsTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/ReplacementsTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.replacements.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt Wed Apr 10 10:46:53 2019 +0530
@@ -30,8 +30,8 @@
JttHotspot org.graalvm.compiler.jtt.hotspot
JttJdk org.graalvm.compiler.jtt.jdk
JttLangAL org.graalvm.compiler.jtt.lang.[a-lA-L]
-JttLangMathAL org.graalvm.compiler.jtt.lang.Math_[a-lA-L]
-JttLangMathMZ org.graalvm.compiler.jtt.lang.Math_[m-zM-Z]
+JttLangMathAL org.graalvm.compiler.jtt.lang.Math_[a-lA-L] timeout=300
+JttLangMathMZ org.graalvm.compiler.jtt.lang.Math_[m-zM-Z] timeout=300
JttLangNZ org.graalvm.compiler.jtt.lang.[n-zN-Z]
JttLoop org.graalvm.compiler.jtt.loop
Jtt.Micro org.graalvm.compiler.jtt.micro
--- a/test/hotspot/jtreg/compiler/graalunit/UtilTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/UtilTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -34,5 +34,7 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.util.test -exclude ExcludeList.txt
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.util.test -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/generateTests.sh Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/compiler/graalunit/generateTests.sh Wed Apr 10 10:46:53 2019 +0530
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 2019, 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
@@ -22,14 +22,22 @@
# questions.
#
-while read -r fName pName requireInfo
+while read -r fName pName timeoutInfo requireInfo
do
fName="${fName}Test.java"
echo "Generate $fName for $pName ..."
+ action="main"
+ if [[ $timeoutInfo == timeout* ]] ; then
+ action="$action/$timeoutInfo"
+ else
+ requireInfo="$timeoutInfo $requireInfo"
+ fi
+
+
cat << EOF | sed 's/[[:blank:]]*$//' > $fName
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -64,8 +72,10 @@
*
* @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
*
- * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix $pName -exclude ExcludeList.txt
+ * @run $action compiler.graalunit.common.GraalUnitTestLauncher -prefix $pName -exclude ExcludeList.txt
*/
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
EOF
done < TestPackages.txt
--- a/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Wed Apr 10 10:46:53 2019 +0530
@@ -31,6 +31,8 @@
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g TestMemoryMXBeans -1 1024
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms1g -Xmx1g TestMemoryMXBeans 1024 1024
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms128m -Xmx1g TestMemoryMXBeans 128 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms1g -Xmx1g -XX:ShenandoahUncommitDelay=0 TestMemoryMXBeans 1024 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms128m -Xmx1g -XX:ShenandoahUncommitDelay=0 TestMemoryMXBeans 128 1024
*/
import java.lang.management.*;
@@ -46,6 +48,9 @@
long initSize = 1L * Integer.parseInt(args[0]) * 1024 * 1024;
long maxSize = 1L * Integer.parseInt(args[1]) * 1024 * 1024;
+ // wait for GC to uncommit
+ Thread.sleep(1000);
+
testMemoryBean(initSize, maxSize);
}
@@ -65,7 +70,15 @@
throw new IllegalStateException("Max heap size is wrong: " + heapMax + " vs " + maxSize);
}
if (initSize > 0 && maxSize > 0 && initSize != maxSize && heapCommitted == heapMax) {
- throw new IllegalStateException("Init committed heap size is wrong: " + heapCommitted +
+ throw new IllegalStateException("Committed heap size is max: " + heapCommitted +
+ " (init: " + initSize + ", max: " + maxSize + ")");
+ }
+ if (initSize > 0 && maxSize > 0 && initSize == maxSize && heapCommitted != heapMax) {
+ throw new IllegalStateException("Committed heap size is not max: " + heapCommitted +
+ " (init: " + initSize + ", max: " + maxSize + ")");
+ }
+ if (initSize > 0 && heapCommitted < initSize) {
+ throw new IllegalStateException("Committed heap size is below min: " + heapCommitted +
" (init: " + initSize + ", max: " + maxSize + ")");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestSafepointWorkers.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * 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 TestSingleSafepointWorker
+ * @key gc
+ * @requires vm.gc.Shenandoah
+ *
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahParallelSafepointThreads=1 -Xmx128m TestSafepointWorkers
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahParallelSafepointThreads=2 -Xmx128m TestSafepointWorkers
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahParallelSafepointThreads=4 -Xmx128m TestSafepointWorkers
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahParallelSafepointThreads=8 -Xmx128m TestSafepointWorkers
+ */
+
+public class TestSafepointWorkers {
+ static final long TARGET_MB = Long.getLong("target", 1000); // 1 Gb allocation
+
+ static volatile Object sink;
+
+ public static void main(String[] args) throws Exception {
+ long count = TARGET_MB * 1024 * 1024 / 16;
+ for (long c = 0; c < count; c++) {
+ sink = new Object();
+ }
+ }
+}
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java Wed Apr 10 10:46:53 2019 +0530
@@ -43,13 +43,9 @@
public static void main(String[] args) throws Exception {
String[][] opts = {
new String[] { "ShenandoahKeepAliveBarrier" },
- new String[] { "ShenandoahWriteBarrier" },
- new String[] { "ShenandoahReadBarrier" },
- // StoreValRead+SATB are actually compatible, but we need to protect against
- // StorveValEnqueue+SATB. TODO: Make it better.
- new String[] { "ShenandoahSATBBarrier", "ShenandoahStoreValReadBarrier", "ShenandoahStoreValEnqueueBarrier" },
+ new String[] { "ShenandoahLoadRefBarrier" },
+ new String[] { "ShenandoahSATBBarrier", "ShenandoahStoreValEnqueueBarrier" },
new String[] { "ShenandoahCASBarrier" },
- new String[] { "ShenandoahAcmpBarrier" },
new String[] { "ShenandoahCloneBarrier" },
};
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,21 +38,16 @@
public static void main(String[] args) throws Exception {
String[] concurrent = {
- "ShenandoahReadBarrier",
- "ShenandoahWriteBarrier",
+ "ShenandoahLoadRefBarrier",
"ShenandoahCASBarrier",
- "ShenandoahAcmpBarrier",
"ShenandoahCloneBarrier",
"ShenandoahSATBBarrier",
"ShenandoahKeepAliveBarrier",
- "ShenandoahStoreValReadBarrier",
};
String[] traversal = {
- "ShenandoahReadBarrier",
- "ShenandoahWriteBarrier",
+ "ShenandoahLoadRefBarrier",
"ShenandoahCASBarrier",
- "ShenandoahAcmpBarrier",
"ShenandoahCloneBarrier",
};
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,7 +24,7 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestAllocationInEden
* @bug 8031323
* @summary Verify that object's alignment in eden space is not affected by
* SurvivorAlignmentInBytes option.
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,7 +24,7 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestPromotionFromEdenToTenured
* @bug 8031323
* @summary Verify that objects promoted from eden space to tenured space during
* full GC are not aligned to SurvivorAlignmentInBytes value.
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,7 +24,7 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterFullGC
* @bug 8031323
* @summary Verify that objects promoted from survivor space to tenured space
* during full GC are not aligned to SurvivorAlignmentInBytes value.
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,13 +24,14 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestPromotionFromSurvivorToTenuredAfterMinorGC
* @bug 8031323
* @summary Verify that objects promoted from survivor space to tenured space
* when their age exceeded tenuring threshold are not aligned to
* SurvivorAlignmentInBytes value.
* @requires vm.gc != "Z" & vm.gc != "Shenandoah"
* @library /test/lib
+ * @library /
* @modules java.base/jdk.internal.misc
* java.management
* @build sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,7 +24,7 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestPromotionLABLargeSurvivorAlignment
* @bug 8060463
* @summary Verify that objects promoted from eden space to survivor space
* with large values for SurvivorAlignmentInBytes succeed.
--- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,12 +24,13 @@
package gc.survivorAlignment;
/**
- * @test
+ * @test gc.survivorAlignment.TestPromotionToSurvivor
* @bug 8031323
* @summary Verify that objects promoted from eden space to survivor space after
* minor GC are aligned to SurvivorAlignmentInBytes.
* @requires vm.gc != "Z" & vm.gc != "Shenandoah"
* @library /test/lib
+ * @library /
* @modules java.base/jdk.internal.misc
* java.management
* @build sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,19 +38,19 @@
// Break expected error messages into 3 parts since the loader name includes its identity
// hash which is unique and can't be compared against.
static String expectedErrorMessage1_part1 = "loader constraint violation in interface itable initialization for " +
- "class test.C: when selecting method test.I.m()Ltest/Foo; the class loader " +
+ "class test.C: when selecting method 'test.Foo test.I.m()' the class loader " +
"PreemptingClassLoader @";
static String expectedErrorMessage1_part2 = " for super interface test.I, and the class loader 'app' of the " +
- "selected method's type, test.J have different Class objects for the " +
+ "selected method's interface, test.J have different Class objects for the " +
"type test.Foo used in the signature (test.I is in unnamed module of loader " +
"PreemptingClassLoader @";
static String expectedErrorMessage1_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
static String expectedErrorMessage2_part1 = "loader constraint violation in interface itable initialization for " +
- "class test.C: when selecting method test.I.m()Ltest/Foo; the class loader " +
+ "class test.C: when selecting method 'test.Foo test.I.m()' the class loader " +
"'ItableLdrCnstrnt_Test_Loader' @";
static String expectedErrorMessage2_part2 = " for super interface test.I, and the class loader 'app' of the " +
- "selected method's type, test.J have different Class objects for the " +
+ "selected method's interface, test.J have different Class objects for the " +
"type test.Foo used in the signature (test.I is in unnamed module of loader " +
"'ItableLdrCnstrnt_Test_Loader' @";
static String expectedErrorMessage2_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
@@ -79,7 +79,9 @@
if (!errorMsg.contains(expectedErrorMessage_part1) ||
!errorMsg.contains(expectedErrorMessage_part2) ||
!errorMsg.contains(expectedErrorMessage_part3)) {
- System.out.println("Expected: " + expectedErrorMessage_part1 + "<id>" + expectedErrorMessage_part2 + "\n" +
+ System.out.println("Expected: " + expectedErrorMessage_part1 + "<id>" +
+ expectedErrorMessage_part2 + "<id>" +
+ expectedErrorMessage_part3 + "\n" +
"but got: " + errorMsg);
throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg);
}
--- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,7 +38,7 @@
// Break expected error messages into 3 parts since the loader name includes its identity
// hash which is unique and can't be compared against.
static String expectedErrorMessage1_part1 = "loader constraint violation for class test.Task: when " +
- "selecting overriding method test.Task.m()Ltest/Foo; the " +
+ "selecting overriding method 'test.Foo test.Task.m()' the " +
"class loader PreemptingClassLoader @";
static String expectedErrorMessage1_part2 = " of the selected method's type test.Task, and the class " +
"loader 'app' for its super type test.J have different Class objects " +
@@ -47,7 +47,7 @@
static String expectedErrorMessage1_part3 = ", parent loader 'app'; test.J is in unnamed module of loader 'app')";
static String expectedErrorMessage2_part1 = "loader constraint violation for class test.Task: when " +
- "selecting overriding method test.Task.m()Ltest/Foo; the " +
+ "selecting overriding method 'test.Foo test.Task.m()' the " +
"class loader 'VtableLdrCnstrnt_Test_Loader' @";
static String expectedErrorMessage2_part2 = " of the selected method's type test.Task, and the class " +
"loader 'app' for its super type test.J have different Class objects " +
--- a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java Wed Apr 10 10:46:53 2019 +0530
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8133747 8218458
* @key nmt
* @summary Running with NMT detail should produce expected stack traces.
* @library /test/lib
@@ -36,26 +37,50 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+/**
+ * We are checking for details that should be seen with NMT detail enabled.
+ * In particular the stack traces from os::malloc call sites should have 4
+ * (based on NMT detail stack depth setting) 'interesting' frames and skip
+ * the higher-level allocation frames and frames specific to the NMT logic.
+ * The actual stack trace is affected by the native compiler's inlining ability
+ * and the type of build, so we need to check for a number of possible stacks.
+ * This information does not change often enough that we are concerned about the
+ * stability of this test - rather we prefer to detect changes in compiler behaviour
+ * through this test and update it accordingly.
+ */
public class CheckForProperDetailStackTrace {
+
/* The stack trace we look for by default. Note that :: has been replaced by .*
- to make sure it maches even if the symbol is not unmangled. */
- public static String stackTraceDefault =
+ to make sure it matches even if the symbol is not unmangled.
+ */
+ private static String stackTraceDefault =
".*Hashtable.*allocate_new_entry.*\n" +
".*ModuleEntryTable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry.*\n" +
".*Modules.*define_module.*\n";
- /* The stack trace we look for on Solaris and Windows slowdebug builds. For some
- reason ALWAYSINLINE for AllocateHeap is ignored, so it appears in the stack strace. */
- public static String stackTraceAllocateHeap =
+ /* Alternate stacktrace that we check if the default fails, because
+ new_entry may be inlined.
+ */
+ private static String stackTraceAlternate =
+ ".*Hashtable.*allocate_new_entry.*\n" +
+ ".*ModuleEntryTable.*locked_create_entry.*\n" +
+ ".*Modules.*define_module.*\n" +
+ ".*JVM_DefineModule.*\n";
+
+ /* The stack trace we look for on AIX, Solaris and Windows slowdebug builds.
+ ALWAYSINLINE is only a hint and is ignored for AllocateHeap on the
+ aforementioned platforms. When that happens allocate_new_entry is
+ inlined instead.
+ */
+ private static String stackTraceAllocateHeap =
".*AllocateHeap.*\n" +
".*ModuleEntryTable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry.*\n" +
".*Modules.*define_module.*\n";
/* A symbol that should always be present in NMT detail output. */
- private static String expectedSymbol =
- "locked_create_entry";
+ private static String expectedSymbol = "locked_create_entry";
public static void main(String args[]) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
@@ -67,23 +92,22 @@
output.shouldHaveExitValue(0);
- // We should never see either of these frames because they are supposed to be skipped. */
+ // We should never see either of these frames because they are supposed to be skipped.
output.shouldNotContain("NativeCallStack::NativeCallStack");
output.shouldNotContain("os::get_native_stack");
// AllocateHeap shouldn't be in the output because it is supposed to always be inlined.
// We check for that here, but allow it for Aix, Solaris and Windows slowdebug builds
// because the compiler ends up not inlining AllocateHeap.
- Boolean okToHaveAllocateHeap =
- Platform.isSlowDebugBuild() &&
- (Platform.isAix() || Platform.isSolaris() || Platform.isWindows());
+ Boolean okToHaveAllocateHeap = Platform.isSlowDebugBuild() &&
+ (Platform.isAix() || Platform.isSolaris() || Platform.isWindows());
if (!okToHaveAllocateHeap) {
output.shouldNotContain("AllocateHeap");
}
// See if we have any stack trace symbols in the output
- boolean hasSymbols =
- output.getStdout().contains(expectedSymbol) || output.getStderr().contains(expectedSymbol);
+ boolean hasSymbols = output.getStdout().contains(expectedSymbol) ||
+ output.getStderr().contains(expectedSymbol);
if (!hasSymbols) {
// It's ok for ARM not to have symbols, because it does not support NMT detail
// when targeting thumb2. It's also ok for Windows not to have symbols, because
@@ -92,21 +116,37 @@
return; // we are done
}
output.reportDiagnosticSummary();
- throw new RuntimeException("Expected symbol missing missing from output: " + expectedSymbol);
+ throw new RuntimeException("Expected symbol missing from output: " + expectedSymbol);
}
- /* Make sure the expected NMT detail stack trace is found. */
- String expectedStackTrace =
- (okToHaveAllocateHeap ? stackTraceAllocateHeap : stackTraceDefault);
- if (!stackTraceMatches(expectedStackTrace, output)) {
- output.reportDiagnosticSummary();
- throw new RuntimeException("Expected stack trace missing missing from output: " + expectedStackTrace);
+ // Make sure the expected NMT detail stack trace is found
+ System.out.println("Looking for a stack matching:");
+ if (okToHaveAllocateHeap) {
+ System.out.print(stackTraceAllocateHeap);
+ if (stackTraceMatches(stackTraceAllocateHeap, output)) {
+ return;
+ }
+ } else {
+ System.out.print(stackTraceDefault);
+ if (!stackTraceMatches(stackTraceDefault, output)) {
+ System.out.println("Looking for alternate stack matching:");
+ System.out.print(stackTraceAlternate);
+ if (stackTraceMatches(stackTraceAlternate, output)) {
+ return;
+ }
+ } else {
+ return;
+ }
}
+ // Failed to match so dump all the output
+ output.reportDiagnosticSummary();
+ throw new RuntimeException("Expected stack trace missing from output");
}
public static boolean stackTraceMatches(String stackTrace, OutputAnalyzer output) {
- Matcher stdoutMatcher = Pattern.compile(stackTrace, Pattern.MULTILINE).matcher(output.getStdout());
- Matcher stderrMatcher = Pattern.compile(stackTrace, Pattern.MULTILINE).matcher(output.getStderr());
+ Pattern p = Pattern.compile(stackTrace, Pattern.MULTILINE);
+ Matcher stdoutMatcher = p.matcher(output.getStdout());
+ Matcher stderrMatcher = p.matcher(output.getStderr());
return (stdoutMatcher.find() || stderrMatcher.find());
}
}
--- a/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java Wed Apr 10 10:46:53 2019 +0530
@@ -671,7 +671,7 @@
static void test_NoHostInvoke() throws Throwable {
System.out.println("Testing for missing nest-host attribute");
String msg = "class TestNestmateMembership$Caller tried to access " +
- "private method TestNestmateMembership$TargetNoHost.m()V";
+ "private method 'void TestNestmateMembership$TargetNoHost.m()'";
try {
Caller.invokeTargetNoHost();
throw new Error("Missing IllegalAccessError: " + msg);
@@ -698,7 +698,7 @@
}
msg = "class TestNestmateMembership$CallerNoHost tried to access " +
- "private method TestNestmateMembership$Target.m()V";
+ "private method 'void TestNestmateMembership$Target.m()'";
try {
CallerNoHost.invokeTarget();
throw new Error("Missing IllegalAccessError: " + msg);
@@ -707,7 +707,7 @@
check_expected(expected, msg);
}
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
- "method TestNestmateMembership$TargetNoHost.m()V";
+ "method 'void TestNestmateMembership$TargetNoHost.m()'";
try {
CallerNoHost.invokeTargetNoHost();
throw new Error("Missing IllegalAccessError: " + msg);
@@ -950,7 +950,7 @@
static void test_NoHostConstruct() throws Throwable {
System.out.println("Testing for missing nest-host attribute");
String msg = "class TestNestmateMembership$Caller tried to access private " +
- "method TestNestmateMembership$TargetNoHost.<init>()V";
+ "method 'void TestNestmateMembership$TargetNoHost.<init>()'";
try {
Caller.newTargetNoHost();
throw new Error("Missing IncompatibleClassChangeError: " + msg);
@@ -977,7 +977,7 @@
}
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
- "method TestNestmateMembership$Target.<init>()V";
+ "method 'void TestNestmateMembership$Target.<init>()'";
try {
CallerNoHost.newTarget();
throw new Error("Missing IncompatibleClassChangeError: " + msg);
@@ -986,7 +986,7 @@
check_expected(expected, msg);
}
msg = "class TestNestmateMembership$CallerNoHost tried to access private " +
- "method TestNestmateMembership$TargetNoHost.<init>()V";
+ "method 'void TestNestmateMembership$TargetNoHost.<init>()'";
try {
CallerNoHost.newTargetNoHost();
throw new Error("Missing IncompatibleClassChangeError: " + msg);
--- a/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestConstructorHierarchy.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestConstructorHierarchy.java Wed Apr 10 10:46:53 2019 +0530
@@ -51,7 +51,7 @@
throw new Error("Unexpected construction of ExternalSuper");
}
catch (IllegalAccessError iae) {
- if (iae.getMessage().contains("class TestConstructorHierarchy tried to access private method ExternalSuper.<init>()V")) {
+ if (iae.getMessage().contains("class TestConstructorHierarchy tried to access private method 'void ExternalSuper.<init>()'")) {
System.out.println("Got expected exception constructing ExternalSuper: " + iae);
}
else throw new Error("Unexpected IllegalAccessError: " + iae);
@@ -61,7 +61,7 @@
throw new Error("Unexpected construction of NestedA and supers");
}
catch (IllegalAccessError iae) {
- if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access private method ExternalSuper.<init>()V")) {
+ if (iae.getMessage().contains("class TestConstructorHierarchy$NestedA tried to access private method 'void ExternalSuper.<init>()'")) {
System.out.println("Got expected exception constructing NestedA: " + iae);
}
else throw new Error("Unexpected IllegalAccessError: " + iae);
@@ -71,7 +71,7 @@
throw new Error("Unexpected construction of ExternalSub");
}
catch (IllegalAccessError iae) {
- if (iae.getMessage().contains("class ExternalSub tried to access private method TestConstructorHierarchy$NestedA.<init>()V")) {
+ if (iae.getMessage().contains("class ExternalSub tried to access private method 'void TestConstructorHierarchy$NestedA.<init>()'")) {
System.out.println("Got expected exception constructing ExternalSub: " + iae);
}
else throw new Error("Unexpected IllegalAccessError: " + iae);
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -47,6 +47,15 @@
public void process(String args[]) throws Throwable {
if (args.length == 0) {
+ // Dump the shared archive in case it was not generated during the JDK build.
+ // Put the archive at separate file to avoid clashes with concurrent tests.
+ CDSOptions opts = new CDSOptions()
+ .setXShareMode("dump")
+ .setArchiveName(ReplaceCriticalClasses.class.getName() + ".jsa")
+ .setUseVersion(false)
+ .addSuffix("-showversion");
+ CDSTestUtils.run(opts).assertNormalExit("");
+
launchChildProcesses(getTests());
} else if (args.length == 3 && args[0].equals("child")) {
Class klass = Class.forName(args[2].replace("/", "."));
@@ -152,7 +161,7 @@
CDSOptions opts = (new CDSOptions())
.setXShareMode("auto")
- .setUseSystemArchive(true)
+ .setArchiveName(ReplaceCriticalClasses.class.getName() + ".jsa")
.setUseVersion(false)
.addSuffix("-showversion",
"-Xlog:cds",
--- a/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -42,8 +42,6 @@
public class DockerBasicTest {
private static final String imageNameAndTag = Common.imageName("basic");
- // Diganostics: set to false to examine image after the test
- private static final boolean removeImageAfterTest = true;
public static void main(String[] args) throws Exception {
if (!DockerTestUtils.canTestDocker()) {
@@ -56,8 +54,9 @@
testJavaVersion();
testHelloDocker();
} finally {
- if (removeImageAfterTest)
+ if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
DockerTestUtils.removeDockerImage(imageNameAndTag);
+ }
}
}
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -99,11 +99,11 @@
}
private static String expectedErrorMessageAME1_1 =
- "Missing implementation of resolved method abstract " +
- "anAbstractMethod()Ljava/lang/String; of abstract class AME1_B.";
+ "Missing implementation of resolved method 'abstract " +
+ "java.lang.String anAbstractMethod()' of abstract class AME1_B.";
private static String expectedErrorMessageAME1_2 =
"Receiver class AME1_E does not define or inherit an implementation of the " +
- "resolved method abstract aFunctionOfMyInterface()Ljava/lang/String; of " +
+ "resolved method 'abstract java.lang.String aFunctionOfMyInterface()' of " +
"interface AME1_C.";
public static void test_ame1() {
@@ -158,11 +158,11 @@
}
private static String expectedErrorMessageAME2_Interpreted =
- "Missing implementation of resolved method abstract " +
- "aFunctionOfMyInterface()V of interface AME2_A.";
+ "Missing implementation of resolved method 'abstract " +
+ "void aFunctionOfMyInterface()' of interface AME2_A.";
private static String expectedErrorMessageAME2_Compiled =
"Receiver class AME2_C does not define or inherit an implementation of the resolved method " +
- "abstract aFunctionOfMyInterface()V of interface AME2_A.";
+ "'abstract void aFunctionOfMyInterface()' of interface AME2_A.";
public AbstractMethodErrorTest() throws InstantiationException, IllegalAccessException {
try {
@@ -228,7 +228,7 @@
private static String expectedErrorMessageAME3_1 =
"Receiver class AME3_C does not define or inherit an implementation of the resolved method " +
- "ma()V of class AME3_A. Selected method is abstract AME3_B.ma()V.";
+ "'void ma()' of class AME3_A. Selected method is 'abstract void AME3_B.ma()'.";
// Testing abstract class that extends a class that has an implementation.
// Loop so that method gets eventually compiled/osred.
@@ -259,7 +259,7 @@
private static String expectedErrorMessageAME3_2 =
"Receiver class AME3_C does not define or inherit an implementation of " +
- "the resolved method abstract ma()V of abstract class AME3_B.";
+ "the resolved method 'abstract void ma()' of abstract class AME3_B.";
// Testing abstract class that extends a class that has an implementation.
// Loop so that method gets eventually compiled/osred.
@@ -289,7 +289,7 @@
}
private static String expectedErrorMessageAME4 =
- "Missing implementation of resolved method abstract ma()V of " +
+ "Missing implementation of resolved method 'abstract void ma()' of " +
"abstract class AME4_B.";
// Testing abstract class that extends a class that has an implementation.
@@ -336,7 +336,7 @@
}
private static String expectedErrorMessageAME5_VtableStub =
- "Receiver class AME5_B does not define or inherit an implementation of the resolved method abstract mc()V " +
+ "Receiver class AME5_B does not define or inherit an implementation of the resolved method 'abstract void mc()' " +
"of abstract class AME5_A.";
// AbstractMethodErrors detected in vtable stubs.
@@ -409,7 +409,7 @@
private static String expectedErrorMessageAME6_ItableStub =
"Receiver class AME6_B does not define or inherit an implementation of the resolved" +
- " method abstract mc()V of interface AME6_A.";
+ " method 'abstract void mc()' of interface AME6_A.";
// -------------------------------------------------------------------------
// AbstractMethodErrors detected in itable stubs.
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IllegalAccessErrorTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IllegalAccessErrorTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -141,7 +141,7 @@
private static void iae4_m() { }
private static String expectedErrorMessage4 =
- "class test.Runner4 tried to access private method test.IllegalAccessErrorTest.iae4_m()V " +
+ "class test.Runner4 tried to access private method 'void test.IllegalAccessErrorTest.iae4_m()' " +
"(test.Runner4 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')";
// Test according to java/lang/invoke/DefineClassTest.java
@@ -264,7 +264,7 @@
}
private static String expectedErrorMessage7_1 =
- "class test.IAE78_B tried to access method test.IAE78_A.<init>()V " +
+ "class test.IAE78_B tried to access method 'void test.IAE78_A.<init>()' " +
"(test.IAE78_B is in unnamed module of loader 'test7_method_CL' @";
private static String expectedErrorMessage7_2 =
"; test.IAE78_A is in unnamed module of loader 'app')";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TeMe3_C.jasm Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 SAP SE. 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.
+ */
+
+package test;
+
+/* Method ma() is missing in this implementation to cause error. */
+
+class TeMe3_C extends TeMe3_B {
+ public Method "<init>":"()V"
+ stack 1 locals 1
+ {
+ aload_0;
+ invokespecial Method TeMe3_B."<init>":()V;
+ return;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 SAP SE. 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
+ * @summary Check that methods are printed properly.
+ * @compile -encoding UTF-8 TestPrintingMethods.java
+ * @compile TeMe3_C.jasm
+ * @run main/othervm -Xbootclasspath/a:. test.TestPrintingMethods
+ */
+
+package test;
+
+public class TestPrintingMethods {
+
+ private static String expectedErrorMessage_VV = "void test.TeMe3_B.ma()";
+ private static String expectedErrorMessage_integral = "double[][] test.TeMe3_B.ma(int, boolean, byte[][], float)";
+ private static String expectedErrorMessage_classes = "test.TeMe3_B[][] test.TeMe3_B.ma(java.lang.Object[][][])";
+ private static String expectedErrorMessage_unicode = "java.lang.Object test.TeMe3_B.m\u20ac\u00a3a(java.lang.Object)";
+
+ static void checkMsg(Error e, String expected) throws Exception {
+ String errorMsg = e.getMessage();
+ if (errorMsg == null) {
+ throw new RuntimeException("Caught AbstractMethodError with empty message.");
+ } else if (errorMsg.contains(expected)) {
+ System.out.println("Passed with message: " + errorMsg);
+ } else {
+ System.out.println("Expected method to be printed as \"" + expected + "\"\n" +
+ "in exception message: " + errorMsg);
+ throw new RuntimeException("Method not printed as expected.");
+ }
+ }
+
+ // Call various missing methods to check that the exception
+ // message contains the proper string for the method name and
+ // signature. We expect Java-like printing of parameters etc.
+ static void test() throws Exception {
+ TeMe3_A c = new TeMe3_C();
+
+ try {
+ c.ma();
+ throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+ } catch (AbstractMethodError e) {
+ checkMsg(e, expectedErrorMessage_VV);
+ }
+
+ try {
+ c.ma(2, true, new byte[2][3], 23.4f);
+ throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+ } catch (AbstractMethodError e) {
+ checkMsg(e, expectedErrorMessage_integral);
+ }
+
+ try {
+ c.ma(new java.lang.Object[1][2][3]);
+ throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+ } catch (AbstractMethodError e) {
+ checkMsg(e, expectedErrorMessage_classes);
+ }
+
+ try {
+ c.m\u20ac\u00a3a(new java.lang.Object());
+ throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+ } catch (AbstractMethodError e) {
+ checkMsg(e, expectedErrorMessage_unicode);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ test();
+ }
+}
+
+// Helper classes to test abstract method error.
+//
+// Errorneous versions of these classes are implemented in java
+// assembler.
+
+
+// -----------------------------------------------------------------------
+// Test AbstractMethod error shadowing existing implementation.
+//
+// Class hierachy:
+//
+// A // A class implementing m() and similar.
+// |
+// B // An abstract class defining m() abstract.
+// |
+// C // An errorneous class lacking an implementation of m().
+//
+class TeMe3_A {
+ public void ma() {
+ System.out.print("A.ma()");
+ }
+ public double[][] ma(int i, boolean z, byte[][] b, float f) {
+ return null;
+ }
+ public TeMe3_B[][] ma(java.lang.Object[][][] o) {
+ return null;
+ }
+ public java.lang.Object m\u20ac\u00a3a(java.lang.Object s) {
+ return null;
+ }
+}
+
+abstract class TeMe3_B extends TeMe3_A {
+ public abstract void ma();
+ public abstract double[][] ma(int i, boolean z, byte[][] b, float f);
+ public abstract TeMe3_B[][] ma(java.lang.Object[][][] o);
+ public abstract java.lang.Object m\u20ac\u00a3a(java.lang.Object s);
+}
+
+// An errorneous version of this class is implemented in java
+// assembler.
+class TeMe3_C extends TeMe3_B {
+ // These methods are missing in the .jasm implementation.
+ public void ma() {
+ System.out.print("C.ma()");
+ }
+ public double[][] ma(int i, boolean z, byte[][] b, float f) {
+ return new double[2][2];
+ }
+ public TeMe3_B[][] ma(java.lang.Object[][][] o) {
+ return new TeMe3_C[3][3];
+ }
+ public java.lang.Object m\u20ac\u00a3a(java.lang.Object s) {
+ return new java.lang.Object();
+ }
+}
+
--- a/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -103,7 +103,7 @@
// java.lang.IllegalAccessError:
// tried to access private method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
// myloaders.MySameClassLoader @<id>; p1.c1 is in module m1x of loader myloaders.MySameClassLoader @<id>)
- if (!message.contains("class p1.c1 tried to access private method p2.c2.method2()V " +
+ if (!message.contains("class p1.c1 tried to access private method 'void p2.c2.method2()' " +
"(p1.c1 is in module m1x of loader myloaders.MySameClassLoader @") ||
!message.contains("; p2.c2 is in module m2x of loader myloaders.MySameClassLoader @")) {
throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
--- a/test/hotspot/jtreg/serviceability/dcmd/framework/HelpTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/HelpTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -75,6 +75,6 @@
run(new JMXExecutor());
}
- private static class Process extends TestJavaProcess {
+ private static class Process extends process.TestJavaProcess {
}
}
--- a/test/hotspot/jtreg/serviceability/dcmd/framework/InvalidCommandTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/InvalidCommandTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -73,6 +73,6 @@
run(new JMXExecutor());
}
- private static class Process extends TestJavaProcess {
+ private static class Process extends process.TestJavaProcess {
}
}
--- a/test/hotspot/jtreg/serviceability/dcmd/framework/TestJavaProcess.java Wed Apr 10 10:32:43 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-import nsk.share.jpda.*;
-import nsk.share.jdi.*;
-
-/**
- * A simple process that connects to a pipe and waits for command "quit" to
- * be received.
- *
- * Usage: java TestJavaProcess -pipe.port <PIPE_PORT_NUMBER>
- */
-
-public class TestJavaProcess {
-
- static final int PASSED = 0;
- static final int FAILED = 2;
-
- public static void main(String argv[]) {
-
- log("Test Java process started!");
-
- ArgumentHandler argHandler = new ArgumentHandler(argv);
- IOPipe pipe = argHandler.createDebugeeIOPipe();
- pipe.println("ready");
- log("Waiting for the quit command from the test ...");
- String cmd = pipe.readln();
- int exitCode = PASSED;
- if (cmd.equals("quit")) {
- log("'quit' received");
- } else {
- log("Invalid command received " + cmd);
- exitCode = FAILED;
- }
- System.exit(exitCode);
- }
-
- private static void log(String message) {
- System.out.println(message);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessJarLauncher.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import jdk.test.lib.util.JarUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+/**
+ * Launches a new Java process using -jar Java option.
+ */
+
+public class TestProcessJarLauncher extends TestProcessLauncher {
+
+ private static final String JAR_FILE = "testprocess.jar";
+
+
+ public TestProcessJarLauncher(String className) {
+ super(className);
+ }
+
+ protected String prepareLaunch(String javaExec, String pipePort) {
+ try {
+ File jarFile = prepareJar();
+ return javaExec + " -jar " + jarFile.getAbsolutePath() + " -pipe.port=" + pipePort;
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to prepare a jar file", e);
+ }
+ }
+
+ private File prepareJar() throws IOException {
+ Path jarFile = USER_DIR.resolve(JAR_FILE);
+ Manifest manifest = createManifest();
+ Path testClass = TEST_CLASSES_DIR.resolve(className + ".class");
+ JarUtils.createJarFile(jarFile, manifest, TEST_CLASSES_DIR, Paths.get("."));
+ return jarFile.toFile();
+ }
+
+ private Manifest createManifest() {
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, className);
+ return manifest;
+ }
+
+ public String getJarFile() {
+ return JAR_FILE;
+ }
+}
--- a/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java Wed Apr 10 10:46:53 2019 +0530
@@ -26,6 +26,9 @@
import nsk.share.jpda.*;
import nsk.share.jdi.*;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
/**
* Launches a new Java process that uses a communication pipe to interact
* with the test.
@@ -33,7 +36,10 @@
public class TestProcessLauncher {
- private final String className;
+ protected static final Path USER_DIR = FileSystems.getDefault().getPath(System.getProperty("user.dir", "."));
+ protected static final Path TEST_CLASSES_DIR = FileSystems.getDefault().getPath(System.getProperty("test.classes"));
+
+ protected final String className;
private final ArgumentHandler argHandler;
private IOPipe pipe;
@@ -55,7 +61,7 @@
Binder binder = new Binder(argHandler, log);
binder.prepareForPipeConnection(argHandler);
- String cmd = java + " " + className + " -pipe.port=" + argHandler.getPipePort();
+ String cmd = prepareLaunch(java, argHandler.getPipePort());
Debugee debuggee = binder.startLocalDebugee(cmd);
debuggee.redirectOutput(log);
@@ -75,4 +81,8 @@
}
}
+ protected String prepareLaunch(String javaExec, String pipePort) {
+ return javaExec + " " + className + " -pipe.port=" + pipePort;
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessModuleLauncher.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import jdk.internal.module.ModuleInfoWriter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.module.ModuleDescriptor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Stream;
+
+/*
+ * Launches a new Java process with a main class packed inside a module.
+ */
+
+public class TestProcessModuleLauncher extends TestProcessLauncher {
+
+ private static final Path TEST_MODULES = USER_DIR.resolve("testmodules");
+ private static final String MODULE_NAME = "module1";
+
+ public TestProcessModuleLauncher(String className) {
+ super(className);
+ }
+
+ protected String prepareLaunch(String javaExec, String pipePort) {
+ try {
+ prepareModule();
+ return javaExec + " --module-path " + TEST_MODULES.toFile().getAbsolutePath() +
+ " -m " + MODULE_NAME + "/" + className + " -pipe.port=" + pipePort;
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to prepare a jar file", e);
+ }
+ }
+
+ private void prepareModule() throws IOException {
+ TEST_MODULES.toFile().mkdirs();
+ Path moduleJar = TEST_MODULES.resolve("mod1.jar");
+ ModuleDescriptor md = createModuleDescriptor();
+ createModuleJarFile(moduleJar, md, TEST_CLASSES_DIR, Paths.get("."));
+ }
+
+ private ModuleDescriptor createModuleDescriptor() {
+ ModuleDescriptor.Builder builder
+ = ModuleDescriptor.newModule(MODULE_NAME).requires("java.base");
+ return builder.build();
+ }
+
+ private static void createModuleJarFile(Path jarfile, ModuleDescriptor md, Path dir, Path... files)
+ throws IOException {
+
+ Path parent = jarfile.getParent();
+ if (parent != null) {
+ Files.createDirectories(parent);
+ }
+
+ List<Path> entries = findAllRegularFiles(dir, files);
+
+ try (OutputStream out = Files.newOutputStream(jarfile);
+ JarOutputStream jos = new JarOutputStream(out)) {
+ if (md != null) {
+ JarEntry je = new JarEntry("module-info.class");
+ jos.putNextEntry(je);
+ ModuleInfoWriter.write(md, jos);
+ jos.closeEntry();
+ }
+
+ for (Path entry : entries) {
+ String name = toJarEntryName(entry);
+ jos.putNextEntry(new JarEntry(name));
+ Files.copy(dir.resolve(entry), jos);
+ jos.closeEntry();
+ }
+ }
+ }
+
+ private static String toJarEntryName(Path file) {
+ Path normalized = file.normalize();
+ return normalized.subpath(0, normalized.getNameCount())
+ .toString()
+ .replace(File.separatorChar, '/');
+ }
+
+ private static List<Path> findAllRegularFiles(Path dir, Path[] files) throws IOException {
+ List<Path> entries = new ArrayList<>();
+ for (Path file : files) {
+ try (Stream<Path> stream = Files.find(dir.resolve(file), Integer.MAX_VALUE,
+ (p, attrs) -> attrs.isRegularFile() && !p.getParent().equals(dir.resolve(".")))) {
+ stream.map(dir::relativize)
+ .forEach(entries::add);
+ }
+ }
+ return entries;
+ }
+
+ public String getModuleName() {
+ return MODULE_NAME;
+ }
+}
--- a/test/hotspot/jtreg/serviceability/dcmd/framework/VMVersionTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/VMVersionTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -33,17 +33,21 @@
/*
* @test
+ * @bug 8221730
* @summary Test of diagnostic command VM.version (tests all DCMD executors)
* @library /test/lib
* /vmTestbase
- * @build TestJavaProcess
* @modules java.base/jdk.internal.misc
+ * java.base/jdk.internal.module
* java.compiler
* java.management
* jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData VMVersionTest
*/
public class VMVersionTest {
+
+ private static final String TEST_PROCESS_CLASS_NAME = process.TestJavaProcess.class.getName();
+
public void run(CommandExecutor executor) {
OutputAnalyzer output = executor.execute("VM.version");
output.shouldMatch(".*(?:HotSpot|OpenJDK).*VM.*");
@@ -56,10 +60,34 @@
@Test
public void mainClass() {
- TestProcessLauncher t = new TestProcessLauncher(Process.class.getName());
+ TestProcessLauncher t = new TestProcessLauncher(TEST_PROCESS_CLASS_NAME);
+ try {
+ t.launch();
+ run(new MainClassJcmdExecutor(TEST_PROCESS_CLASS_NAME));
+ } finally {
+ t.quit();
+ }
+ }
+
+ @Test
+ public void mainClassForJar() {
+ TestProcessJarLauncher t = new TestProcessJarLauncher(TEST_PROCESS_CLASS_NAME);
try {
t.launch();
- run(new MainClassJcmdExecutor(Process.class.getName()));
+ String jarFile = t.getJarFile();
+ run(new MainClassJcmdExecutor(jarFile));
+ } finally {
+ t.quit();
+ }
+ }
+
+ @Test
+ public void mainClassForModule() {
+ TestProcessModuleLauncher t = new TestProcessModuleLauncher(TEST_PROCESS_CLASS_NAME);
+ try {
+ t.launch();
+ String moduleName = t.getModuleName();
+ run(new MainClassJcmdExecutor(moduleName));
} finally {
t.quit();
}
@@ -75,5 +103,4 @@
run(new JMXExecutor());
}
- private static class Process extends TestJavaProcess{}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/dcmd/framework/process/TestJavaProcess.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package process;
+
+import nsk.share.jdi.ArgumentHandler;
+import nsk.share.jpda.IOPipe;
+
+/**
+ * A simple process that connects to a pipe and waits for command "quit" to
+ * be received.
+ *
+ * Usage: java TestJavaProcess -pipe.port <PIPE_PORT_NUMBER>
+ */
+
+public class TestJavaProcess {
+
+ static final int PASSED = 0;
+ static final int FAILED = 2;
+
+ public static void main(String argv[]) {
+
+ log("Test Java process started!");
+
+ ArgumentHandler argHandler = new ArgumentHandler(argv);
+ IOPipe pipe = argHandler.createDebugeeIOPipe();
+ pipe.println("ready");
+ log("Waiting for the quit command from the test ...");
+ String cmd = pipe.readln();
+ int exitCode = PASSED;
+ if (cmd.equals("quit")) {
+ log("'quit' received");
+ } else {
+ log("Invalid command received " + cmd);
+ exitCode = FAILED;
+ }
+ System.exit(exitCode);
+ }
+
+ private static void log(String message) {
+ System.out.println(message);
+ }
+}
--- a/test/jdk/ProblemList-graal.txt Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/ProblemList-graal.txt Wed Apr 10 10:46:53 2019 +0530
@@ -29,6 +29,8 @@
java/lang/Class/getDeclaredField/ClassDeclaredFieldsTest.java 8185139 generic-all
java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java 8185139 generic-all
+java/lang/ProcessBuilder/Basic.java#id0 8185139 generic-all
+java/lang/ProcessBuilder/Basic.java#id1 8185139 generic-all
java/lang/ProcessBuilder/SecurityManagerClinit.java 8185139 generic-all
java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java 8185139 generic-all
java/lang/StackWalker/CallerSensitiveMethod/Main.java 8185139 generic-all
@@ -68,6 +70,7 @@
java/lang/ref/OOMEInReferenceHandler.java 8196611 generic-all
java/lang/Runtime/exec/LotsOfOutput.java 8196611 generic-all
java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java 8196611 generic-all
+vm/gc/InfiniteList.java 8196611 generic-all
# tests require pop_frame and force_early_return capabilities
com/sun/jdi/RedefineTTYLineNumber.java 8195635 generic-all
--- a/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -30,7 +30,7 @@
/*
* @test
- * @bug 8077559
+ * @bug 8077559 8221430
* @summary Tests Compact String. This test is testing StringBuffer
* behavior related to Compact String.
* @run testng/othervm -XX:+CompactStrings CompactStringBuffer
@@ -440,6 +440,12 @@
"abcdefgh1.23456");
check(new StringBuffer().append(bmp).append(1.23456).toString(),
"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e081.23456");
+
+ ////////////////////////////////////////////////////////////////////
+ check(new StringBuffer((CharSequence)new StringBuffer(ascii)).toString(),
+ ascii);
+ check(new StringBuffer((CharSequence)new StringBuffer(asciiMixed)).toString(),
+ asciiMixed);
}
private void checkGetChars(StringBuffer sb, int srcBegin, int srcEnd,
--- a/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -635,7 +635,7 @@
public void testGetter(int testMode) throws Throwable {
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
- for (Object[] c : HasFields.CASES) {
+ for (Object[] c : HasFields.testCasesFor(testMode)) {
boolean positive = (c[1] != Error.class);
testGetter(positive, lookup, c[0], c[1], testMode);
if (positive)
@@ -665,7 +665,6 @@
boolean testNPE = ((testMode0 & TEST_NPE) != 0);
int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE);
boolean positive = positive0 && !testNPE;
- boolean isFinal;
boolean isStatic;
Class<?> fclass;
String fname;
@@ -673,14 +672,12 @@
Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
if (f != null) {
isStatic = Modifier.isStatic(f.getModifiers());
- isFinal = Modifier.isFinal(f.getModifiers());
fclass = f.getDeclaringClass();
fname = f.getName();
ftype = f.getType();
} else {
Object[] scnt = (Object[]) fieldRef;
isStatic = (Boolean) scnt[0];
- isFinal = false;
fclass = (Class<?>) scnt[1];
fname = (String) scnt[2];
ftype = (Class<?>) scnt[3];
@@ -724,19 +721,21 @@
? NoSuchFieldException.class
: IllegalAccessException.class,
noAccess);
- if (((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic)) return; // Final static field setter test failed as intended.
if (verbosity >= 5) ex.printStackTrace(System.out);
}
if (verbosity >= 3)
- System.out.println((((testMode0 & TEST_UNREFLECT) != 0)?"unreflect":"find")
- +(((testMode0 & TEST_FIND_STATIC) != 0)?"Static":"")
- +(isGetter?"Getter":"Setter")
- +" "+fclass.getName()+"."+fname+"/"+ftype
- +" => "+mh
- +(noAccess == null ? "" : " !! "+noAccess));
+ System.out.format("%s%s %s.%s/%s => %s %s%n",
+ (testMode0 & TEST_UNREFLECT) != 0
+ ? "unreflect"
+ : "find" + ((testMode0 & TEST_FIND_STATIC) != 0 ? "Static" : ""),
+ (isGetter ? "Getter" : "Setter"),
+ fclass.getName(), fname, ftype, mh,
+ (noAccess == null ? "" : " !! "+noAccess));
+ // negative test case and expected noAccess, then done.
+ if (!positive && noAccess != null) return;
+ // positive test case but found noAccess, then error
if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess);
assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null);
- assertFalse("Setter methods should throw an exception if passed a final static field.", ((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic));
if (!positive && !testNPE) return; // negative access test failed as expected
assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
assertSame(mh.type(), expType);
@@ -762,6 +761,9 @@
assertEquals(f.get(fields), value); // clean to start with
}
Throwable caughtEx = null;
+ // non-final field and setAccessible(true) on instance field will have write access
+ boolean writeAccess = !Modifier.isFinal(f.getModifiers()) ||
+ (!Modifier.isStatic(f.getModifiers()) && f.isAccessible());
if (isGetter) {
Object expValue = value;
for (int i = 0; i <= 1; i++) {
@@ -785,7 +787,7 @@
}
}
assertEquals(sawValue, expValue);
- if (f != null && f.getDeclaringClass() == HasFields.class && !isFinal) {
+ if (f != null && f.getDeclaringClass() == HasFields.class && writeAccess) {
Object random = randomArg(ftype);
f.set(fields, random);
expValue = random;
@@ -819,8 +821,8 @@
}
}
}
- if ((f != null) && (f.getDeclaringClass() == HasFields.class) && !isFinal) {
- f.set(fields, value); // put it back if we changed it.
+ if (f != null && f.getDeclaringClass() == HasFields.class && writeAccess) {
+ f.set(fields, value); // put it back if it has write access
}
if (testNPE) {
if (caughtEx == null || !(caughtEx instanceof NullPointerException))
@@ -868,7 +870,8 @@
public void testSetter(int testMode) throws Throwable {
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
- for (Object[] c : HasFields.CASES) {
+ startTest("testSetter");
+ for (Object[] c : HasFields.testCasesFor(testMode|TEST_SETTER)) {
boolean positive = (c[1] != Error.class);
testSetter(positive, lookup, c[0], c[1], testMode);
if (positive)
--- a/test/jdk/java/lang/invoke/MethodHandlesTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/lang/invoke/MethodHandlesTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -38,6 +38,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Stream;
import static org.junit.Assert.*;
@@ -561,25 +562,37 @@
static long sJ = 1+'J';
static float sF = 1+'F';
static double sD = 1+'D';
+
+ // final fields
+ final boolean fiZ = false;
+ final byte fiB = 2+(byte)'B';
+ final short fiS = 2+(short)'S';
+ final char fiC = 2+'C';
+ final int fiI = 2+'I';
+ final long fiJ = 2+'J';
+ final float fiF = 2+'F';
+ final double fiD = 2+'D';
final static boolean fsZ = false;
- final static byte fsB = 2+(byte)'B';
- final static short fsS = 2+(short)'S';
- final static char fsC = 2+'C';
- final static int fsI = 2+'I';
- final static long fsJ = 2+'J';
- final static float fsF = 2+'F';
- final static double fsD = 2+'D';
+ final static byte fsB = 3+(byte)'B';
+ final static short fsS = 3+(short)'S';
+ final static char fsC = 3+'C';
+ final static int fsI = 3+'I';
+ final static long fsJ = 3+'J';
+ final static float fsF = 3+'F';
+ final static double fsD = 3+'D';
Object iL = 'L';
- String iR = "R";
- static Object sL = 'M';
- static String sR = "S";
- final static Object fsL = 'N';
- final static String fsR = "T";
+ String iR = "iR";
+ static Object sL = 1+'L';
+ static String sR = "sR";
+ final Object fiL = 2+'L';
+ final String fiR = "fiR";
+ final static Object fsL = 3+'L';
+ final static String fsR = "fsR";
- static final Object[][] CASES;
+ static final ArrayList<Object[]> STATIC_FIELD_CASES = new ArrayList<>();
+ static final ArrayList<Object[]> INSTANCE_FIELD_CASES = new ArrayList<>();
static {
- ArrayList<Object[]> cases = new ArrayList<>();
Object types[][] = {
{'L',Object.class}, {'R',String.class},
{'I',int.class}, {'J',long.class},
@@ -589,42 +602,91 @@
};
HasFields fields = new HasFields();
for (Object[] t : types) {
- for (int kind = 0; kind <= 2; kind++) {
+ for (int kind = 0; kind <= 1; kind++) {
boolean isStatic = (kind != 0);
- boolean isFinal = (kind == 2);
+ ArrayList<Object[]> cases = isStatic ? STATIC_FIELD_CASES : INSTANCE_FIELD_CASES;
char btc = (Character)t[0];
- String name = (isStatic ? "s" : "i") + btc;
- if (isFinal) name = "f" + name;
+ String fname = (isStatic ? "s" : "i") + btc;
+ String finalFname = (isStatic ? "fs" : "fi") + btc;
Class<?> type = (Class<?>) t[1];
- Object value;
- Field field;
- try {
- field = HasFields.class.getDeclaredField(name);
- } catch (NoSuchFieldException | SecurityException ex) {
- throw new InternalError("no field HasFields."+name);
- }
- try {
- value = field.get(fields);
- } catch (IllegalArgumentException | IllegalAccessException ex) {
- throw new InternalError("cannot fetch field HasFields."+name);
- }
+ // non-final field
+ Field nonFinalField = getField(fname, type);
+ Object value = getValue(fields, nonFinalField);
if (type == float.class) {
float v = 'F';
if (isStatic) v++;
- if (isFinal) v++;
assertTrue(value.equals(v));
}
- if (isFinal && isStatic) field.setAccessible(true);
- assertTrue(name.equals(field.getName()));
- assertTrue(type.equals(field.getType()));
- assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
- assertTrue(isFinal == (Modifier.isFinal(field.getModifiers())));
- cases.add(new Object[]{ field, value });
+ assertTrue(isStatic == (Modifier.isStatic(nonFinalField.getModifiers())));
+ cases.add(new Object[]{ nonFinalField, value });
+
+ // setAccessible(true) on final field but static final field only has read access
+ Field finalField = getField(finalFname, type);
+ Object fvalue = getValue(fields, finalField);
+ finalField.setAccessible(true);
+ assertTrue(isStatic == (Modifier.isStatic(finalField.getModifiers())));
+ cases.add(new Object[]{ finalField, fvalue, Error.class});
}
}
- cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
- cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
- CASES = cases.toArray(new Object[0][]);
+ INSTANCE_FIELD_CASES.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
+ STATIC_FIELD_CASES.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
+ }
+
+ private static Field getField(String name, Class<?> type) {
+ try {
+ Field field = HasFields.class.getDeclaredField(name);
+ assertTrue(name.equals(field.getName()));
+ assertTrue(type.equals(field.getType()));
+ return field;
+ } catch (NoSuchFieldException | SecurityException ex) {
+ throw new InternalError("no field HasFields."+name);
+ }
+ }
+
+ private static Object getValue(Object o, Field field) {
+ try {
+ return field.get(o);
+ } catch (IllegalArgumentException | IllegalAccessException ex) {
+ throw new InternalError("cannot fetch field HasFields."+field.getName());
+ }
+ }
+
+ static Object[][] testCasesFor(int testMode) {
+ Stream<Object[]> cases;
+ if ((testMode & TEST_UNREFLECT) != 0) {
+ cases = Stream.concat(STATIC_FIELD_CASES.stream(), INSTANCE_FIELD_CASES.stream());
+ } else if ((testMode & TEST_FIND_STATIC) != 0) {
+ cases = STATIC_FIELD_CASES.stream();
+ } else if ((testMode & TEST_FIND_FIELD) != 0) {
+ cases = INSTANCE_FIELD_CASES.stream();
+ } else {
+ throw new InternalError("unexpected test mode: " + testMode);
+ }
+ return cases.map(c -> mapTestCase(testMode, c)).toArray(Object[][]::new);
+
+ }
+
+ private static Object[] mapTestCase(int testMode, Object[] c) {
+ // non-final fields (2-element) and final fields (3-element) if not TEST_SETTER
+ if (c.length == 2 || (testMode & TEST_SETTER) == 0)
+ return c;
+
+ // final fields (3-element)
+ assertTrue((testMode & TEST_SETTER) != 0 && c[0] instanceof Field && c[2] == Error.class);
+ if ((testMode & TEST_UNREFLECT) == 0)
+ return new Object[]{ c[0], c[2]}; // negative test case; can't set on final fields
+
+ // unreflectSetter grants write access on instance final field if accessible flag is true
+ // hence promote the negative test case to positive test case
+ Field f = (Field) c[0];
+ int mods = f.getModifiers();
+ if (!Modifier.isFinal(mods) || (!Modifier.isStatic(mods) && f.isAccessible())) {
+ // positive test case
+ return new Object[]{ c[0], c[1] };
+ } else {
+ // otherwise, negative test case
+ return new Object[]{ c[0], c[2]};
+ }
}
}
--- a/test/jdk/java/lang/reflect/AccessibleObject/CanAccessTest.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/lang/reflect/AccessibleObject/CanAccessTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -94,7 +94,7 @@
* for instance members
*/
public void testInstanceMethod() throws Exception {
- Method m = Unsafe.class.getDeclaredMethod("addressSize0");
+ Method m = Unsafe.class.getDeclaredMethod("allocateMemory0", long.class);
assertFalse(m.canAccess(INSTANCE));
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019, 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 8221530
+ * @summary Test uses custom launcher that starts VM using JNI that verifies
+ * reflection API with null caller class
+ * @library /test/lib
+ * @run main/native CallerAccessTest
+ */
+
+import java.io.File;
+import java.util.Map;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class CallerAccessTest {
+ public static void main(String[] args) throws IOException {
+ Path launcher = Paths.get(System.getProperty("test.nativepath"), "CallerAccessTest");
+ ProcessBuilder pb = new ProcessBuilder(launcher.toString());
+ Map<String, String> env = pb.environment();
+
+ String libName = Platform.isWindows() ? "bin" : "lib";
+ Path libPath = Paths.get(Utils.TEST_JDK).resolve(libName);
+ String libDir = libPath.toAbsolutePath().toString();
+ String serverDir = libPath.resolve("server").toAbsolutePath().toString();
+
+ // set up shared library path
+ String sharedLibraryPathEnvName = Platform.sharedLibraryPathVariableName();
+ env.compute(sharedLibraryPathEnvName,
+ (k, v) -> (v == null) ? libDir : v + File.pathSeparator + libDir);
+ env.compute(sharedLibraryPathEnvName,
+ (k, v) -> (v == null) ? serverDir : v + File.pathSeparator + serverDir);
+
+ System.out.println("Launching: " + launcher + " shared library path: " +
+ env.get(sharedLibraryPathEnvName));
+ new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/exeCallerAccessTest/exeCallerAccessTest.c Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "jni.h"
+#include "assert.h"
+
+static jclass classClass;
+static jclass iaeClass;
+static jmethodID mid_Class_forName;
+static jmethodID mid_Class_getField;
+static jmethodID mid_Field_get;
+
+int getField(JNIEnv *env, char* declaringClass_name, char* field_name);
+int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env);
+
+int main(int argc, char** args) {
+ JavaVM *jvm;
+ JNIEnv *env;
+ JavaVMInitArgs vm_args;
+ JavaVMOption options[1];
+ jint rc;
+
+ vm_args.version = JNI_VERSION_1_2;
+ vm_args.nOptions = 0;
+ vm_args.options = options;
+
+ if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) {
+ printf("ERROR: cannot create VM.\n");
+ exit(-1);
+ }
+
+ classClass = (*env)->FindClass(env, "java/lang/Class");
+ iaeClass = (*env)->FindClass(env, "java/lang/IllegalAccessException");
+ mid_Class_forName = (*env)->GetStaticMethodID(env, classClass, "forName",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ assert(mid_Class_forName != NULL);
+
+ mid_Class_getField = (*env)->GetMethodID(env, classClass, "getField",
+ "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
+ assert(mid_Class_getField != NULL);
+
+ jclass fieldClass = (*env)->FindClass(env, "java/lang/reflect/Field");
+ mid_Field_get = (*env)->GetMethodID(env, fieldClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
+ assert(mid_Class_getField != NULL);
+
+ // can access to public member of an exported type
+ if ((rc = getField(env, "java.lang.Integer", "TYPE")) != 0) {
+ printf("ERROR: fail to access java.lang.Integer::TYPE\n");
+ exit(-1);
+ }
+
+ // expect IAE to jdk.internal.misc.Unsafe class
+ if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) {
+ printf("ERROR: IAE not thrown\n");
+ exit(-1);
+ }
+ if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) {
+ printf("ERROR: exception is not an instance of IAE\n");
+ exit(-1);
+ }
+
+ // expect IAE to jdk.internal.misc.Unsafe class
+ if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) {
+ printf("ERROR: IAE not thrown\n");
+ exit(-1);
+ }
+ if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) {
+ printf("ERROR: exception is not an instance of IAE\n");
+ exit(-1);
+ }
+
+ (*jvm)->DestroyJavaVM(jvm);
+ return 0;
+}
+
+int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env) {
+ jthrowable t = (*env)->ExceptionOccurred(env);
+ if ((*env)->IsInstanceOf(env, t, iaeClass) == JNI_TRUE) {
+ (*env)->ExceptionClear(env);
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+int getField(JNIEnv *env, char* declaringClass_name, char* field_name) {
+ jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName,
+ (*env)->NewStringUTF(env, declaringClass_name));
+ if ((*env)->ExceptionOccurred(env) != NULL) {
+ (*env)->ExceptionDescribe(env);
+ return 1;
+ }
+
+ jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name));
+ if ((*env)->ExceptionOccurred(env) != NULL) {
+ (*env)->ExceptionDescribe(env);
+ return 2;
+ }
+
+ jobject v = (*env)->CallObjectMethod(env, f, mid_Field_get, c);
+ if ((*env)->ExceptionOccurred(env) != NULL) {
+ (*env)->ExceptionDescribe(env);
+ return 3;
+ }
+ return 0;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/security/Permissions/DeserializeInvalidPermissions.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, 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 8020637
+ * @summary Deserialize a serialized Permissions object with incorrect Class to
+ * Permission mappings
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.security.Permissions;
+import java.util.Base64;
+
+public class DeserializeInvalidPermissions {
+
+ private static final String BASE = System.getProperty("test.src", ".");
+
+ /**
+ * A base64 encoded serialized Permissions object. This contains two
+ * Permissions, SecurityPermission("foo") and FilePermission("bar", "read").
+ * However, the Hashtable mappings have been switched, such that
+ * FilePermission.class maps to BasicPermissionCollection (which contains
+ * the SecurityPermission) and SecurityPermission.class maps to
+ * FilePermissionCollection.
+ */
+ private static String INVALID_PERMISSIONS =
+ "rO0ABXNyABlqYXZhLnNlY3VyaXR5LlBlcm1pc3Npb25zQ21LTdLID1ADAAJMAA1hbGxQ" +
+ "ZXJtaXNzaW9udAAkTGphdmEvc2VjdXJpdHkvUGVybWlzc2lvbkNvbGxlY3Rpb247TAAF" +
+ "cGVybXN0ABVMamF2YS91dGlsL0hhc2h0YWJsZTt4cgAiamF2YS5zZWN1cml0eS5QZXJt" +
+ "aXNzaW9uQ29sbGVjdGlvbqKk2tZqGAkpAgABWgAIcmVhZE9ubHl4cABwc3IAE2phdmEu" +
+ "dXRpbC5IYXNodGFibGUTuw8lIUrkuAMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4" +
+ "cD9AAAAAAAADdwgAAAAEAAAAAnZyABZqYXZhLmlvLkZpbGVQZXJtaXNzaW9ubg+fk/TA" +
+ "qbsDAAFMAAdhY3Rpb25zdAASTGphdmEvbGFuZy9TdHJpbmc7eHIAGGphdmEuc2VjdXJp" +
+ "dHkuUGVybWlzc2lvbrHG4T8oV1F+AgABTAAEbmFtZXEAfgAIeHBzcgAnamF2YS5zZWN1" +
+ "cml0eS5CYXNpY1Blcm1pc3Npb25Db2xsZWN0aW9uCkKHBI3t48cDAANaAAthbGxfYWxs" +
+ "b3dlZEwACXBlcm1DbGFzc3QAEUxqYXZhL2xhbmcvQ2xhc3M7TAALcGVybWlzc2lvbnNx" +
+ "AH4AAnhxAH4AAwAAdnIAIGphdmEuc2VjdXJpdHkuU2VjdXJpdHlQZXJtaXNzaW9uSKpm" +
+ "PrGHHSYCAAB4cgAdamF2YS5zZWN1cml0eS5CYXNpY1Blcm1pc3Npb25XJQvcz06megIA" +
+ "AHhxAH4ACXNxAH4ABT9AAAAAAAABdwgAAAACAAAAAXQAA2Zvb3NxAH4ADnEAfgASeHhx" +
+ "AH4AEHNyACBqYXZhLmlvLkZpbGVQZXJtaXNzaW9uQ29sbGVjdGlvbh6SeX3UjlWpAwAB" +
+ "TAALcGVybWlzc2lvbnN0ABJMamF2YS91dGlsL1ZlY3Rvcjt4cQB+AAMAc3IAEGphdmEu" +
+ "dXRpbC5WZWN0b3LZl31bgDuvAQMAA0kAEWNhcGFjaXR5SW5jcmVtZW50SQAMZWxlbWVu" +
+ "dENvdW50WwALZWxlbWVudERhdGF0ABNbTGphdmEvbGFuZy9PYmplY3Q7eHAAAAAAAAAA" +
+ "AXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAFzcQB+AAd0AANi" +
+ "YXJ0AARyZWFkeHh4eHg=";
+
+ /**
+ * A base64 encoded serialized PermissionsHash object, which is an internal
+ * class used to store Permissions that do not implement their own
+ * PermissionCollection. This contains one Permission,
+ * PrivateCredentialPermission("a.b.PrivateCredential a.b.Principal
+ * \"duke\"", "read")
+ * However, the Hashtable entry has been modified to map the
+ * PrivateCredentialPermission to SecurityPermission("foo") instead of
+ * itself.
+ */
+ private static String INVALID_PERMISSIONS_HASH =
+ "rO0ABXNyABlqYXZhLnNlY3VyaXR5LlBlcm1pc3Npb25zQ21LTdLID1ADAAJMAA1hbGxQ" +
+ "ZXJtaXNzaW9udAAkTGphdmEvc2VjdXJpdHkvUGVybWlzc2lvbkNvbGxlY3Rpb247TAAF" +
+ "cGVybXN0ABVMamF2YS91dGlsL0hhc2h0YWJsZTt4cgAiamF2YS5zZWN1cml0eS5QZXJt" +
+ "aXNzaW9uQ29sbGVjdGlvbqKk2tZqGAkpAgABWgAIcmVhZE9ubHl4cAFwc3IAE2phdmEu" +
+ "dXRpbC5IYXNodGFibGUTuw8lIUrkuAMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4" +
+ "cD9AAAAAAAAEdwgAAAAGAAAAA3ZyABZqYXZhLmlvLkZpbGVQZXJtaXNzaW9ubg+fk/TA" +
+ "qbsDAAFMAAdhY3Rpb25zdAASTGphdmEvbGFuZy9TdHJpbmc7eHIAGGphdmEuc2VjdXJp" +
+ "dHkuUGVybWlzc2lvbrHG4T8oV1F+AgABTAAEbmFtZXEAfgAIeHBzcgAgamF2YS5pby5G" +
+ "aWxlUGVybWlzc2lvbkNvbGxlY3Rpb24eknl91I5VqQMAAUwAC3Blcm1pc3Npb25zdAAS" +
+ "TGphdmEvdXRpbC9WZWN0b3I7eHEAfgADAHNyABBqYXZhLnV0aWwuVmVjdG9y2Zd9W4A7" +
+ "rwEDAANJABFjYXBhY2l0eUluY3JlbWVudEkADGVsZW1lbnRDb3VudFsAC2VsZW1lbnRE" +
+ "YXRhdAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAAAAAAAF1cgATW0xqYXZhLmxhbmcu" +
+ "T2JqZWN0O5DOWJ8QcylsAgAAeHAAAAABc3EAfgAHdAADYmFydAAEcmVhZHh4eHZyAC9q" +
+ "YXZheC5zZWN1cml0eS5hdXRoLlByaXZhdGVDcmVkZW50aWFsUGVybWlzc2lvbklV3Hd7" +
+ "UH9MAgADWgAHdGVzdGluZ0wAD2NyZWRlbnRpYWxDbGFzc3EAfgAITAAKcHJpbmNpcGFs" +
+ "c3QAD0xqYXZhL3V0aWwvU2V0O3hxAH4ACXNyAB1qYXZhLnNlY3VyaXR5LlBlcm1pc3Np" +
+ "b25zSGFzaIomZbSmPV1AAwABTAAFcGVybXNxAH4AAnhxAH4AAwBzcQB+AAU/QAAAAAAA" +
+ "AXcIAAAAAgAAAAFzcQB+ABZ0ACphLmIuUHJpdmF0ZUNyZWRlbnRpYWwgYS5iLlByaW5j" +
+ "aXBhbCAiZHVrZSIAdAAVYS5iLlByaXZhdGVDcmVkZW50aWFscHNyACBqYXZhLnNlY3Vy" +
+ "aXR5LlNlY3VyaXR5UGVybWlzc2lvbkiqZj6xhx0mAgAAeHIAHWphdmEuc2VjdXJpdHku" +
+ "QmFzaWNQZXJtaXNzaW9uVyUL3M9OpnoCAAB4cQB+AAl0AANmb294eHZxAH4AH3NyACdq" +
+ "YXZhLnNlY3VyaXR5LkJhc2ljUGVybWlzc2lvbkNvbGxlY3Rpb24KQocEje3jxwMAA1oA" +
+ "C2FsbF9hbGxvd2VkTAAJcGVybUNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAAtwZXJt" +
+ "aXNzaW9uc3EAfgACeHEAfgADAABxAH4AI3NxAH4ABT9AAAAAAAABdwgAAAACAAAAAXEA" +
+ "fgAic3EAfgAfcQB+ACJ4eHh4";
+
+ public static void main(String[] args) throws Exception {
+
+ Base64.Decoder decoder = Base64.getDecoder();
+ deserialize(decoder.decode(INVALID_PERMISSIONS));
+ deserialize(decoder.decode(INVALID_PERMISSIONS_HASH));
+ }
+
+ private static void deserialize(byte[] serialBytes) throws Exception {
+ try (ObjectInputStream ois =
+ new ObjectInputStream(new ByteArrayInputStream(serialBytes))) {
+ try {
+ Permissions p = (Permissions) ois.readObject();
+ throw new Exception("expected InvalidObjectException");
+ } catch (InvalidObjectException ioe) {
+ // test passed
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/security/Signature/SignatureGetInstance.java Wed Apr 10 10:46:53 2019 +0530
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2019, 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 8216039
+ * @summary Ensure the BC provider-reselection workaround in Signature class
+ * functions correctly
+ * @modules java.base/sun.security.util
+ * @run main/othervm SignatureGetInstance
+ */
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+import sun.security.util.SignatureUtil;
+
+public class SignatureGetInstance {
+
+ private static final String SIGALG = "RSASSA-PSS";
+
+ public static void main(String[] args) throws Exception {
+ Provider testProvider = new TestProvider();
+ // put test provider before SunRsaSign provider
+ Security.insertProviderAt(testProvider, 1);
+ //Security.addProvider(testProvider);
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ KeyPair kp = kpg.generateKeyPair();
+
+ MyPrivKey testPriv = new MyPrivKey();
+ MyPubKey testPub = new MyPubKey();
+
+ testDblInit(testPriv, testPub, true, "TestProvider");
+ testDblInit(kp.getPrivate(), kp.getPublic(), true, "SunRsaSign");
+ testDblInit(testPriv, kp.getPublic(), false, null);
+ testDblInit(kp.getPrivate(), testPub, false, null);
+
+ testSetAndInit(null, testPriv, true);
+ testSetAndInit(null, testPub, true);
+ testSetAndInit(null, kp.getPrivate(), true);
+ testSetAndInit(null, kp.getPublic(), true);
+
+ String provName = "SunRsaSign";
+ testSetAndInit(provName, testPriv, false);
+ testSetAndInit(provName, testPub, false);
+ testSetAndInit(provName, kp.getPrivate(), true);
+ testSetAndInit(provName, kp.getPublic(), true);
+
+ provName = "TestProvider";
+ testSetAndInit(provName, testPriv, true);
+ testSetAndInit(provName, testPub, true);
+ testSetAndInit(provName, kp.getPrivate(), false);
+ testSetAndInit(provName, kp.getPublic(), false);
+
+ System.out.println("Test Passed");
+ }
+
+ private static void checkName(Signature s, String name) {
+ if (name != null &&
+ !(name.equals(s.getProvider().getName()))) {
+ throw new RuntimeException("Fail: provider name mismatch");
+ }
+ }
+
+ private static void testDblInit(PrivateKey key1, PublicKey key2,
+ boolean shouldPass, String expectedProvName) throws Exception {
+ Signature sig = Signature.getInstance(SIGALG);
+ SignatureUtil.initSignWithParam(sig, key1, PSSParameterSpec.DEFAULT, null);
+ try {
+ sig.initVerify(key2);
+ if (!shouldPass) {
+ throw new RuntimeException("Fail: should throw InvalidKeyException");
+ }
+ checkName(sig, expectedProvName);
+ } catch (InvalidKeyException ike) {
+ if (shouldPass) {
+ System.out.println("Fail: Unexpected InvalidKeyException");
+ throw ike;
+ }
+ }
+ }
+
+ private static void testSetAndInit(String provName, Key key,
+ boolean shouldPass) throws Exception {
+ Signature sig;
+ if (provName == null) {
+ sig = Signature.getInstance(SIGALG);
+ } else {
+ sig = Signature.getInstance(SIGALG, provName);
+ }
+ AlgorithmParameterSpec params = PSSParameterSpec.DEFAULT;
+ boolean doSign = (key instanceof PrivateKey);
+ try {
+ if (doSign) {
+ SignatureUtil.initSignWithParam(sig, (PrivateKey)key, params, null);
+ } else {
+ SignatureUtil.initVerifyWithParam(sig, (PublicKey)key, params);
+ }
+ if (!shouldPass) {
+ throw new RuntimeException("Fail: should throw InvalidKeyException");
+ }
+ checkName(sig, provName);
+ // check that the earlier parameter is still there
+ if (sig.getParameters() == null) {
+ throw new RuntimeException("Fail: parameters not preserved");
+ }
+ } catch (InvalidKeyException ike) {
+ if (shouldPass) {
+ System.out.println("Fail: Unexpected InvalidKeyException");
+ throw ike;
+ }
+ }
+ }
+
+ // Test provider which only accepts its own Key objects
+ // Registered to be more preferred than SunRsaSign provider
+ // for testing deferred provider selection
+ public static class TestProvider extends Provider {
+ TestProvider() {
+ super("TestProvider", "1.0", "provider for SignatureGetInstance");
+ put("Signature.RSASSA-PSS",
+ "SignatureGetInstance$MySigImpl");
+ }
+ }
+
+ public static class MyPrivKey implements PrivateKey {
+ public String getAlgorithm() { return "RSASSA-PSS"; }
+ public String getFormat() { return "MyOwn"; }
+ public byte[] getEncoded() { return null; }
+ }
+
+ public static class MyPubKey implements PublicKey {
+ public String getAlgorithm() { return "RSASSA-PSS"; }
+ public String getFormat() { return "MyOwn"; }
+ public byte[] getEncoded() { return null; }
+ }
+
+ public static class MySigImpl extends SignatureSpi {
+ // simulate BC behavior of only using params set before init calls
+ AlgorithmParameterSpec initParamSpec = null;
+ AlgorithmParameterSpec paramSpec = null;
+
+ public MySigImpl() {
+ super();
+ }
+
+ @Override
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ if (!(publicKey instanceof MyPubKey)) {
+ throw new InvalidKeyException("Must be MyPubKey");
+ }
+ initParamSpec = paramSpec;
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ if (!(privateKey instanceof MyPrivKey)) {
+ throw new InvalidKeyException("Must be MyPrivKey");
+ }
+ initParamSpec = paramSpec;
+ }
+
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ }
+
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ }
+
+ @Override
+ protected byte[] engineSign()
+ throws SignatureException {
+ return new byte[0];
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes)
+ throws SignatureException {
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ }
+
+ @Override
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ paramSpec = params;
+ }
+
+ @Override
+ @Deprecated
+ protected AlgorithmParameters engineGetParameter(String param)
+ throws InvalidParameterException {
+ return null;
+ }
+
+ @Override
+ protected AlgorithmParameters engineGetParameters() {
+ if (initParamSpec != null) {
+ try {
+ AlgorithmParameters ap =
+ AlgorithmParameters.getInstance("RSASSA-PSS");
+ ap.init(initParamSpec);
+ return ap;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+ }
+}
--- a/test/jdk/java/util/Map/MapFactories.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/util/Map/MapFactories.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -50,7 +50,7 @@
/*
* @test
- * @bug 8048330
+ * @bug 8048330 8221924
* @summary Test convenience static factory methods on Map.
* @run testng MapFactories
*/
@@ -386,6 +386,11 @@
act.containsKey(null);
}
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void getNullShouldThrowNPE(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.get(null);
+ }
+
@Test(dataProvider="all")
public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) {
// assume that act.equals(exp) tested elsewhere
--- a/test/jdk/java/util/logging/LogManager/TestLoggerNames.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/java/util/logging/LogManager/TestLoggerNames.java Wed Apr 10 10:46:53 2019 +0530
@@ -133,7 +133,8 @@
public static void main(String[] args) throws InterruptedException {
- LogManager.getLogManager().addLogger(new TestLogger("com.foo.bar.zzz", null));
+ TestLogger test = new TestLogger("com.foo.bar.zzz", null);
+ LogManager.getLogManager().addLogger(test);
try {
Logger.getLogger(null);
throw new RuntimeException("Logger.getLogger(null) didn't throw expected NPE");
@@ -144,7 +145,9 @@
loggers.add(Logger.getLogger("one.two.addMeAChild"));
loggers.add(Logger.getLogger("aaa.bbb.replaceMe"));
loggers.add(Logger.getLogger("bbb.aaa.addMeAChild"));
- TestLogger test = (TestLogger)Logger.getLogger("com.foo.bar.zzz");
+ if (test != Logger.getLogger("com.foo.bar.zzz")) {
+ throw new AssertionError("wrong logger returned");
+ }
loggers.add(Logger.getLogger("ddd.aaa.addMeAChild"));
checkLoggerNames(loggers);
--- a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java Wed Apr 10 10:46:53 2019 +0530
@@ -23,9 +23,9 @@
/*
* @test
- * @bug 4750141 4895631 8217579
+ * @bug 4750141 4895631 8217579 8163326
* @summary Check enabled and supported ciphersuites are correct
- * @run main CheckCipherSuites default
+ * @run main/othervm CheckCipherSuites default
* @run main/othervm CheckCipherSuites limited
*/
@@ -38,54 +38,97 @@
// List of enabled cipher suites when the "crypto.policy" security
// property is set to "unlimited" (the default value).
private final static String[] ENABLED_DEFAULT = {
- "TLS_AES_128_GCM_SHA256",
+ // TLS 1.3 cipher suites
"TLS_AES_256_GCM_SHA384",
+ "TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256",
+
+ // Suite B compliant cipher suites
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+
+ // Not suite B, but we want it to position the suite early
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+
+ // AES_256(GCM) - ECDHE - forward screcy
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
- "TLS_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+
+ // AES_128(GCM) - ECDHE - forward screcy
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(GCM) - DHE - forward screcy
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_128(GCM) - DHE - forward screcy
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(CBC) - ECDHE - forward screcy
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
- "TLS_RSA_WITH_AES_256_CBC_SHA256",
+
+ // AES_256(CBC) - ECDHE - forward screcy
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(CBC) - DHE - forward screcy
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+
+ // AES_128(CBC) - DHE - forward screcy
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(GCM) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+ "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+
+ // AES_128(GCM) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(CBC) - not forward screcy
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
- "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
- "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+
+ // AES_128(CBC) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(CBC) - ECDHE - using SHA
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
- "TLS_RSA_WITH_AES_256_CBC_SHA",
- "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
- "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+
+ // AES_128(CBC) - ECDHE - using SHA
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+
+ // AES_256(CBC) - DHE - using SHA
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
- "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
- "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_RSA_WITH_AES_128_CBC_SHA",
+
+ // AES_128(CBC) - DHE - using SHA
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+
+ // AES_256(CBC) - using SHA, not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+
+ // AES_128(CBC) - using SHA, not forward screcy
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+
+ // deprecated
+ "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
};
@@ -95,79 +138,122 @@
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
};
// List of supported cipher suites when the "crypto.policy" security
// property is set to "unlimited" (the default value).
private final static String[] SUPPORTED_DEFAULT = {
- "TLS_AES_128_GCM_SHA256",
+ // TLS 1.3 cipher suites
"TLS_AES_256_GCM_SHA384",
+ "TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256",
+
+ // Suite B compliant cipher suites
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+
+ // Not suite B, but we want it to position the suite early
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+
+ // AES_256(GCM) - ECDHE - forward screcy
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
- "TLS_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+
+ // AES_128(GCM) - ECDHE - forward screcy
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(GCM) - DHE - forward screcy
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_128(GCM) - DHE - forward screcy
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(CBC) - ECDHE - forward screcy
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
- "TLS_RSA_WITH_AES_256_CBC_SHA256",
+
+ // AES_256(CBC) - ECDHE - forward screcy
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(CBC) - DHE - forward screcy
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+
+ // AES_128(CBC) - DHE - forward screcy
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(GCM) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+ "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+
+ // AES_128(GCM) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+
+ // AES_256(CBC) - not forward screcy
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
- "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
- "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+
+ // AES_128(CBC) - not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+
+ // AES_256(CBC) - ECDHE - using SHA
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
- "TLS_RSA_WITH_AES_256_CBC_SHA",
- "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
- "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+
+ // AES_128(CBC) - ECDHE - using SHA
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+
+ // AES_256(CBC) - DHE - using SHA
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
- "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
- "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_RSA_WITH_AES_128_CBC_SHA",
+
+ // AES_128(CBC) - DHE - using SHA
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+
+ // AES_256(CBC) - using SHA, not forward screcy
+ "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+
+ // AES_128(CBC) - using SHA, not forward screcy
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+
+ // deprecated
+ "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
};
@@ -177,25 +263,25 @@
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_RSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
};
@@ -228,7 +314,8 @@
throw new Exception("Illegal argument");
}
- SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
+ SSLSocketFactory factory =
+ (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket)factory.createSocket();
String[] enabled = socket.getEnabledCipherSuites();
@@ -257,5 +344,4 @@
long end = System.currentTimeMillis();
System.out.println("Done (" + (end - start) + " ms).");
}
-
}
--- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -25,7 +25,7 @@
/**
* @test
* @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
- * 8209452 8209506 8210432 8195793
+ * 8209452 8209506 8210432 8195793 8222089 8222133
* @summary Check root CA entries in cacerts file
*/
import java.io.File;
@@ -237,7 +237,22 @@
// Exception list to 90 days expiry policy
// No error will be reported if certificate in this list expires
- private static final HashSet<String> EXPIRY_EXC_ENTRIES = new HashSet<>();
+ private static final HashSet<String> EXPIRY_EXC_ENTRIES = new HashSet<>() {
+ {
+ // Valid until: Sat Jul 06 19:59:59 EDT 2019
+ add("certplusclass2primaryca [jdk]");
+ // Valid until: Sat Jul 06 19:59:59 EDT 2019
+ add("certplusclass3pprimaryca [jdk]");
+ // Valid until: Tue Jul 09 14:40:36 EDT 2019
+ add("utnuserfirstobjectca [jdk]");
+ // Valid until: Tue Jul 09 19:59:00 EDT 2019
+ add("deutschetelekomrootca2 [jdk]");
+ // Valid until: Tue Jul 09 13:36:58 EDT 2019
+ add("utnuserfirstclientauthemailca [jdk]");
+ // Valid until: Tue Jul 09 14:19:22 EDT 2019
+ add("utnuserfirsthardwareca [jdk]");
+ }
+ };
// Ninety days in milliseconds
private static final long NINETY_DAYS = 7776000000L;
--- a/test/jdk/sun/security/util/misc/SetNullSigParams.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/sun/security/util/misc/SetNullSigParams.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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,8 +23,8 @@
/*
* @test
- * @bug 8214096
- * @summary Make sure SignatureUtil can accept null algorithm parameters
+ * @bug 8214096 8216039
+ * @summary Make sure SignatureUtil works with null algorithm parameters
* @modules java.base/sun.security.util
*/
import java.security.*;
@@ -35,8 +35,8 @@
public static void main(String[] args) throws Exception {
Signature sig = new SpecialSigImpl();
- SignatureUtil.specialSetParameter(sig, (byte[]) null);
- SignatureUtil.specialSetParameter(sig, (AlgorithmParameters) null);
+ SignatureUtil.initVerifyWithParam(sig, (PublicKey) null, null);
+ SignatureUtil.initSignWithParam(sig, null, null, null);
}
// Sample Signature impl class which simulates 3rd party provider behavior
--- a/test/jdk/sun/tools/jcmd/TestProcessHelper.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/sun/tools/jcmd/TestProcessHelper.java Wed Apr 10 10:46:53 2019 +0530
@@ -108,7 +108,7 @@
for (String a : arg) {
cmd.add(a);
}
- testProcessHelper(cmd);
+ testProcessHelper(cmd, TEST_PROCESS_MAIN_CLASS);
}
}
}
@@ -130,7 +130,7 @@
for (String a : arg) {
cmd.add(a);
}
- testProcessHelper(cmd);
+ testProcessHelper(cmd, jarFile.getAbsolutePath());
}
}
@@ -156,7 +156,7 @@
for (String a : arg) {
cmd.add(a);
}
- testProcessHelper(cmd);
+ testProcessHelper(cmd, MODULE_NAME + "/" + TEST_PROCESS_MAIN_CLASS);
}
}
}
@@ -171,7 +171,7 @@
}
}
- private void testProcessHelper(List<String> args) throws Exception {
+ private void testProcessHelper(List<String> args, String expectedValue) throws Exception {
ProcessBuilder pb = new ProcessBuilder(args);
String cmd = pb.command().stream().collect(Collectors.joining(" "));
System.out.println("Starting the process:" + cmd);
@@ -179,7 +179,7 @@
if (!p.isAlive()) {
throw new RuntimeException("Cannot start the process: " + cmd);
}
- checkMainClass(p, TEST_PROCESS_MAIN_CLASS);
+ checkMainClass(p, expectedValue);
}
private File prepareJar() throws Exception {
--- a/test/jdk/tools/jar/modularJar/Basic.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/tools/jar/modularJar/Basic.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -24,7 +24,9 @@
import java.io.*;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Method;
-import java.nio.file.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.*;
import java.util.function.Consumer;
import java.util.jar.JarEntry;
@@ -32,6 +34,7 @@
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
+import java.util.spi.ToolProvider;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -59,6 +62,16 @@
*/
public class Basic {
+
+ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(()
+ -> new RuntimeException("jar tool not found")
+ );
+ private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+ .orElseThrow(()
+ -> new RuntimeException("javac tool not found")
+ );
+
static final Path TEST_SRC = Paths.get(System.getProperty("test.src", "."));
static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
static final Path MODULE_CLASSES = TEST_CLASSES.resolve("build");
@@ -977,13 +990,14 @@
}
Stream.of(args).forEach(commands::add);
ProcessBuilder p = new ProcessBuilder(commands);
- if (stdinSource != null)
+ if (stdinSource != null) {
p.redirectInput(stdinSource);
+ }
return run(p);
}
static Result jar(String... args) {
- return jarWithStdin(null, args);
+ return run(JAR_TOOL, args);
}
static Path compileModule(String mn) throws IOException {
@@ -1071,10 +1085,8 @@
static void javac(Path dest, Path modulePath, Path... sourceFiles)
throws IOException
{
- String javac = getJDKTool("javac");
List<String> commands = new ArrayList<>();
- commands.add(javac);
if (!TOOL_VM_OPTIONS.isEmpty()) {
commands.addAll(Arrays.asList(TOOL_VM_OPTIONS.split("\\s+", -1)));
}
@@ -1092,7 +1104,13 @@
}
Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
- quickFail(run(new ProcessBuilder(commands)));
+ StringWriter sw = new StringWriter();
+ try (PrintWriter pw = new PrintWriter(sw)) {
+ int rc = JAVAC_TOOL.run(pw, pw, commands.toArray(new String[0]));
+ if(rc != 0) {
+ throw new RuntimeException(sw.toString());
+ }
+ }
}
static Result java(Path modulePath, String entryPoint, String... args) {
@@ -1138,9 +1156,13 @@
return false;
}
- static void quickFail(Result r) {
- if (r.ec != 0)
- throw new RuntimeException(r.output);
+ static Result run(ToolProvider tp, String[] commands) {
+ int rc = 0;
+ StringWriter sw = new StringWriter();
+ try (PrintWriter pw = new PrintWriter(sw)) {
+ rc = tp.run(pw, pw, commands);
+ }
+ return new Result(rc, sw.toString());
}
static Result run(ProcessBuilder pb) {
--- a/test/jdk/tools/launcher/Arrrghs.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/jdk/tools/launcher/Arrrghs.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, 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
@@ -24,7 +24,7 @@
/**
* @test
* @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
- * 6894719 6968053 7151434 7146424 8007333 8077822 8143640 8132379
+ * 6894719 6968053 7151434 7146424 8007333 8077822 8143640 8132379 8218547
* @summary Argument parsing validation.
* @modules jdk.compiler
* jdk.zipfs
@@ -36,6 +36,9 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -55,20 +58,6 @@
*
*/
- /*
- * SIGH, On Windows all strings are quoted, we need to unwrap it
- */
- private static String removeExtraQuotes(String in) {
- if (isWindows) {
- // Trim the string and remove the enclosed quotes if any.
- in = in.trim();
- if (in.startsWith("\"") && in.endsWith("\"")) {
- return in.substring(1, in.length()-1);
- }
- }
- return in;
- }
-
// the pattern we hope to see in the output
static final Pattern ArgPattern = Pattern.compile("\\s*argv\\[[0-9]*\\].*=.*");
@@ -490,6 +479,27 @@
}
/*
+ * Tests -jar command on a jar file with "long" (> 260 chars) full path on Windows
+ */
+ @Test
+ void testLongPathJarFile() throws IOException {
+ if (!isWindows) {
+ return;
+ }
+ // put the jar file to a location with long path
+ String longPathPart = "longpathtest_longpathtest/";
+ String longPathStr = longPathPart.repeat(15);
+ Path longPath = Paths.get(longPathStr);
+ Path jarPath = Files.createDirectories(longPath).resolve("elp.jar");
+ File elp = jarPath.toFile();
+ createJar(elp, new File("Foo"), "public static void main(String[] args){ System.out.println(\"Hello from ELP\"); }");
+ System.out.println("execute " + elp.getAbsolutePath());
+ TestResult tr = doExec(javaCmd, "-jar", elp.getAbsolutePath());
+ tr.checkPositive();
+ tr.contains("Hello from ELP");
+ }
+
+ /*
* Tests various dispositions of the main method, these tests are limited
* to English locales as they check for error messages that are localized.
*/
--- a/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java Wed Apr 10 10:46:53 2019 +0530
@@ -109,7 +109,7 @@
checkOutput("pkg3/package-summary.html", true,
"<div class=\"contentContainer\">\n"
- + "<section role=\"region\"><a id=\"package.description\">\n"
+ + "<section><a id=\"package.description\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<div class=\"block\"><p>This is the first line. Note the newlines before the <p> is relevant.</div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Wed Apr 10 10:46:53 2019 +0530
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8072945 8081854 8141492 8148985 8150188 4649116 8173707 8151743 8169819 8183037 8182765 8196202
- * 8202624 8210047 8184205
+ * 8202624 8210047 8184205 8221871
* @summary Test the version of HTML generated by the javadoc tool.
* @author bpatel
* @library ../../lib
@@ -100,7 +100,7 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\"><a id=\"package.description\">\n"
+ "<section><a id=\"package.description\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<div class=\"block\">Test package.</div>",
@@ -129,13 +129,13 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Interface Hierarchy\">Interface Hierarchy</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Annotation Type Hierarchy\">Annotation Type Hierarchy</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Enum Hierarchy\">Enum Hierarchy</h2>",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -173,9 +173,9 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Contents\">Contents</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"pkg\">pkg.*</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -212,7 +212,7 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Package\">Package pkg</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -232,13 +232,13 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Interface Hierarchy\">Interface Hierarchy</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Annotation Type Hierarchy\">Annotation Type Hierarchy</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Enum Hierarchy\">Enum Hierarchy</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -280,11 +280,11 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2>Overview</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2>Package</h2>\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2>Class or Interface</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -303,46 +303,46 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"nested.class.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Nested Class Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"field.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Field Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Method Summary</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"field.detail\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Field Detail</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Detail</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.detail\">\n"
+ "<!-- -->\n"
@@ -365,7 +365,7 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"enum.constant.summary\">\n"
+ "<!-- -->\n"
@@ -373,7 +373,7 @@
+ "<h2>Enum Constant Summary</h2>\n"
+ "<div class=\"memberSummary\">\n",
"<table aria-labelledby=\"t0\">\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.summary\">\n"
+ "<!-- -->\n"
@@ -381,13 +381,13 @@
+ "<h2>Method Summary</h2>\n"
+ "<div class=\"memberSummary\">\n",
"<table aria-labelledby=\"t0\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"enum.constant.detail\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Enum Constant Detail</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.detail\">\n"
+ "<!-- -->\n"
@@ -410,7 +410,7 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.summary\">\n"
+ "<!-- -->\n"
@@ -418,7 +418,7 @@
+ "<h2>Method Summary</h2>\n"
+ "<div class=\"memberSummary\">\n",
"<table aria-labelledby=\"t0\">\n",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"method.detail\">\n"
+ "<!-- -->\n"
@@ -441,13 +441,13 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Summary</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
@@ -470,13 +470,13 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Summary</h2>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
@@ -499,21 +499,21 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"annotation.type.required.element.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Required Element Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"annotation.type.optional.element.summary\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Optional Element Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\"><a id=\"annotation.type.element.detail\">\n"
+ "<!-- -->\n"
@@ -537,7 +537,7 @@
"<main role=\"main\">\n"
+ "<div class=\"header\">",
"<div class=\"useSummary\">\n<table>",
- "<section role=\"region\"><a id=\"pkg\">\n"
+ "<section><a id=\"pkg\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Uses of <a href=\"../RegClass.html\" title=\"class in pkg1\">RegClass</a> in <a href=\"../../pkg/package-summary.html\">pkg</a></h2>\n"
@@ -568,7 +568,7 @@
"<a name=\"navbar.top.firstrow\">\n"
+ "<!-- -->\n"
+ "</a>",
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<h2 title=\"Package pkg Description\">Package pkg Description</h2>\n",
"<div class=\"typeSummary\">\n<table summary=\"Interface Summary table, listing interfaces, and an explanation\">",
"<div class=\"typeSummary\">\n<table summary=\"Class Summary table, listing classes, and an explanation\">",
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java Wed Apr 10 10:46:53 2019 +0530
@@ -478,7 +478,7 @@
void checkHtml5Description(boolean found) {
checkOutput("moduleA/module-summary.html", found,
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<div class=\"deprecationBlock\"><span class=\"deprecatedLabel\">Deprecated, for removal:"
+ " This API element is subject to removal in a future version.</span>\n"
+ "<div class=\"deprecationComment\">This module is deprecated.</div>\n"
@@ -490,7 +490,7 @@
+ "<div class=\"block\">This is a test description for the moduleA module with a Search "
+ "phrase <a id=\"searchphrase\" class=\"searchTagResult\">search phrase</a>.</div>");
checkOutput("moduleB/module-summary.html", found,
- "<section role=\"region\">\n"
+ "<section>\n"
+ "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ "<a id=\"module.description\">\n"
+ "<!-- -->\n"
--- a/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java Wed Apr 10 10:46:53 2019 +0530
@@ -151,7 +151,7 @@
);
checkOutput("class-use/UsedInC.html", true,
"<li class=\"blockList\">\n"
- + "<section role=\"region\"><a id=\"unnamed.package\">"
+ + "<section><a id=\"unnamed.package\">"
);
checkOutput("package-use.html", true,
"<th class=\"colFirst\" scope=\"row\">"
--- a/test/lib/jdk/test/lib/apps/LingeredApp.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/lib/jdk/test/lib/apps/LingeredApp.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -492,18 +492,22 @@
}
String theLockFileName = args[0];
+ Path path = Paths.get(theLockFileName);
try {
- Path path = Paths.get(theLockFileName);
-
while (Files.exists(path)) {
// Touch the lock to indicate our readiness
setLastModified(theLockFileName, epoch());
Thread.sleep(spinDelay);
}
- } catch (NoSuchFileException ex) {
+ } catch (IOException ex) {
// Lock deleted while we are setting last modified time.
- // Ignore error and lets the app exits
+ // Ignore the error and let the app exit.
+ if (Files.exists(path)) {
+ // If the lock file was not removed, return an error.
+ System.err.println("LingeredApp IOException: lock file still exists");
+ System.exit(4);
+ }
} catch (Exception ex) {
System.err.println("LingeredApp ERROR: " + ex);
// Leave exit_code = 1 to Java launcher
--- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Wed Apr 10 10:46:53 2019 +0530
@@ -38,6 +38,7 @@
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
public class DockerTestUtils {
@@ -45,8 +46,23 @@
private static boolean isDockerEngineAvailable = false;
private static boolean wasDockerEngineChecked = false;
- // Diagnostics: set to true to enable more diagnostic info
- private static final boolean DEBUG = false;
+ // Use this property to specify docker location on your system.
+ // E.g.: "/usr/local/bin/docker".
+ private static final String DOCKER_COMMAND =
+ System.getProperty("jdk.test.docker.command", "docker");
+
+ // Set this property to true to retain image after test. By default
+ // images are removed after test execution completes.
+ // Retaining the image can be useful for diagnostics and image inspection.
+ // E.g.: start image interactively: docker run -it <IMAGE_NAME>.
+ public static final boolean RETAIN_IMAGE_AFTER_TEST =
+ Boolean.getBoolean("jdk.test.docker.retain.image");
+
+ // Path to a JDK under test.
+ // This may be useful when developing tests on non-Linux platforms.
+ public static final String JDK_UNDER_TEST =
+ System.getProperty("jdk.test.docker.jdk", Utils.TEST_JDK);
+
/**
* Optimized check of whether the docker engine is available in a given
@@ -76,9 +92,7 @@
if (isDockerEngineAvailable()) {
return true;
} else {
- System.out.println("Docker engine is not available on this system");
- System.out.println("This test is SKIPPED");
- return false;
+ throw new SkippedException("Docker engine is not available on this system");
}
}
@@ -94,7 +108,7 @@
*/
private static boolean isDockerEngineAvailableCheck() throws Exception {
try {
- execute("docker", "ps")
+ execute(DOCKER_COMMAND, "ps")
.shouldHaveExitValue(0)
.shouldContain("CONTAINER")
.shouldContain("IMAGE");
@@ -126,7 +140,7 @@
throw new RuntimeException("The docker build directory already exists: " + buildDir);
}
- Path jdkSrcDir = Paths.get(Utils.TEST_JDK);
+ Path jdkSrcDir = Paths.get(JDK_UNDER_TEST);
Path jdkDstDir = buildDir.resolve("jdk");
Files.createDirectories(jdkDstDir);
@@ -157,7 +171,7 @@
DockerfileConfig.getBaseImageVersion());
// Build the docker
- execute("docker", "build", "--no-cache", "--tag", imageName, buildDir.toString())
+ execute(DOCKER_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString())
.shouldHaveExitValue(0)
.shouldContain("Successfully built");
}
@@ -174,7 +188,7 @@
public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception {
ArrayList<String> cmd = new ArrayList<>();
- cmd.add("docker");
+ cmd.add(DOCKER_COMMAND);
cmd.add("run");
if (opts.tty)
cmd.add("--tty=true");
@@ -201,11 +215,10 @@
* Remove docker image
*
* @param DockerRunOptions optins for running docker
- * @return output of the command
* @throws Exception
*/
- public static OutputAnalyzer removeDockerImage(String imageNameAndTag) throws Exception {
- return execute("docker", "rmi", "--force", imageNameAndTag);
+ public static void removeDockerImage(String imageNameAndTag) throws Exception {
+ execute(DOCKER_COMMAND, "rmi", "--force", imageNameAndTag);
}
--- a/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java Wed Apr 10 10:46:53 2019 +0530
@@ -46,7 +46,7 @@
switch (Platform.getOsArch()) {
case "aarch64":
- return "aarch64/ubuntu";
+ return "arm64v8/ubuntu";
case "ppc64le":
return "ppc64le/ubuntu";
case "s390x":
--- a/test/micro/org/openjdk/bench/java/lang/StringBuilders.java Wed Apr 10 10:32:43 2019 +0530
+++ b/test/micro/org/openjdk/bench/java/lang/StringBuilders.java Wed Apr 10 10:46:53 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -42,6 +42,8 @@
private String[] str16p8p7;
private String[] str3p9p8;
private String[] str22p40p31;
+ private StringBuilder sbLatin1;
+ private StringBuilder sbUtf16;
@Setup
public void setup() {
@@ -53,6 +55,8 @@
str16p8p7 = new String[]{"1234567890123456", "12345678", "1234567"};
str3p9p8 = new String[]{"123", "123456789", "12345678"};
str22p40p31 = new String[]{"1234567890123456789012", "1234567890123456789012345678901234567890", "1234567890123456789012345678901"};
+ sbLatin1 = new StringBuilder("Latin1 string");
+ sbUtf16 = new StringBuilder("UTF-\uFF11\uFF16 string");
}
/** StringBuilder wins over StringMaker. */
@@ -256,4 +260,24 @@
result.append("stringelinglinglinglong");
return result.toString();
}
+
+ @Benchmark
+ public StringBuilder fromLatin1String() {
+ return new StringBuilder("Latin1 string");
+ }
+
+ @Benchmark
+ public StringBuilder fromUtf16String() {
+ return new StringBuilder("UTF-\uFF11\uFF16 string");
+ }
+
+ @Benchmark
+ public StringBuilder fromLatin1StringBuilder() {
+ return new StringBuilder(sbLatin1);
+ }
+
+ @Benchmark
+ public StringBuilder fromUtf16StringBuilder() {
+ return new StringBuilder(sbUtf16);
+ }
}