This commit is contained in:
Dean Long 2015-10-27 01:45:01 -04:00
commit 206767c0a2
1072 changed files with 73572 additions and 31006 deletions
.hgignore.hgtags.hgtags-top-repoREADME-builds.htmlREADME-builds.md
common
corba
.hgtags
src
java.corba/share/classes/com/sun/corba/se/impl/io
jdk.rmic/share/classes/sun/rmi/rmic/iiop
hotspot

@ -5,3 +5,5 @@ nbproject/private/
^.hgtip
^.bridge2
.DS_Store
.metadata/
.recommenders/

@ -327,3 +327,7 @@ c8753d0be1778944dc512ec86a459941ea1ad2c3 jdk9-b78
6521875cb63e1d0121b30af56ebbc36db078c4c6 jdk9-b82
f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83
51b2db2fa04c16d767b66113dbf08c5349ce382a jdk9-b84
8392405ab038b22e69a3728e17dbdd9e3d3a22ed jdk9-b85
7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86
1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87
16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88

@ -327,3 +327,7 @@ b8afcf91331d78626a583ec1b63164468d6f4181 jdk9-b81
42b56d1f418523ecb61a49d7493302c80c8009cc jdk9-b82
ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
1c8134475511ffe6726677e1418a89a7a45e92d6 jdk9-b84
1f345217c9bab05f192d00cf1665b3286c49ccdb jdk9-b85
2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88

File diff suppressed because it is too large Load Diff

1263
README-builds.md Normal file

File diff suppressed because it is too large Load Diff

@ -288,7 +288,7 @@ AC_DEFUN([BASIC_SETUP_TOOL],
# Publish this variable in the help.
AC_ARG_VAR($1, [Override default value for $1])
if test "x[$]$1" = x; then
if [[ -z "${$1+x}" ]]; then
# The variable is not set by user, try to locate tool using the code snippet
$2
else
@ -312,25 +312,32 @@ AC_DEFUN([BASIC_SETUP_TOOL],
# for unknown variables in the end.
CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
# Check if the provided tool contains a complete path.
tool_specified="[$]$1"
tool_basename="${tool_specified##*/}"
if test "x$tool_basename" = "x$tool_specified"; then
# A command without a complete path is provided, search $PATH.
AC_MSG_NOTICE([Will search for user supplied tool $1=$tool_basename])
AC_PATH_PROG($1, $tool_basename)
if test "x[$]$1" = x; then
AC_MSG_ERROR([User supplied tool $tool_basename could not be found])
fi
else
# Otherwise we believe it is a complete path. Use it as it is.
AC_MSG_NOTICE([Will use user supplied tool $1=$tool_specified])
# Check if we try to supply an empty value
if test "x[$]$1" = x; then
AC_MSG_NOTICE([Setting user supplied tool $1= (no value)])
AC_MSG_CHECKING([for $1])
if test ! -x "$tool_specified"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([User supplied tool $1=$tool_specified does not exist or is not executable])
AC_MSG_RESULT([disabled])
else
# Check if the provided tool contains a complete path.
tool_specified="[$]$1"
tool_basename="${tool_specified##*/}"
if test "x$tool_basename" = "x$tool_specified"; then
# A command without a complete path is provided, search $PATH.
AC_MSG_NOTICE([Will search for user supplied tool $1=$tool_basename])
AC_PATH_PROG($1, $tool_basename)
if test "x[$]$1" = x; then
AC_MSG_ERROR([User supplied tool $tool_basename could not be found])
fi
else
# Otherwise we believe it is a complete path. Use it as it is.
AC_MSG_NOTICE([Will use user supplied tool $1=$tool_specified])
AC_MSG_CHECKING([for $1])
if test ! -x "$tool_specified"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([User supplied tool $1=$tool_specified does not exist or is not executable])
fi
AC_MSG_RESULT([$tool_specified])
fi
AC_MSG_RESULT([$tool_specified])
fi
fi
fi
@ -376,9 +383,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
[
# Start with tools that do not need have cross compilation support
# and can be expected to be found in the default PATH. These tools are
# used by configure. Nor are these tools expected to be found in the
# devkit from the builddeps server either, since they are
# needed to download the devkit.
# used by configure.
# First are all the simple required tools.
BASIC_REQUIRE_PROGS(BASENAME, basename)
@ -405,6 +410,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
BASIC_REQUIRE_PROGS(NAWK, [nawk gawk awk])
BASIC_REQUIRE_PROGS(PRINTF, printf)
BASIC_REQUIRE_PROGS(RM, rm)
BASIC_REQUIRE_PROGS(RMDIR, rmdir)
BASIC_REQUIRE_PROGS(SH, sh)
BASIC_REQUIRE_PROGS(SORT, sort)
BASIC_REQUIRE_PROGS(TAIL, tail)
@ -437,6 +443,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
BASIC_PATH_PROGS(READLINK, [greadlink readlink])
BASIC_PATH_PROGS(DF, df)
BASIC_PATH_PROGS(CPIO, [cpio bsdcpio])
BASIC_PATH_PROGS(NICE, nice)
])
# Setup basic configuration paths, and platform-specific stuff related to PATHs.

@ -108,12 +108,6 @@ AC_DEFUN([BOOTJDK_CHECK_ARGUMENTS],
fi
])
# Test: Is bootjdk available from builddeps?
AC_DEFUN([BOOTJDK_CHECK_BUILDDEPS],
[
BDEPS_CHECK_MODULE(BOOT_JDK, bootjdk, xxx, [BOOT_JDK_FOUND=maybe], [BOOT_JDK_FOUND=no])
])
# Test: Is $JAVA_HOME set?
AC_DEFUN([BOOTJDK_CHECK_JAVA_HOME],
[
@ -276,9 +270,6 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
AC_MSG_ERROR([The path given by --with-boot-jdk does not contain a valid Boot JDK])
fi
# Test: Is bootjdk available from builddeps?
BOOTJDK_DO_CHECK([BOOTJDK_CHECK_BUILDDEPS])
# Test: On MacOS X, can we find a boot jdk using /usr/libexec/java_home?
BOOTJDK_DO_CHECK([BOOTJDK_CHECK_MACOSX_JAVA_LOCATOR])
@ -314,6 +305,16 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
AC_SUBST(BOOT_JDK_SOURCETARGET)
AC_SUBST(JAVAC_FLAGS)
# Check if the boot jdk is 32 or 64 bit
if "$JAVA" -d64 -version > /dev/null 2>&1; then
BOOT_JDK_BITS="64"
else
BOOT_JDK_BITS="32"
fi
AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
AC_MSG_RESULT([$BOOT_JDK_BITS])
AC_SUBST(BOOT_JDK_BITS)
])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
@ -350,7 +351,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
# Maximum amount of heap memory.
# Maximum stack size.
JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2`
if test "x$BUILD_NUM_BITS" = x32; then
if test "x$BOOT_JDK_BITS" = "x32"; then
if test "$JVM_MAX_HEAP" -gt "1100"; then
JVM_MAX_HEAP=1100
elif test "$JVM_MAX_HEAP" -lt "512"; then
@ -358,10 +359,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
fi
STACK_SIZE=768
else
# Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit
# pointers are used. Apparently, we need to increase the heap and stack
# space for the jvm. More specifically, when running javac to build huge
# jdk batch
# Running a 64 bit JVM allows for and requires a bigger heap
if test "$JVM_MAX_HEAP" -gt "1600"; then
JVM_MAX_HEAP=1600
elif test "$JVM_MAX_HEAP" -lt "512"; then

@ -328,12 +328,23 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC],
AC_ARG_ENABLE([sjavac], [AS_HELP_STRING([--enable-sjavac],
[use sjavac to do fast incremental compiles @<:@disabled@:>@])],
[ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC='no'])
[ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC="no"])
if test "x$JVM_ARG_OK" = "xfalse"; then
AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac])
ENABLE_SJAVAC=no;
ENABLE_SJAVAC="no"
fi
AC_MSG_CHECKING([whether to use sjavac])
AC_MSG_RESULT([$ENABLE_SJAVAC])
AC_SUBST(ENABLE_SJAVAC)
AC_ARG_ENABLE([javac-server], [AS_HELP_STRING([--enable-javac-server],
[use only the server part of sjavac for faster javac compiles @<:@disabled@:>@])],
[ENABLE_JAVAC_SERVER="${enableval}"], [ENABLE_JAVAC_SERVER="no"])
if test "x$JVM_ARG_OK" = "xfalse"; then
AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling javac server])
ENABLE_JAVAC_SERVER="no"
fi
AC_MSG_CHECKING([whether to use javac server])
AC_MSG_RESULT([$ENABLE_JAVAC_SERVER])
AC_SUBST(ENABLE_JAVAC_SERVER)
])

@ -1,66 +0,0 @@
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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.
#
# This is a configuration example using builddeps
# that are downloaded from an ftp server.
# This is how you use it:
#configure --with-builddeps-server=ftp://builddeps.server/adir \
# --with-builddeps-conf=..../builddeps.conf.example
# --with-builddeps-dir=/localdisk/mybuilddeps
# Translate a configuration triplet/quadruplet into something
# known by this configuration file.
# If no rewrite was found, then rewritten_target=${OPENJDK_TARGET_AUTOCONF_NAME}
REWRITE_i686_pc_linux_gnu=i686-unknown-linux-gnu
REWRITE_i386_pc_solaris2_10=i686-sun-solaris2_10
# The needed cups builddeps are platform independent header files.
# I.e. they need not be part of the devkit.
builddep_cups=lib/cups_1_3_9.zip
builddep_cups_CFLAGS=-I${depdir}
# The devkit is the cross compiler tools and sys-roots
# for the build platform.
builddep_devkit=sdk/sdk-${rewritten_build}-20110921.tar.gz
# The freetype dependency is partly platform dependent.
# It is stored inside the sys-root.
builddep_freetype2=sdk/sdk-${rewritten_build}-20110921.tar.gz
builddep_freetype2_CFLAGS=-I${depdir}/${rewritten_target}/sys-root/usr/include/freetype2
builddep_freetype2_LIBS=-lfreetype
# There are many other build dependencies, but they are implicitly
# found inside the devkit sys-root.
# The boot jdk runs on the build system and is used to compile and run
# Java build tools and of course, the bootstrap javac.
builddep_bootjdk_BUILD_i386_pc_solaris2=java/jdk-7u2-fcs-bin-b13-solaris-i586-17_nov_2011.zip
builddep_bootjdk_BUILD_x86_64_pc_solaris2=java/jdk-7u2-fcs-bin-b13-solaris-x64-17_nov_2011.zip
builddep_bootjdk_BUILD_i686_unknown_linux_gnu=java/jdk-7u2-fcs-bin-b13-linux-i586-17_nov_2011.zip
builddep_bootjdk_BUILD_x86_64_unknown_linux_gnu=java/jdk-7u2-fcs-bin-b13-linux-x64-17_nov_2011.zip
builddep_bootjdk_BUILD_sparc_solaris2=java/jdk-7u2-fcs-bin-b13-solaris-sparc-17_nov_2011.zip
builddep_bootjdk_BUILD_sparcv9_solaris2=java/jdk-7u2-fcs-bin-b13-solaris-sparcv9-17_nov_2011.zip
builddep_bootjdk_BUILD_i386_pc_windows=java/jdk-7u2-fcs-bin-b13-windows-i586-17_nov_2011.zip
builddep_bootjdk_BUILD_x86_64_pc_windows=java/jdk-7u2-fcs-bin-b13-windows-x64-17_nov_2011.zip
builddep_bootjdk_ROOT=${depdir}/jdk7_02/jdk1.7.0_02

@ -1,247 +0,0 @@
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
AC_DEFUN_ONCE([BDEPS_SCAN_FOR_BUILDDEPS],
[
define(LIST_OF_BUILD_DEPENDENCIES,)
if test "x$with_builddeps_server" != x || test "x$with_builddeps_conf" != x; then
if test "x$with_builddeps_conf" != x; then
AC_MSG_CHECKING([for supplied builddeps configuration file])
builddepsfile=$with_builddeps_conf
if test -s $builddepsfile; then
. $builddepsfile
AC_MSG_RESULT([loaded!])
else
AC_MSG_ERROR([The given builddeps conf file $with_builddeps_conf could not be loaded!])
fi
else
AC_MSG_CHECKING([for builddeps.conf files in sources...])
builddepsfile=`mktemp`
touch $builddepsfile
# Put all found confs into a single file.
find ${SRC_ROOT} -name builddeps.conf -exec cat \{\} \; >> $builddepsfile
# Source the file to acquire the variables
if test -s $builddepsfile; then
. $builddepsfile
AC_MSG_RESULT([found at least one!])
else
AC_MSG_ERROR([Could not find any builddeps.conf at all!])
fi
fi
# Create build and target names that use _ instead of "-" and ".".
# This is necessary to use them in variable names.
build_var=`echo ${OPENJDK_BUILD_AUTOCONF_NAME} | tr '-' '_' | tr '.' '_'`
target_var=`echo ${OPENJDK_TARGET_AUTOCONF_NAME} | tr '-' '_' | tr '.' '_'`
# Extract rewrite information for build and target
eval rewritten_build=\${REWRITE_${build_var}}
if test "x$rewritten_build" = x; then
rewritten_build=${OPENJDK_BUILD_AUTOCONF_NAME}
echo Build stays the same $rewritten_build
else
echo Rewriting build for builddeps into $rewritten_build
fi
eval rewritten_target=\${REWRITE_${target_var}}
if test "x$rewritten_target" = x; then
rewritten_target=${OPENJDK_TARGET_AUTOCONF_NAME}
echo Target stays the same $rewritten_target
else
echo Rewriting target for builddeps into $rewritten_target
fi
rewritten_build_var=`echo ${rewritten_build} | tr '-' '_' | tr '.' '_'`
rewritten_target_var=`echo ${rewritten_target} | tr '-' '_' | tr '.' '_'`
fi
AC_CHECK_PROGS(BDEPS_UNZIP, [7z unzip])
if test "x$BDEPS_UNZIP" = x7z; then
BDEPS_UNZIP="7z x"
fi
AC_CHECK_PROGS(BDEPS_FTP, [wget lftp ftp])
])
AC_DEFUN([BDEPS_FTPGET],
[
# $1 is the ftp://abuilddeps.server.com/libs/cups.zip
# $2 is the local file name for the downloaded file.
VALID_TOOL=no
if test "x$BDEPS_FTP" = xwget; then
VALID_TOOL=yes
wget -O $2 $1
fi
if test "x$BDEPS_FTP" = xlftp; then
VALID_TOOL=yes
lftp -c "get $1 -o $2"
fi
if test "x$BDEPS_FTP" = xftp; then
VALID_TOOL=yes
FTPSERVER=`echo $1 | cut -f 3 -d '/'`
FTPPATH=`echo $1 | cut -f 4- -d '/'`
FTPUSERPWD=${FTPSERVER%%@*}
if test "x$FTPSERVER" != "x$FTPUSERPWD"; then
FTPUSER=${userpwd%%:*}
FTPPWD=${userpwd#*@}
FTPSERVER=${FTPSERVER#*@}
else
FTPUSER=ftp
FTPPWD=ftp
fi
# the "pass" command does not work on some
# ftp clients (read ftp.exe) but if it works,
# passive mode is better!
( \
echo "user $FTPUSER $FTPPWD" ; \
echo "pass" ; \
echo "bin" ; \
echo "get $FTPPATH $2" ; \
) | ftp -in $FTPSERVER
fi
if test "x$VALID_TOOL" != xyes; then
AC_MSG_ERROR([I do not know how to use the tool: $BDEPS_FTP])
fi
])
AC_DEFUN([BDEPS_CHECK_MODULE],
[
define([LIST_OF_BUILD_DEPENDENCIES],LIST_OF_BUILD_DEPENDENCIES[$2=$3'\n'])
if test "x$with_builddeps_server" != x || test "x$with_builddeps_conf" != x; then
# Source the builddeps file again, to make sure it uses the latest variables!
. $builddepsfile
# Look for a target and build machine specific resource!
eval resource=\${builddep_$2_BUILD_${rewritten_build_var}_TARGET_${rewritten_target_var}}
if test "x$resource" = x; then
# Ok, lets instead look for a target specific resource
eval resource=\${builddep_$2_TARGET_${rewritten_target_var}}
fi
if test "x$resource" = x; then
# Ok, lets instead look for a build specific resource
eval resource=\${builddep_$2_BUILD_${rewritten_build_var}}
fi
if test "x$resource" = x; then
# Ok, lets instead look for a generic resource
# (The $2 comes from M4 and not the shell, thus no need for eval here.)
resource=${builddep_$2}
fi
if test "x$resource" != x; then
AC_MSG_NOTICE([Using builddeps $resource for $2])
# If the resource in the builddeps.conf file is an existing directory,
# for example /java/linux/cups
if test -d ${resource}; then
depdir=${resource}
else
BDEPS_FETCH($2, $resource, $with_builddeps_server, $with_builddeps_dir, depdir)
fi
# Source the builddeps file again, because in the previous command, the depdir
# was updated to point at the current build dependency install directory.
. $builddepsfile
# Now extract variables from the builddeps.conf files.
theroot=${builddep_$2_ROOT}
thecflags=${builddep_$2_CFLAGS}
thelibs=${builddep_$2_LIBS}
if test "x$depdir" = x; then
AC_MSG_ERROR([Could not download build dependency $2])
fi
$1=$depdir
if test "x$theroot" != x; then
$1="$theroot"
fi
if test "x$thecflags" != x; then
$1_CFLAGS="$thecflags"
fi
if test "x$thelibs" != x; then
$1_LIBS="$thelibs"
fi
m4_default([$4], [:])
m4_ifvaln([$5], [else $5])
fi
m4_ifvaln([$5], [else $5])
fi
])
AC_DEFUN([BDEPS_FETCH],
[
# $1 is for example mymodule
# $2 is for example libs/general/libmymod_1_2_3.zip
# $3 is for example ftp://mybuilddeps.myserver.com/builddeps
# $4 is for example /localhome/builddeps
# $5 is the name of the variable into which we store the depdir, eg MYMOD
# Will download ftp://mybuilddeps.myserver.com/builddeps/libs/general/libmymod_1_2_3.zip and
# unzip into the directory: /localhome/builddeps/libmymod_1_2_3
filename=`basename $2`
filebase=`echo $filename | sed 's/\.[[^\.]]*$//'`
filebase=${filename%%.*}
extension=${filename#*.}
installdir=$4/$filebase
if test ! -f $installdir/$filename.unpacked; then
AC_MSG_NOTICE([Downloading build dependency $1 from $3/$2 and installing into $installdir])
if test ! -d $installdir; then
mkdir -p $installdir
fi
if test ! -d $installdir; then
AC_MSG_ERROR([Could not create directory $installdir])
fi
tmpfile=`mktemp $installdir/$1.XXXXXXXXX`
touch $tmpfile
if test ! -f $tmpfile; then
AC_MSG_ERROR([Could not create files in directory $installdir])
fi
BDEPS_FTPGET([$3/$2] , [$tmpfile])
mv $tmpfile $installdir/$filename
if test ! -s $installdir/$filename; then
AC_MSG_ERROR([Could not download $3/$2])
fi
case "$extension" in
zip) echo "Unzipping $installdir/$filename..."
(cd $installdir ; rm -f $installdir/$filename.unpacked ; $BDEPS_UNZIP $installdir/$filename > /dev/null && touch $installdir/$filename.unpacked)
;;
tar.gz) echo "Untaring $installdir/$filename..."
(cd $installdir ; rm -f $installdir/$filename.unpacked ; tar xzf $installdir/$filename && touch $installdir/$filename.unpacked)
;;
tgz) echo "Untaring $installdir/$filename..."
(cd $installdir ; rm -f $installdir/$filename.unpacked ; tar xzf $installdir/$filename && touch $installdir/$filename.unpacked)
;;
*) AC_MSG_ERROR([Cannot handle build depency archive with extension $extension])
;;
esac
fi
if test -f $installdir/$filename.unpacked; then
$5=$installdir
fi
])
AC_DEFUN_ONCE([BDEPS_CONFIGURE_BUILDDEPS],
[
AC_ARG_WITH(builddeps-conf, [AS_HELP_STRING([--with-builddeps-conf],
[use this configuration file for the builddeps])])
AC_ARG_WITH(builddeps-server, [AS_HELP_STRING([--with-builddeps-server],
[download and use build dependencies from this server url])])
AC_ARG_WITH(builddeps-dir, [AS_HELP_STRING([--with-builddeps-dir],
[store downloaded build dependencies here @<:@/localhome/builddeps@:>@])],
[],
[with_builddeps_dir=/localhome/builddeps])
AC_ARG_WITH(builddeps-group, [AS_HELP_STRING([--with-builddeps-group],
[chgrp the downloaded build dependencies to this group])])
])

@ -66,7 +66,7 @@ export STRIP="@STRIP@ @STRIPFLAGS@"
export TEE="@TEE@"
export UNIQ="@UNIQ@"
export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
export UNZIP="@UNZIP@"
export UNARCHIVE="@UNZIP@ -q"
export SRC_ROOT="@TOPDIR@"
export OUTPUT_ROOT="@OUTPUT_ROOT@"

@ -39,7 +39,6 @@ m4_include([build-aux/pkg.m4])
# Include these first...
m4_include([basics.m4])
m4_include([basics_windows.m4])
m4_include([builddeps.m4])
# ... then the rest
m4_include([boot-jdk.m4])
m4_include([build-performance.m4])
@ -121,12 +120,6 @@ PKG_PROG_PKG_CONFIG
# After basic tools have been setup, we can check build os specific details.
PLATFORM_SETUP_OPENJDK_BUILD_OS_VERSION
# Setup builddeps, for automatic downloading of tools we need.
# This is needed before we can call BDEPS_CHECK_MODULE, which is done in
# boot-jdk setup, but we need to have basic tools setup first.
BDEPS_CONFIGURE_BUILDDEPS
BDEPS_SCAN_FOR_BUILDDEPS
###############################################################################
#
# Determine OpenJDK variants, options and version numbers.
@ -211,14 +204,8 @@ JDKOPT_SETUP_CODE_COVERAGE
# After we have toolchain, we can compile fixpath. It's needed by the lib checks.
BASIC_COMPILE_FIXPATH
LIB_SETUP_INIT
LIB_SETUP_X11
LIB_SETUP_CUPS
LIB_SETUP_FREETYPE
LIB_SETUP_ALSA
LIB_SETUP_MISC_LIBS
LIB_SETUP_STATIC_LINK_LIBSTDCPP
LIB_SETUP_ON_WINDOWS
LIB_DETERMINE_DEPENDENCIES
LIB_SETUP_LIBRARIES
###############################################################################
#

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2015, 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,7 +31,7 @@ AC_DEFUN_ONCE([HELP_SETUP_DEPENDENCY_HELP],
AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY],
[
# Print a helpful message on how to acquire the necessary build dependency.
# $1 is the help tag: freetype, cups, pulse, alsa etc
# $1 is the help tag: freetype, cups, alsa etc
MISSING_DEPENDENCY=$1
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@ -109,8 +109,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;;
freetype)
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
pulse)
PKGHANDLER_COMMAND="sudo apt-get install libpulse-dev" ;;
ffi)
PKGHANDLER_COMMAND="sudo apt-get install libffi-dev" ;;
x11)
PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;;
ccache)
@ -130,8 +130,6 @@ yum_help() {
PKGHANDLER_COMMAND="sudo yum install cups-devel" ;;
freetype)
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
pulse)
PKGHANDLER_COMMAND="sudo yum install pulseaudio-libs-devel" ;;
x11)
PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel libXi-devel" ;;
ccache)

@ -0,0 +1,90 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Setup alsa (Advanced Linux Sound Architecture)
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_ALSA],
[
AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa],
[specify prefix directory for the alsa package
(expecting the libraries under PATH/lib and the headers under PATH/include)])])
AC_ARG_WITH(alsa-include, [AS_HELP_STRING([--with-alsa-include],
[specify directory for the alsa include files])])
AC_ARG_WITH(alsa-lib, [AS_HELP_STRING([--with-alsa-lib],
[specify directory for the alsa library])])
if test "x$NEEDS_LIB_ALSA" = xfalse; then
if test "x${with_alsa}" != x || test "x${with_alsa_include}" != x || test "x${with_alsa_lib}" != x; then
AC_MSG_WARN([alsa not used, so --with-alsa is ignored])
fi
ALSA_CFLAGS=
ALSA_LIBS=
else
ALSA_FOUND=no
if test "x${with_alsa}" = xno || test "x${with_alsa_include}" = xno || test "x${with_alsa_lib}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of alsa. Remove the --without-alsa option.])
fi
if test "x${with_alsa}" != x; then
ALSA_LIBS="-L${with_alsa}/lib -lasound"
ALSA_CFLAGS="-I${with_alsa}/include"
ALSA_FOUND=yes
fi
if test "x${with_alsa_include}" != x; then
ALSA_CFLAGS="-I${with_alsa_include}"
ALSA_FOUND=yes
fi
if test "x${with_alsa_lib}" != x; then
ALSA_LIBS="-L${with_alsa_lib} -lasound"
ALSA_FOUND=yes
fi
# Do not try pkg-config if we have a sysroot set.
if test "x$SYSROOT" = x; then
if test "x$ALSA_FOUND" = xno; then
PKG_CHECK_MODULES(ALSA, alsa, [ALSA_FOUND=yes], [ALSA_FOUND=no])
fi
fi
if test "x$ALSA_FOUND" = xno; then
AC_CHECK_HEADERS([alsa/asoundlib.h],
[
ALSA_FOUND=yes
ALSA_CFLAGS=-Iignoreme
ALSA_LIBS=-lasound
DEFAULT_ALSA=yes
],
[ALSA_FOUND=no]
)
fi
if test "x$ALSA_FOUND" = xno; then
HELP_MSG_MISSING_DEPENDENCY([alsa])
AC_MSG_ERROR([Could not find alsa! $HELP_MSG])
fi
fi
AC_SUBST(ALSA_CFLAGS)
AC_SUBST(ALSA_LIBS)
])

@ -0,0 +1,226 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Setup bundled libraries.
#
# For libjpeg, giflib, libpng, lcms2 and zlib, the source is present in the
# OpenJDK repository. Default is to use these libraries as bundled, but they
# might be replaced by en external version by the user.
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_BUNDLED_LIBS],
[
LIB_SETUP_LIBJPEG
LIB_SETUP_GIFLIB
LIB_SETUP_LIBPNG
LIB_SETUP_ZLIB
LIB_SETUP_LCMS
])
################################################################################
# Setup libjpeg
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_LIBJPEG],
[
AC_ARG_WITH(libjpeg, [AS_HELP_STRING([--with-libjpeg],
[use libjpeg from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
AC_MSG_CHECKING([for which libjpeg to use])
# default is bundled
DEFAULT_LIBJPEG=bundled
# if user didn't specify, use DEFAULT_LIBJPEG
if test "x${with_libjpeg}" = "x"; then
with_libjpeg=${DEFAULT_LIBJPEG}
fi
AC_MSG_RESULT(${with_libjpeg})
if test "x${with_libjpeg}" = "xbundled"; then
USE_EXTERNAL_LIBJPEG=false
elif test "x${with_libjpeg}" = "xsystem"; then
AC_CHECK_HEADER(jpeglib.h, [],
[ AC_MSG_ERROR([--with-libjpeg=system specified, but jpeglib.h not found!])])
AC_CHECK_LIB(jpeg, jpeg_CreateDecompress, [],
[ AC_MSG_ERROR([--with-libjpeg=system specified, but no libjpeg found])])
USE_EXTERNAL_LIBJPEG=true
else
AC_MSG_ERROR([Invalid use of --with-libjpeg: ${with_libjpeg}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBJPEG)
])
################################################################################
# Setup giflib
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_GIFLIB],
[
AC_ARG_WITH(giflib, [AS_HELP_STRING([--with-giflib],
[use giflib from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
AC_MSG_CHECKING([for which giflib to use])
# default is bundled
DEFAULT_GIFLIB=bundled
# if user didn't specify, use DEFAULT_GIFLIB
if test "x${with_giflib}" = "x"; then
with_giflib=${DEFAULT_GIFLIB}
fi
AC_MSG_RESULT(${with_giflib})
if test "x${with_giflib}" = "xbundled"; then
USE_EXTERNAL_LIBGIF=false
elif test "x${with_giflib}" = "xsystem"; then
AC_CHECK_HEADER(gif_lib.h, [],
[ AC_MSG_ERROR([--with-giflib=system specified, but gif_lib.h not found!])])
AC_CHECK_LIB(gif, DGifGetCode, [],
[ AC_MSG_ERROR([--with-giflib=system specified, but no giflib found!])])
USE_EXTERNAL_LIBGIF=true
else
AC_MSG_ERROR([Invalid value of --with-giflib: ${with_giflib}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBGIF)
])
################################################################################
# Setup libpng
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_LIBPNG],
[
AC_ARG_WITH(libpng, [AS_HELP_STRING([--with-libpng],
[use libpng from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
AC_MSG_CHECKING([for which libpng to use])
# default is bundled
DEFAULT_LIBPNG=bundled
# if user didn't specify, use DEFAULT_LIBPNG
if test "x${with_libpng}" = "x"; then
with_libpng=${DEFAULT_LIBPNG}
fi
if test "x${with_libpng}" = "xbundled"; then
USE_EXTERNAL_LIBPNG=false
AC_MSG_RESULT([bundled])
elif test "x${with_libpng}" = "xsystem"; then
PKG_CHECK_MODULES(PNG, libpng,
[ LIBPNG_FOUND=yes ],
[ LIBPNG_FOUND=no ])
if test "x${LIBPNG_FOUND}" = "xyes"; then
USE_EXTERNAL_LIBPNG=true
AC_MSG_RESULT([system])
else
AC_MSG_RESULT([system not found])
AC_MSG_ERROR([--with-libpng=system specified, but no libpng found!])
fi
else
AC_MSG_ERROR([Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBPNG)
])
################################################################################
# Setup zlib
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_ZLIB],
[
AC_ARG_WITH(zlib, [AS_HELP_STRING([--with-zlib],
[use zlib from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
AC_CHECK_LIB(z, compress,
[ ZLIB_FOUND=yes ],
[ ZLIB_FOUND=no ])
AC_MSG_CHECKING([for which zlib to use])
DEFAULT_ZLIB=bundled
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
# On macosx default is system...on others default is bundled
DEFAULT_ZLIB=system
fi
if test "x${ZLIB_FOUND}" != "xyes"; then
# If we don't find any system...set default to bundled
DEFAULT_ZLIB=bundled
fi
# If user didn't specify, use DEFAULT_ZLIB
if test "x${with_zlib}" = "x"; then
with_zlib=${DEFAULT_ZLIB}
fi
if test "x${with_zlib}" = "xbundled"; then
USE_EXTERNAL_LIBZ=false
AC_MSG_RESULT([bundled])
elif test "x${with_zlib}" = "xsystem"; then
if test "x${ZLIB_FOUND}" = "xyes"; then
USE_EXTERNAL_LIBZ=true
AC_MSG_RESULT([system])
else
AC_MSG_RESULT([system not found])
AC_MSG_ERROR([--with-zlib=system specified, but no zlib found!])
fi
else
AC_MSG_ERROR([Invalid value for --with-zlib: ${with_zlib}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBZ)
])
################################################################################
# Setup lcms (Little CMS)
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_LCMS],
[
AC_ARG_WITH(lcms, [AS_HELP_STRING([--with-lcms],
[use lcms2 from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
AC_MSG_CHECKING([for which lcms to use])
DEFAULT_LCMS=bundled
# If user didn't specify, use DEFAULT_LCMS
if test "x${with_lcms}" = "x"; then
with_lcms=${DEFAULT_LCMS}
fi
if test "x${with_lcms}" = "xbundled"; then
USE_EXTERNAL_LCMS=false
AC_MSG_RESULT([bundled])
elif test "x${with_lcms}" = "xsystem"; then
AC_MSG_RESULT([system])
PKG_CHECK_MODULES([LCMS], [lcms2], [LCMS_FOUND=yes], [LCMS_FOUND=no])
if test "x${LCMS_FOUND}" = "xyes"; then
USE_EXTERNAL_LCMS=true
else
AC_MSG_ERROR([--with-lcms=system specified, but no lcms found!])
fi
else
AC_MSG_ERROR([Invalid value for --with-lcms: ${with_lcms}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LCMS)
])

@ -0,0 +1,87 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Setup cups (Common Unix Printing System)
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_CUPS],
[
AC_ARG_WITH(cups, [AS_HELP_STRING([--with-cups],
[specify prefix directory for the cups package
(expecting the headers under PATH/include)])])
AC_ARG_WITH(cups-include, [AS_HELP_STRING([--with-cups-include],
[specify directory for the cups include files])])
if test "x$NEEDS_LIB_CUPS" = xfalse; then
if test "x${with_cups}" != x || test "x${with_cups_include}" != x; then
AC_MSG_WARN([cups not used, so --with-cups is ignored])
fi
CUPS_CFLAGS=
else
CUPS_FOUND=no
if test "x${with_cups}" = xno || test "x${with_cups_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of cups. Remove the --without-cups option.])
fi
if test "x${with_cups}" != x; then
CUPS_CFLAGS="-I${with_cups}/include"
CUPS_FOUND=yes
fi
if test "x${with_cups_include}" != x; then
CUPS_CFLAGS="-I${with_cups_include}"
CUPS_FOUND=yes
fi
if test "x$CUPS_FOUND" = xno; then
# Are the cups headers installed in the default /usr/include location?
AC_CHECK_HEADERS([cups/cups.h cups/ppd.h], [
CUPS_FOUND=yes
CUPS_CFLAGS=
DEFAULT_CUPS=yes
])
fi
if test "x$CUPS_FOUND" = xno; then
# Getting nervous now? Lets poke around for standard Solaris third-party
# package installation locations.
AC_MSG_CHECKING([for cups headers])
if test -s $SYSROOT/opt/sfw/cups/include/cups/cups.h; then
# An SFW package seems to be installed!
CUPS_FOUND=yes
CUPS_CFLAGS="-I$SYSROOT/opt/sfw/cups/include"
elif test -s $SYSROOT/opt/csw/include/cups/cups.h; then
# A CSW package seems to be installed!
CUPS_FOUND=yes
CUPS_CFLAGS="-I$SYSROOT/opt/csw/include"
fi
AC_MSG_RESULT([$CUPS_FOUND])
fi
if test "x$CUPS_FOUND" = xno; then
HELP_MSG_MISSING_DEPENDENCY([cups])
AC_MSG_ERROR([Could not find cups! $HELP_MSG ])
fi
fi
AC_SUBST(CUPS_CFLAGS)
])

114
common/autoconf/lib-ffi.m4 Normal file

@ -0,0 +1,114 @@
#
# Copyright (c) 2015, 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.
#
################################################################################
# Setup libffi (Foreign Function Interface)
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
[
AC_ARG_WITH(libffi, [AS_HELP_STRING([--with-libffi],
[specify prefix directory for the libffi package
(expecting the libraries under PATH/lib and the headers under PATH/include)])])
AC_ARG_WITH(libffi-include, [AS_HELP_STRING([--with-libffi-include],
[specify directory for the libffi include files])])
AC_ARG_WITH(libffi-lib, [AS_HELP_STRING([--with-libffi-lib],
[specify directory for the libffi library])])
if test "x$NEEDS_LIB_FFI" = xfalse; then
if test "x${with_libffi}" != x || test "x${with_libffi_include}" != x || test "x${with_libffi_lib}" != x; then
AC_MSG_WARN([libffi not used, so --with-libffi is ignored])
fi
LIBFFI_CFLAGS=
LIBFFI_LIBS=
else
LIBFFI_FOUND=no
if test "x${with_libffi}" = xno || test "x${with_libffi_include}" = xno || test "x${with_libffi_lib}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of libffi. Remove the --without-libffi option.])
fi
if test "x${with_libffi}" != x; then
LIBFFI_LIBS="-L${with_libffi}/lib -lffi"
LIBFFI_CFLAGS="-I${with_libffi}/include"
LIBFFI_FOUND=yes
fi
if test "x${with_libffi_include}" != x; then
LIBFFI_CFLAGS="-I${with_libffi_include}"
LIBFFI_FOUND=yes
fi
if test "x${with_libffi_lib}" != x; then
LIBFFI_LIBS="-L${with_libffi_lib} -lffi"
LIBFFI_FOUND=yes
fi
# Do not try pkg-config if we have a sysroot set.
if test "x$SYSROOT" = x; then
if test "x$LIBFFI_FOUND" = xno; then
# Figure out LIBFFI_CFLAGS and LIBFFI_LIBS
PKG_CHECK_MODULES([LIBFFI], [libffi], [LIBFFI_FOUND=yes], [LIBFFI_FOUND=no])
fi
fi
if test "x$LIBFFI_FOUND" = xno; then
AC_CHECK_HEADERS([ffi.h],
[
LIBFFI_FOUND=yes
LIBFFI_CFLAGS=
LIBFFI_LIBS=-lffi
],
[LIBFFI_FOUND=no]
)
fi
if test "x$LIBFFI_FOUND" = xno; then
HELP_MSG_MISSING_DEPENDENCY([ffi])
AC_MSG_ERROR([Could not find libffi! $HELP_MSG])
fi
AC_MSG_CHECKING([if libffi works])
AC_LANG_PUSH(C)
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $LIBFFI_CFLAGS"
OLD_LIBS="$LIBS"
LIBS="$LIBS $LIBFFI_LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <ffi.h>],
[
ffi_call(NULL, NULL, NULL, NULL);
return 0;
])],
[LIBFFI_WORKS=yes],
[LIBFFI_WORKS=no]
)
CFLAGS="$OLD_CFLAGS"
LIBS="$OLD_LIBS"
AC_LANG_POP(C)
AC_MSG_RESULT([$LIBFFI_WORKS])
if test "x$LIBFFI_WORKS" = xno; then
HELP_MSG_MISSING_DEPENDENCY([ffi])
AC_MSG_ERROR([Found libffi but could not link and compile with it. $HELP_MSG])
fi
fi
AC_SUBST(LIBFFI_CFLAGS)
AC_SUBST(LIBFFI_LIBS)
])

@ -0,0 +1,420 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Build the freetype lib from source
################################################################################
AC_DEFUN([LIB_BUILD_FREETYPE],
[
FREETYPE_SRC_PATH="$1"
BUILD_FREETYPE=yes
# Check if the freetype sources are acessible..
if ! test -d $FREETYPE_SRC_PATH; then
AC_MSG_WARN([--with-freetype-src specified, but can not find path "$FREETYPE_SRC_PATH" - ignoring --with-freetype-src])
BUILD_FREETYPE=no
fi
# ..and contain a vc2010 project file
vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj"
if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then
AC_MSG_WARN([Can not find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src])
BUILD_FREETYPE=no
fi
# Now check if configure found a version of 'msbuild.exe'
if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then
AC_MSG_WARN([Can not find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src])
BUILD_FREETYPE=no
fi
# Ready to go..
if test "x$BUILD_FREETYPE" = xyes; then
# msbuild requires trailing slashes for output directories
freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/"
freetype_lib_path_unix="$freetype_lib_path"
freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/"
BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(vcxproj_path)
BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_lib_path)
BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_obj_path)
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
freetype_platform=x64
else
freetype_platform=win32
fi
# The original freetype project file is for VS 2010 (i.e. 'v100'),
# so we have to adapt the toolset if building with any other toolsed (i.e. SDK).
# Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/
# 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4
AC_MSG_NOTICE([Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ...])
# First we try to build the freetype.dll
$ECHO -e "@echo off\n"\
"$MSBUILD $vcxproj_path "\
"/p:PlatformToolset=$PLATFORM_TOOLSET "\
"/p:Configuration=\"Release Multithreaded\" "\
"/p:Platform=$freetype_platform "\
"/p:ConfigurationType=DynamicLibrary "\
"/p:TargetName=freetype "\
"/p:OutDir=\"$freetype_lib_path\" "\
"/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat
cmd /c freetype.bat
if test -s "$freetype_lib_path_unix/freetype.dll"; then
# If that succeeds we also build freetype.lib
$ECHO -e "@echo off\n"\
"$MSBUILD $vcxproj_path "\
"/p:PlatformToolset=$PLATFORM_TOOLSET "\
"/p:Configuration=\"Release Multithreaded\" "\
"/p:Platform=$freetype_platform "\
"/p:ConfigurationType=StaticLibrary "\
"/p:TargetName=freetype "\
"/p:OutDir=\"$freetype_lib_path\" "\
"/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat
cmd /c freetype.bat
if test -s "$freetype_lib_path_unix/freetype.lib"; then
# Once we build both, lib and dll, set freetype lib and include path appropriately
POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include"
POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix"
AC_MSG_NOTICE([Compiling freetype sources succeeded! (see freetype.log for build results)])
else
BUILD_FREETYPE=no
fi
else
BUILD_FREETYPE=no
fi
fi
])
################################################################################
# Check if a potential freeype library match is correct and usable
################################################################################
AC_DEFUN([LIB_CHECK_POTENTIAL_FREETYPE],
[
POTENTIAL_FREETYPE_INCLUDE_PATH="$1"
POTENTIAL_FREETYPE_LIB_PATH="$2"
METHOD="$3"
# Let's start with an optimistic view of the world :-)
FOUND_FREETYPE=yes
# First look for the canonical freetype main include file ft2build.h.
if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
# Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
# Fail.
FOUND_FREETYPE=no
fi
fi
if test "x$FOUND_FREETYPE" = xyes; then
# Include file found, let's continue the sanity check.
AC_MSG_NOTICE([Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD])
# Reset to default value
FREETYPE_BASE_NAME=freetype
FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
if test "x$OPENJDK_TARGET_OS" = xmacosx \
&& test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
# On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
# for the .6 version explicitly.
FREETYPE_BASE_NAME=freetype.6
FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
AC_MSG_NOTICE([Compensating for missing symlink by using version 6 explicitly])
else
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location.])
FOUND_FREETYPE=no
fi
else
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# On Windows, we will need both .lib and .dll file.
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location.])
FOUND_FREETYPE=no
fi
elif test "x$OPENJDK_TARGET_OS" = xsolaris \
&& test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
# Found lib in isa dir, use that instead.
POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
AC_MSG_NOTICE([Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead])
fi
fi
fi
if test "x$FOUND_FREETYPE" = xyes; then
BASIC_FIXUP_PATH(POTENTIAL_FREETYPE_INCLUDE_PATH)
BASIC_FIXUP_PATH(POTENTIAL_FREETYPE_LIB_PATH)
FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
AC_MSG_CHECKING([for freetype includes])
AC_MSG_RESULT([$FREETYPE_INCLUDE_PATH])
FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
AC_MSG_CHECKING([for freetype libraries])
AC_MSG_RESULT([$FREETYPE_LIB_PATH])
fi
])
################################################################################
# Setup freetype (The FreeType2 font rendering library)
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
[
AC_ARG_WITH(freetype, [AS_HELP_STRING([--with-freetype],
[specify prefix directory for the freetype package
(expecting the libraries under PATH/lib and the headers under PATH/include)])])
AC_ARG_WITH(freetype-include, [AS_HELP_STRING([--with-freetype-include],
[specify directory for the freetype include files])])
AC_ARG_WITH(freetype-lib, [AS_HELP_STRING([--with-freetype-lib],
[specify directory for the freetype library])])
AC_ARG_WITH(freetype-src, [AS_HELP_STRING([--with-freetype-src],
[specify directory with freetype sources to automatically build the library (experimental, Windows-only)])])
AC_ARG_ENABLE(freetype-bundling, [AS_HELP_STRING([--disable-freetype-bundling],
[disable bundling of the freetype library with the build result @<:@enabled on Windows or when using --with-freetype, disabled otherwise@:>@])])
# Need to specify explicitly since it needs to be overridden on some versions of macosx
FREETYPE_BASE_NAME=freetype
FREETYPE_CFLAGS=
FREETYPE_LIBS=
FREETYPE_BUNDLE_LIB_PATH=
if test "x$NEEDS_LIB_FREETYPE" = xfalse; then
if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then
AC_MSG_WARN([freetype not used, so --with-freetype is ignored])
fi
if test "x$enable_freetype_bundling" != x; then
AC_MSG_WARN([freetype not used, so --enable-freetype-bundling is ignored])
fi
else
# freetype is needed to build; go get it!
BUNDLE_FREETYPE="$enable_freetype_bundling"
if test "x$with_freetype_src" != x; then
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# Try to build freetype if --with-freetype-src was given on Windows
LIB_BUILD_FREETYPE([$with_freetype_src])
if test "x$BUILD_FREETYPE" = xyes; then
# Okay, we built it. Check that it works.
LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH, $POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype-src])
if test "x$FOUND_FREETYPE" != xyes; then
AC_MSG_ERROR([Can not use the built freetype at location given by --with-freetype-src])
fi
else
AC_MSG_NOTICE([User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)])
AC_MSG_ERROR([Consider building freetype manually and using --with-freetype instead.])
fi
else
AC_MSG_WARN([--with-freetype-src is currently only supported on Windows - ignoring])
fi
fi
if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then
# User has specified settings
if test "x$BUNDLE_FREETYPE" = x; then
# If not specified, default is to bundle freetype
BUNDLE_FREETYPE=yes
fi
if test "x$with_freetype" != x; then
POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype/include"
POTENTIAL_FREETYPE_LIB_PATH="$with_freetype/lib"
fi
# Allow --with-freetype-lib and --with-freetype-include to override
if test "x$with_freetype_include" != x; then
POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype_include"
fi
if test "x$with_freetype_lib" != x; then
POTENTIAL_FREETYPE_LIB_PATH="$with_freetype_lib"
fi
if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x && test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
# Okay, we got it. Check that it works.
LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH, $POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype])
if test "x$FOUND_FREETYPE" != xyes; then
AC_MSG_ERROR([Can not find or use freetype at location given by --with-freetype])
fi
else
# User specified only one of lib or include. This is an error.
if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" = x ; then
AC_MSG_NOTICE([User specified --with-freetype-lib but not --with-freetype-include])
AC_MSG_ERROR([Need both freetype lib and include paths. Consider using --with-freetype instead.])
else
AC_MSG_NOTICE([User specified --with-freetype-include but not --with-freetype-lib])
AC_MSG_ERROR([Need both freetype lib and include paths. Consider using --with-freetype instead.])
fi
fi
else
# User did not specify settings, but we need freetype. Try to locate it.
if test "x$BUNDLE_FREETYPE" = x; then
# If not specified, default is to bundle freetype only on windows
if test "x$OPENJDK_TARGET_OS" = xwindows; then
BUNDLE_FREETYPE=yes
else
BUNDLE_FREETYPE=no
fi
fi
# If we have a sysroot, assume that's where we are supposed to look and skip pkg-config.
if test "x$SYSROOT" = x; then
if test "x$FOUND_FREETYPE" != xyes; then
# Check modules using pkg-config, but only if we have it (ugly output results otherwise)
if test "x$PKG_CONFIG" != x; then
PKG_CHECK_MODULES(FREETYPE, freetype2, [FOUND_FREETYPE=yes], [FOUND_FREETYPE=no])
if test "x$FOUND_FREETYPE" = xyes; then
# On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
# 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$OPENJDK_TARGET_CPU" = xx86_64; then
FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
fi
# PKG_CHECK_MODULES will set FREETYPE_CFLAGS and _LIBS, but we don't get a lib path for bundling.
if test "x$BUNDLE_FREETYPE" = xyes; then
AC_MSG_NOTICE([Found freetype using pkg-config, but ignoring since we can not bundle that])
FOUND_FREETYPE=no
else
AC_MSG_CHECKING([for freetype])
AC_MSG_RESULT([yes (using pkg-config)])
fi
fi
fi
fi
fi
if test "x$FOUND_FREETYPE" != xyes; then
# Check in well-known locations
if test "x$OPENJDK_TARGET_OS" = xwindows; then
FREETYPE_BASE_DIR="$PROGRAMFILES/GnuWin32"
BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(FREETYPE_BASE_DIR)
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
if test "x$FOUND_FREETYPE" != xyes; then
FREETYPE_BASE_DIR="$ProgramW6432/GnuWin32"
BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(FREETYPE_BASE_DIR)
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
else
FREETYPE_BASE_DIR="$SYSROOT/usr"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
if test "x$FOUND_FREETYPE" != xyes; then
FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if test "x$FOUND_FREETYPE" != xyes; then
FREETYPE_BASE_DIR="$SYSROOT/usr/sfw"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if test "x$FOUND_FREETYPE" != xyes; then
FREETYPE_BASE_DIR="$SYSROOT/usr"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/x86_64-linux-gnu], [well-known location])
else
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/i386-linux-gnu], [well-known location])
if test "x$FOUND_FREETYPE" != xyes; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib32], [well-known location])
fi
fi
fi
fi
fi # end check in well-known locations
if test "x$FOUND_FREETYPE" != xyes; then
HELP_MSG_MISSING_DEPENDENCY([freetype])
AC_MSG_ERROR([Could not find freetype! $HELP_MSG ])
fi
fi # end user specified settings
# Set FREETYPE_CFLAGS, _LIBS and _LIB_PATH from include and lib dir.
if test "x$FREETYPE_CFLAGS" = x; then
BASIC_FIXUP_PATH(FREETYPE_INCLUDE_PATH)
if test -d $FREETYPE_INCLUDE_PATH/freetype2/freetype; then
FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH/freetype2 -I$FREETYPE_INCLUDE_PATH"
else
FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH"
fi
fi
if test "x$FREETYPE_LIBS" = x; then
BASIC_FIXUP_PATH(FREETYPE_LIB_PATH)
if test "x$OPENJDK_TARGET_OS" = xwindows; then
FREETYPE_LIBS="$FREETYPE_LIB_PATH/$FREETYPE_BASE_NAME.lib"
else
FREETYPE_LIBS="-L$FREETYPE_LIB_PATH -l$FREETYPE_BASE_NAME"
fi
fi
# Try to compile it
AC_MSG_CHECKING([if we can compile and link with freetype])
AC_LANG_PUSH(C++)
PREV_CXXCFLAGS="$CXXFLAGS"
PREV_LIBS="$LIBS"
PREV_CXX="$CXX"
CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS"
LIBS="$LIBS $FREETYPE_LIBS"
CXX="$FIXPATH $CXX"
AC_LINK_IFELSE([AC_LANG_SOURCE([[
#include<ft2build.h>
#include FT_FREETYPE_H
int main () {
FT_Init_FreeType(NULL);
return 0;
}
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
AC_MSG_NOTICE([Could not compile and link with freetype. This might be a 32/64-bit mismatch.])
AC_MSG_NOTICE([Using FREETYPE_CFLAGS=$FREETYPE_CFLAGS and FREETYPE_LIBS=$FREETYPE_LIBS])
HELP_MSG_MISSING_DEPENDENCY([freetype])
AC_MSG_ERROR([Can not continue without freetype. $HELP_MSG])
]
)
CXXCFLAGS="$PREV_CXXFLAGS"
LIBS="$PREV_LIBS"
CXX="$PREV_CXX"
AC_LANG_POP(C++)
AC_MSG_CHECKING([if we should bundle freetype])
if test "x$BUNDLE_FREETYPE" = xyes; then
FREETYPE_BUNDLE_LIB_PATH="$FREETYPE_LIB_PATH"
fi
AC_MSG_RESULT([$BUNDLE_FREETYPE])
fi # end freetype needed
AC_SUBST(FREETYPE_BUNDLE_LIB_PATH)
AC_SUBST(FREETYPE_CFLAGS)
AC_SUBST(FREETYPE_LIBS)
])

120
common/autoconf/lib-std.m4 Normal file

@ -0,0 +1,120 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Setup the standard C/C++ runtime libraries.
#
# Most importantly, determine if stdc++ should be linked statically or
# dynamically.
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS],
[
# statically link libstdc++ before C++ ABI is stablized on Linux unless
# dynamic build is configured on command line.
AC_ARG_WITH([stdc++lib], [AS_HELP_STRING([--with-stdc++lib=<static>,<dynamic>,<default>],
[force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as fallback])],
[
if test "x$with_stdc__lib" != xdynamic && test "x$with_stdc__lib" != xstatic \
&& test "x$with_stdc__lib" != xdefault; then
AC_MSG_ERROR([Bad parameter value --with-stdc++lib=$with_stdc__lib!])
fi
],
[with_stdc__lib=default]
)
if test "x$OPENJDK_TARGET_OS" = xlinux; then
# Test if -lstdc++ works.
AC_MSG_CHECKING([if dynamic link of stdc++ is possible])
AC_LANG_PUSH(C++)
OLD_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -lstdc++"
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
[has_dynamic_libstdcxx=yes],
[has_dynamic_libstdcxx=no])
CXXFLAGS="$OLD_CXXFLAGS"
AC_LANG_POP(C++)
AC_MSG_RESULT([$has_dynamic_libstdcxx])
# Test if stdc++ can be linked statically.
AC_MSG_CHECKING([if static link of stdc++ is possible])
STATIC_STDCXX_FLAGS="-Wl,-Bstatic -lstdc++ -lgcc -Wl,-Bdynamic"
AC_LANG_PUSH(C++)
OLD_LIBS="$LIBS"
OLD_CXX="$CXX"
LIBS="$STATIC_STDCXX_FLAGS"
CXX="$CC"
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
[has_static_libstdcxx=yes],
[has_static_libstdcxx=no])
LIBS="$OLD_LIBS"
CXX="$OLD_CXX"
AC_LANG_POP(C++)
AC_MSG_RESULT([$has_static_libstdcxx])
if test "x$has_static_libstdcxx" = xno && test "x$has_dynamic_libstdcxx" = xno; then
AC_MSG_ERROR([Cannot link to stdc++, neither dynamically nor statically!])
fi
if test "x$with_stdc__lib" = xstatic && test "x$has_static_libstdcxx" = xno; then
AC_MSG_ERROR([Static linking of libstdc++ was not possible!])
fi
if test "x$with_stdc__lib" = xdynamic && test "x$has_dynamic_libstdcxx" = xno; then
AC_MSG_ERROR([Dynamic linking of libstdc++ was not possible!])
fi
# If dynamic was requested, it's available since it would fail above otherwise.
# If dynamic wasn't requested, go with static unless it isn't available.
AC_MSG_CHECKING([how to link with libstdc++])
if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then
LIBCXX="$LIBCXX -lstdc++"
LDCXX="$CXX"
STATIC_CXX_SETTING="STATIC_CXX=false"
AC_MSG_RESULT([dynamic])
else
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
LDCXX="$CC"
STATIC_CXX_SETTING="STATIC_CXX=true"
AC_MSG_RESULT([static])
fi
fi
AC_SUBST(STATIC_CXX_SETTING)
# libCrun is the c++ runtime-library with SunStudio (roughly the equivalent of gcc's libstdc++.so)
if test "x$TOOLCHAIN_TYPE" = xsolstudio && test "x$LIBCXX" = x; then
LIBCXX="${SYSROOT}/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1"
fi
# TODO better (platform agnostic) test
if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$TOOLCHAIN_TYPE" = xgcc; then
LIBCXX="-lstdc++"
fi
AC_SUBST(LIBCXX)
# Setup Windows runtime dlls
if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
TOOLCHAIN_SETUP_VS_RUNTIME_DLLS
fi
])

135
common/autoconf/lib-x11.m4 Normal file

@ -0,0 +1,135 @@
#
# Copyright (c) 2011, 2015, 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.
#
################################################################################
# Setup X11 Windows system
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_X11],
[
if test "x$NEEDS_LIB_X11" = xfalse; then
if test "x${with_x}" != x; then
AC_MSG_WARN([X11 is not used, so --with-x is ignored])
fi
X_CFLAGS=
X_LIBS=
else
if test "x${with_x}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of X11. Remove the --without-x option.])
fi
if test "x${with_x}" != x && test "x${with_x}" != xyes; then
# The user has specified a X11 base directory. Use it for includes and
# libraries, unless explicitely overridden.
if test "x$x_includes" = xNONE; then
x_includes="${with_x}/include"
fi
if test "x$x_libraries" = xNONE; then
x_libraries="${with_x}/lib"
fi
else
# Check if the user has specified sysroot, but not --with-x, --x-includes or --x-libraries.
# Make a simple check for the libraries at the sysroot, and setup --x-includes and
# --x-libraries for the sysroot, if that seems to be correct.
if test "x$SYSROOT" != "x"; then
if test "x$x_includes" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/X11R6/include"
elif test -f "$SYSROOT/usr/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/include"
fi
fi
if test "x$x_libraries" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/X11R6/lib"
elif test -f "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
x_libraries="$SYSROOT/usr/lib64"
elif test -f "$SYSROOT/usr/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/lib"
fi
fi
fi
fi
# Now let autoconf do it's magic
AC_PATH_X
AC_PATH_XTRA
# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling
# this doesn't make sense so we remove it.
if test "x$COMPILE_TYPE" = xcross; then
X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[[^ ]]*//g'`
fi
if test "x$no_x" = xyes; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find X11 libraries. $HELP_MSG])
fi
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
OPENWIN_HOME="/usr/openwin"
X_CFLAGS="-I$SYSROOT$OPENWIN_HOME/include -I$SYSROOT$OPENWIN_HOME/include/X11/extensions"
X_LIBS="-L$SYSROOT$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-L$SYSROOT$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR"
fi
AC_LANG_PUSH(C)
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $SYSROOT_CFLAGS $X_CFLAGS"
# Need to include Xlib.h and Xutil.h to avoid "present but cannot be compiled" warnings on Solaris 10
AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h],
[X11_HEADERS_OK=yes],
[X11_HEADERS_OK=no; break],
[
# include <X11/Xlib.h>
# include <X11/Xutil.h>
]
)
if test "x$X11_HEADERS_OK" = xno; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h XTest.h Intrinsic.h). $HELP_MSG])
fi
# If XLinearGradient isn't available in Xrender.h, signal that it needs to be
# defined in libawt_xawt.
AC_MSG_CHECKING([if XlinearGradient is defined in Xrender.h])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <X11/extensions/Xrender.h>]],
[[XLinearGradient x;]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
X_CFLAGS="$X_CFLAGS -DSOLARIS10_NO_XRENDER_STRUCTS"])
CFLAGS="$OLD_CFLAGS"
AC_LANG_POP(C)
fi # NEEDS_LIB_X11
AC_SUBST(X_CFLAGS)
AC_SUBST(X_LIBS)
])

File diff suppressed because it is too large Load Diff

@ -96,7 +96,7 @@ REQUIRED_OS_NAME:=@REQUIRED_OS_NAME@
REQUIRED_OS_VERSION:=@REQUIRED_OS_VERSION@
@SET_OPENJDK@
LIBM:=-lm
LIBM:=@LIBM@
LIBDL:=@LIBDL@
# colon or semicolon
@ -245,6 +245,7 @@ MEMORY_SIZE:=@MEMORY_SIZE@
# Enable sjavac support = use a javac server,
# multi core javac compilation and dependency tracking.
ENABLE_SJAVAC:=@ENABLE_SJAVAC@
ENABLE_JAVAC_SERVER:=@ENABLE_JAVAC_SERVER@
# Store sjavac server synchronization files here, and
# the sjavac server log files.
SJAVAC_SERVER_DIR=$(MAKESUPPORT_OUTPUTDIR)/javacservers
@ -499,10 +500,12 @@ LN:=@LN@
MKDIR:=@MKDIR@
MV:=@MV@
NAWK:=@NAWK@
NICE:=@NICE@
PATCH:=@PATCH@
PRINTF:=@PRINTF@
PWD:=@THEPWDCMD@
RM:=@RM@
RMDIR:=@RMDIR@
SED:=@SED@
SH:=@SH@
SORT:=@SORT@

@ -51,8 +51,6 @@ else
STAT_PRINT_SIZE="-c %s"
fi
UNARCHIVE="$UNZIP -q"
COMPARE_EXCEPTIONS_INCLUDE="$SRC_ROOT/common/bin/compare_exceptions.sh.incl"
if [ ! -e "$COMPARE_EXCEPTIONS_INCLUDE" ]; then
echo "Error: Cannot locate the exceptions file, it should have been here: $COMPARE_EXCEPTIONS_INCLUDE"

@ -0,0 +1,62 @@
#!/bin/bash
# Get an absolute path to this script, since that determines the top-level
# directory.
this_script_dir=`dirname $0`
TOPDIR=`cd $this_script_dir/../.. > /dev/null && pwd`
GREP=grep
MD_FILE=$TOPDIR/README-builds.md
HTML_FILE=$TOPDIR/README-builds.html
# Locate the markdown processor tool and check that it is the correct version.
locate_markdown_processor() {
if [ -z "$MARKDOWN" ]; then
MARKDOWN=`which markdown 2> /dev/null`
if [ -z "$MARKDOWN" ]; then
echo "Error: Cannot locate markdown processor" 1>&2
exit 1
fi
fi
# Test version
MARKDOWN_VERSION=`$MARKDOWN -version | $GREP version`
if [ "x$MARKDOWN_VERSION" != "xThis is Markdown, version 1.0.1." ]; then
echo "Error: Expected markdown version 1.0.1." 1>&2
echo "Actual version found: $MARKDOWN_VERSION" 1>&2
echo "Download markdown here: https://daringfireball.net/projects/markdown/" 1>&2
exit 1
fi
}
# Verify that the source markdown file looks sound.
verify_source_code() {
TOO_LONG_LINES=`$GREP -E -e '^.{80}.+$' $MD_FILE`
if [ "x$TOO_LONG_LINES" != x ]; then
echo "Warning: The following lines are longer than 80 characters:"
$GREP -E -e '^.{80}.+$' $MD_FILE
fi
}
# Convert the markdown file to html format.
process_source() {
echo "Generating html file from markdown"
cat > $HTML_FILE << END
<html>
<head>
<title>OpenJDK Build README</title>
</head>
<body>
END
markdown $MD_FILE >> $HTML_FILE
cat >> $HTML_FILE <<END
</body>
</html>
END
echo "Done"
}
locate_markdown_processor
verify_source_code
process_source

@ -327,3 +327,7 @@ d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
c20d8ebddaa6fb09cc81d3edf3d1d05f4232700a jdk9-b82
ca8a1719588424f6e04e943790c7fcb7cb0b8c8f jdk9-b83
df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
3ec06af1368924469f7ce60a00324bac55eaeecc jdk9-b85
0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88

@ -567,6 +567,11 @@ public class IIOPInputStream
// XXX I18N, logging needed.
throw new NotActiveException("defaultReadObjectDelegate");
if (!currentClassDesc.forClass().isAssignableFrom(
currentObject.getClass())) {
throw new IOException("Object Type mismatch");
}
// The array will be null unless fields were retrieved
// remotely because of a serializable version difference.
// Bug fix for 4365188. See the definition of
@ -1063,6 +1068,9 @@ public class IIOPInputStream
int spBase = spClass; // current top of stack
if (currentClass.getName().equals("java.lang.String")) {
return this.readUTF();
}
/* The object's classes should be processed from supertype to subtype
* Push all the clases of the current object onto a stack.
* Note that only the serializable classes are represented
@ -2257,6 +2265,27 @@ public class IIOPInputStream
try {
Class fieldCl = fields[i].getClazz();
if ((objectValue != null)
&& (!fieldCl.isAssignableFrom(
objectValue.getClass()))) {
throw new IllegalArgumentException("Field mismatch");
}
Field classField = null;
try {
classField = cl.getDeclaredField(fields[i].getName());
} catch (NoSuchFieldException nsfEx) {
throw new IllegalArgumentException(nsfEx);
} catch (SecurityException secEx) {
throw new IllegalArgumentException(secEx.getCause());
}
Class<?> declaredFieldClass = classField.getType();
// check input field type is a declared field type
// input field is a subclass of the declared field
if (!declaredFieldClass.isAssignableFrom(fieldCl)) {
throw new IllegalArgumentException(
"Field Type mismatch");
}
if (objectValue != null && !fieldCl.isInstance(objectValue)) {
throw new IllegalArgumentException();
}

@ -559,6 +559,10 @@ public class IIOPOutputStream
* Push all the clases of the current object onto a stack.
* Remember the stack pointer where this set of classes is being pushed.
*/
if (currentClassDesc.forClass().getName().equals("java.lang.String")) {
this.writeUTF((String)obj);
return;
}
int stackMark = classDescStack.size();
try {
ObjectStreamClass next;

@ -446,6 +446,9 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
if (emitPermissionCheck) {
// produce the following generated code for example
//
// private transient boolean _instantiated = false;
//
// private static Void checkPermission() {
// SecurityManager sm = System.getSecurityManager();
// if (sm != null) {
@ -460,11 +463,21 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
//
// public _XXXXX_Stub() {
// this(checkPermission());
// _instantiated = true;
// }
//
// private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
// checkPermission();
// s.defaultReadObject();
// _instantiated = true;
// }
//
// where XXXXX is the name of the remote interface
p.pln();
p.plnI("private transient boolean _instantiated = false;");
p.pln();
p.pO();
p.plnI("private static Void checkPermission() {");
p.plnI("SecurityManager sm = System.getSecurityManager();");
p.pln("if (sm != null) {");
@ -481,13 +494,23 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
p.pO();
p.pI();
p.pln("private " + currentClass + "(Void ignore) { }");
p.plnI("private " + currentClass + "(Void ignore) { }");
p.pln();
p.pO();
p.plnI("public " + currentClass + "() { ");
p.pln("this(checkPermission());");
p.pln("_instantiated = true;");
p.pOln("}");
p.pln();
p.plnI("private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {");
p.plnI("checkPermission();");
p.pO();
p.pln("s.defaultReadObject();");
p.pln("_instantiated = true;");
p.pOln("}");
p.pln();
//p.pO();
}
if (!emitPermissionCheck) {
@ -894,6 +917,7 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
String paramNames[] = method.getArgumentNames();
Type returnType = method.getReturnType();
ValueType[] exceptions = getStubExceptions(method,false);
boolean hasIOException = false;
addNamesInUse(method);
addNameInUse("_type_ids");
@ -921,6 +945,13 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
p.plnI(" {");
// Now create the method body...
if (emitPermissionCheck) {
p.pln("if ((System.getSecurityManager() != null) && (!_instantiated)) {");
p.plnI(" throw new java.io.IOError(new java.io.IOException(\"InvalidObject \"));");
p.pOln("}");
p.pln();
}
if (localStubs) {
writeLocalStubMethodBody(p,method,theType);

@ -487,3 +487,7 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
1c453a12be3036d482abef1dd470f8aff536b6b9 jdk9-b82
3ed0df2c553a80e0e26b91a6ce08806ea17a066a jdk9-b83
184c4328444974edd6b3b490b9d0177ace7e331c jdk9-b84
03845376ea9dbf9690b6a9cfb4ed63f8cc0541c0 jdk9-b85
1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2015, 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
@ -52,21 +52,19 @@ public class Method extends Metadata {
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("Method");
type = db.lookupType("Method");
constMethod = type.getAddressField("_constMethod");
methodData = type.getAddressField("_method_data");
methodCounters = type.getAddressField("_method_counters");
methodSize = new CIntField(type.getCIntegerField("_method_size"), 0);
accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0);
code = type.getAddressField("_code");
vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0);
bytecodeOffset = type.getSize();
/*
interpreterEntry = type.getAddressField("_interpreter_entry");
fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point");
interpreterEntry = type.getAddressField("_from_interpreted_entry");
*/
objectInitializerName = null;
classInitializerName = null;
}
@ -77,16 +75,22 @@ public class Method extends Metadata {
public boolean isMethod() { return true; }
// Not a Method field, used to keep type.
private static Type type;
// Fields
private static AddressField constMethod;
private static AddressField methodData;
private static AddressField methodCounters;
private static CIntField methodSize;
private static CIntField accessFlags;
private static CIntField vtableIndex;
private static long bytecodeOffset;
private static AddressField code;
/*
private static AddressCField fromCompiledCodeEntryPoint;
private static AddressField interpreterEntry;
*/
// constant method names - <init>, <clinit>
// Initialized lazily to avoid initialization ordering dependencies between Method and SymbolTable
@ -106,11 +110,6 @@ public class Method extends Metadata {
}
/*
private static AddressCField interpreterEntry;
private static AddressCField fromCompiledCodeEntryPoint;
*/
// Accessors for declared fields
public ConstMethod getConstMethod() {
Address addr = constMethod.getValue(getAddress());
@ -128,7 +127,6 @@ public class Method extends Metadata {
return (MethodCounters) VMObjectFactory.newObject(MethodCounters.class, addr);
}
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
public long getMethodSize() { return methodSize.getValue(this); }
public long getMaxStack() { return getConstMethod().getMaxStack(); }
public long getMaxLocals() { return getConstMethod().getMaxLocals(); }
public long getSizeOfParameters() { return getConstMethod().getSizeOfParameters(); }
@ -265,7 +263,7 @@ public class Method extends Metadata {
}
public long getSize() {
return getMethodSize();
return type.getSize() + (isNative() ? 2: 0);
}
public void printValueOn(PrintStream tty) {
@ -273,7 +271,6 @@ public class Method extends Metadata {
}
public void iterateFields(MetadataVisitor visitor) {
visitor.doCInt(methodSize, true);
visitor.doCInt(accessFlags, true);
}

@ -77,6 +77,7 @@ $(GENSRC_DIR)/_gensrc_proc_done: $(PROC_SRCS) \
$(MKDIR) -p $(@D)
$(eval $(call ListPathsSafely,PROC_SRCS,$(@D)/_gensrc_proc_files))
$(JAVA_SMALL) $(NEW_JAVAC) \
-XDignore.symbol.file \
-sourcepath $(SOURCEPATH) \
-implicit:none \
-proc:only \

@ -55,10 +55,17 @@ define_pd_global(intx, CodeEntryAlignment, 16);
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

@ -41,6 +41,18 @@ define_pd_global(bool, ImplicitNullChecks, true); // Generate code for impli
define_pd_global(bool, TrapBasedNullChecks, true);
define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast.
#define DEFAULT_STACK_YELLOW_PAGES (6)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2))
#define MIN_STACK_YELLOW_PAGES (1)
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES (1)
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
// Use large code-entry alignment.
define_pd_global(intx, CodeEntryAlignment, 128);
define_pd_global(intx, OptoLoopAlignment, 16);

@ -52,19 +52,27 @@ define_pd_global(intx, OptoLoopAlignment, 16); // = 4*wordSize
define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC
define_pd_global(intx, InlineSmallCode, 1500);
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#ifdef _LP64
// Stack slots are 2X larger in LP64 than in the 32 bit VM.
define_pd_global(intx, ThreadStackSize, 1024);
define_pd_global(intx, VMThreadStackSize, 1024);
define_pd_global(intx, StackShadowPages, 10 DEBUG_ONLY(+1));
#define DEFAULT_STACK_SHADOW_PAGES (10 DEBUG_ONLY(+1))
#else
define_pd_global(intx, ThreadStackSize, 512);
define_pd_global(intx, VMThreadStackSize, 512);
define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
#endif
#define DEFAULT_STACK_SHADOW_PAGES (3 DEBUG_ONLY(+1))
#endif // _LP64
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

@ -55,16 +55,28 @@ define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000);
define_pd_global(intx, StackYellowPages, NOT_WINDOWS(2) WINDOWS_ONLY(3));
define_pd_global(intx, StackRedPages, 1);
#define DEFAULT_STACK_YELLOW_PAGES (NOT_WINDOWS(2) WINDOWS_ONLY(3))
#define DEFAULT_STACK_RED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#ifdef AMD64
// Very large C++ stack frames using solaris-amd64 optimized builds
// due to lack of optimization caused by C++ compiler bugs
define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2));
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2))
// For those clients that do not use write socket, we allow
// the min range value to be below that of the default
#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(6) DEBUG_ONLY(+2))
#else
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
#endif // AMD64
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
@ -135,6 +147,7 @@ define_pd_global(bool, PreserveFramePointer, false);
\
product(uintx, RTMRetryCount, 5, \
"Number of RTM retries on lock abort or busy") \
range(0, max_uintx) \
\
experimental(intx, RTMSpinLoopCount, 100, \
"Spin count for lock to become free before RTM retry") \

@ -45,9 +45,17 @@ define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000 );
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (5 LP64_ONLY(+1) DEBUG_ONLY(+3))
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

@ -39,15 +39,16 @@
/* a scarce resource and there may be situations where we do not want the VM */ \
/* to run with 16M pages. (Will fall back to 64K pages). */ \
product_pd(bool, Use16MPages, \
"Use 16M pages if available.") \
"Use 16M pages if available.") \
\
/* use optimized addresses for the polling page, */ \
/* e.g. map it to a special 32-bit address. */ \
product_pd(bool, OptimizePollingPageLocation, \
"Optimize the location of the polling page used for Safepoints") \
"Optimize the location of the polling page used for Safepoints") \
\
product_pd(intx, AttachListenerTimeout, \
"Timeout in ms the attach listener waits for a request") \
"Timeout in ms the attach listener waits for a request") \
range(0, 2147483) \
\
// Per default, do not allow 16M pages. 16M pages have to be switched on specifically.

@ -42,10 +42,6 @@ define_pd_global(intx, CompilerThreadStackSize, 4096);
// Allow extra space in DEBUG builds for asserts.
define_pd_global(size_t, JVMInvokeMethodSlack, 8192);
define_pd_global(intx, StackYellowPages, 6);
define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+2));
// Only used on 64 bit platforms
define_pd_global(size_t, HeapBaseMinAddress, 2*G);

@ -42,10 +42,6 @@ define_pd_global(intx, CompilerThreadStackSize, 4096);
// Allow extra space in DEBUG builds for asserts.
define_pd_global(size_t, JVMInvokeMethodSlack, 8192);
define_pd_global(intx, StackYellowPages, 6);
define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+2));
// Only used on 64 bit platforms
define_pd_global(size_t, HeapBaseMinAddress, 2*G);

@ -555,7 +555,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
exception->print_value_string(), p2i((address)exception()), nm->method()->print_value_string(), p2i(pc), p2i(thread));
}
// for AbortVMOnException flag
NOT_PRODUCT(Exceptions::debug_check_abort(exception));
Exceptions::debug_check_abort(exception);
// Clear out the exception oop and pc since looking up an
// exception handler can cause class loading, which might throw an

@ -2003,6 +2003,10 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
}
if (name == vmSymbols::object_initializer_name() && is_interface) {
classfile_parse_error("Interface cannot have a method named <init>, class file %s", CHECK_(nullHandle));
}
int args_size = -1; // only used when _need_verify is true
if (_need_verify) {
args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +

@ -1579,11 +1579,9 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
return;
}
// Make sure "this" has been initialized if current method is an
// <init>. Note that "<init>" methods in interfaces are just
// normal methods. Interfaces cannot have ctors.
// <init>.
if (_method->name() == vmSymbols::object_initializer_name() &&
current_frame.flag_this_uninit() &&
!current_class()->is_interface()) {
current_frame.flag_this_uninit()) {
verify_error(ErrorContext::bad_code(bci),
"Constructor must call super() or this() "
"before return");

@ -6051,8 +6051,8 @@ MarkRefsIntoClosure::MarkRefsIntoClosure(
_span(span),
_bitMap(bitMap)
{
assert(_ref_processor == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
assert(ref_processor() == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
}
void MarkRefsIntoClosure::do_oop(oop obj) {
@ -6073,8 +6073,8 @@ Par_MarkRefsIntoClosure::Par_MarkRefsIntoClosure(
_span(span),
_bitMap(bitMap)
{
assert(_ref_processor == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
assert(ref_processor() == NULL, "deliberately left NULL");
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
}
void Par_MarkRefsIntoClosure::do_oop(oop obj) {
@ -6097,8 +6097,8 @@ MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
_verification_bm(verification_bm),
_cms_bm(cms_bm)
{
assert(_ref_processor == NULL, "deliberately left NULL");
assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
assert(ref_processor() == NULL, "deliberately left NULL");
assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
}
void MarkRefsIntoVerifyClosure::do_oop(oop obj) {
@ -6140,8 +6140,9 @@ MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span,
_concurrent_precleaning(concurrent_precleaning),
_freelistLock(NULL)
{
_ref_processor = rp;
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
// FIXME: Should initialize in base class constructor.
assert(rp != NULL, "ref_processor shouldn't be NULL");
set_ref_processor_internal(rp);
}
// This closure is used to mark refs into the CMS generation at the
@ -6246,8 +6247,9 @@ Par_MarkRefsIntoAndScanClosure::Par_MarkRefsIntoAndScanClosure(
((uint)CMSWorkQueueDrainThreshold * ParallelGCThreads))),
_par_pushAndMarkClosure(collector, span, rp, bit_map, work_queue)
{
_ref_processor = rp;
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
// FIXME: Should initialize in base class constructor.
assert(rp != NULL, "ref_processor shouldn't be NULL");
set_ref_processor_internal(rp);
}
// This closure is used to mark refs into the CMS generation at the
@ -7097,7 +7099,7 @@ PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
_mark_stack(mark_stack),
_concurrent_precleaning(concurrent_precleaning)
{
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
assert(ref_processor() != NULL, "ref_processor shouldn't be NULL");
}
// Grey object rescan during pre-cleaning and second checkpoint phases --
@ -7168,7 +7170,7 @@ Par_PushAndMarkClosure::Par_PushAndMarkClosure(CMSCollector* collector,
_bit_map(bit_map),
_work_queue(work_queue)
{
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
assert(ref_processor() != NULL, "ref_processor shouldn't be NULL");
}
void PushAndMarkClosure::do_oop(oop* p) { PushAndMarkClosure::do_oop_work(p); }

@ -112,6 +112,8 @@ class ConcurrentG1Refine: public CHeapObj<mtGC> {
int thread_threshold_step() const { return _thread_threshold_step; }
G1HotCardCache* hot_card_cache() { return &_hot_card_cache; }
static bool hot_card_cache_enabled() { return G1HotCardCache::default_use_cache(); }
};
#endif // SHARE_VM_GC_G1_CONCURRENTG1REFINE_HPP

@ -3084,17 +3084,21 @@ public:
}
};
static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h) {
ReferenceProcessor* result = NULL;
if (G1UseConcMarkReferenceProcessing) {
result = g1h->ref_processor_cm();
assert(result != NULL, "should not be NULL");
}
return result;
}
G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h,
ConcurrentMark* cm,
CMTask* task)
: _g1h(g1h), _cm(cm), _task(task) {
assert(_ref_processor == NULL, "should be initialized to NULL");
if (G1UseConcMarkReferenceProcessing) {
_ref_processor = g1h->ref_processor_cm();
assert(_ref_processor != NULL, "should not be NULL");
}
}
: MetadataAwareOopClosure(get_cm_oop_closure_ref_processor(g1h)),
_g1h(g1h), _cm(cm), _task(task)
{ }
void CMTask::setup_for_region(HeapRegion* hr) {
assert(hr != NULL,
@ -3731,8 +3735,7 @@ void CMTask::do_marking_step(double time_target_ms,
// and do_marking_step() is not being called serially.
bool do_stealing = do_termination && !is_serial;
double diff_prediction_ms =
g1_policy->get_new_prediction(&_marking_step_diffs_ms);
double diff_prediction_ms = _g1h->g1_policy()->predictor().get_new_prediction(&_marking_step_diffs_ms);
_time_target_ms = time_target_ms - diff_prediction_ms;
// set up the variables that are used in the work-based scheme to

@ -22,6 +22,9 @@
*
*/
#ifndef SHARE_VM_GC_G1_G1CODEBLOBCLOSURE_HPP
#define SHARE_VM_GC_G1_G1CODEBLOBCLOSURE_HPP
#include "gc/g1/g1CollectedHeap.hpp"
#include "memory/iterator.hpp"
@ -53,3 +56,6 @@ public:
void do_code_blob(CodeBlob* cb);
};
#endif // SHARE_VM_GC_G1_G1CODEBLOBCLOSURE_HPP

@ -44,6 +44,7 @@
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1RegionToSpaceMapper.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1YCTypes.hpp"
@ -125,213 +126,6 @@ class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure {
size_t num_processed() const { return _num_processed; }
};
YoungList::YoungList(G1CollectedHeap* g1h) :
_g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0),
_survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) {
guarantee(check_list_empty(false), "just making sure...");
}
void YoungList::push_region(HeapRegion *hr) {
assert(!hr->is_young(), "should not already be young");
assert(hr->get_next_young_region() == NULL, "cause it should!");
hr->set_next_young_region(_head);
_head = hr;
_g1h->g1_policy()->set_region_eden(hr, (int) _length);
++_length;
}
void YoungList::add_survivor_region(HeapRegion* hr) {
assert(hr->is_survivor(), "should be flagged as survivor region");
assert(hr->get_next_young_region() == NULL, "cause it should!");
hr->set_next_young_region(_survivor_head);
if (_survivor_head == NULL) {
_survivor_tail = hr;
}
_survivor_head = hr;
++_survivor_length;
}
void YoungList::empty_list(HeapRegion* list) {
while (list != NULL) {
HeapRegion* next = list->get_next_young_region();
list->set_next_young_region(NULL);
list->uninstall_surv_rate_group();
// This is called before a Full GC and all the non-empty /
// non-humongous regions at the end of the Full GC will end up as
// old anyway.
list->set_old();
list = next;
}
}
void YoungList::empty_list() {
assert(check_list_well_formed(), "young list should be well formed");
empty_list(_head);
_head = NULL;
_length = 0;
empty_list(_survivor_head);
_survivor_head = NULL;
_survivor_tail = NULL;
_survivor_length = 0;
_last_sampled_rs_lengths = 0;
assert(check_list_empty(false), "just making sure...");
}
bool YoungList::check_list_well_formed() {
bool ret = true;
uint length = 0;
HeapRegion* curr = _head;
HeapRegion* last = NULL;
while (curr != NULL) {
if (!curr->is_young()) {
gclog_or_tty->print_cr("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " "
"incorrectly tagged (y: %d, surv: %d)",
p2i(curr->bottom()), p2i(curr->end()),
curr->is_young(), curr->is_survivor());
ret = false;
}
++length;
last = curr;
curr = curr->get_next_young_region();
}
ret = ret && (length == _length);
if (!ret) {
gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!");
gclog_or_tty->print_cr("### list has %u entries, _length is %u",
length, _length);
}
return ret;
}
bool YoungList::check_list_empty(bool check_sample) {
bool ret = true;
if (_length != 0) {
gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %u",
_length);
ret = false;
}
if (check_sample && _last_sampled_rs_lengths != 0) {
gclog_or_tty->print_cr("### YOUNG LIST has non-zero last sampled RS lengths");
ret = false;
}
if (_head != NULL) {
gclog_or_tty->print_cr("### YOUNG LIST does not have a NULL head");
ret = false;
}
if (!ret) {
gclog_or_tty->print_cr("### YOUNG LIST does not seem empty");
}
return ret;
}
void
YoungList::rs_length_sampling_init() {
_sampled_rs_lengths = 0;
_curr = _head;
}
bool
YoungList::rs_length_sampling_more() {
return _curr != NULL;
}
void
YoungList::rs_length_sampling_next() {
assert( _curr != NULL, "invariant" );
size_t rs_length = _curr->rem_set()->occupied();
_sampled_rs_lengths += rs_length;
// The current region may not yet have been added to the
// incremental collection set (it gets added when it is
// retired as the current allocation region).
if (_curr->in_collection_set()) {
// Update the collection set policy information for this region
_g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length);
}
_curr = _curr->get_next_young_region();
if (_curr == NULL) {
_last_sampled_rs_lengths = _sampled_rs_lengths;
// gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths);
}
}
void
YoungList::reset_auxilary_lists() {
guarantee( is_empty(), "young list should be empty" );
assert(check_list_well_formed(), "young list should be well formed");
// Add survivor regions to SurvRateGroup.
_g1h->g1_policy()->note_start_adding_survivor_regions();
_g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */);
int young_index_in_cset = 0;
for (HeapRegion* curr = _survivor_head;
curr != NULL;
curr = curr->get_next_young_region()) {
_g1h->g1_policy()->set_region_survivor(curr, young_index_in_cset);
// The region is a non-empty survivor so let's add it to
// the incremental collection set for the next evacuation
// pause.
_g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr);
young_index_in_cset += 1;
}
assert((uint) young_index_in_cset == _survivor_length, "post-condition");
_g1h->g1_policy()->note_stop_adding_survivor_regions();
_head = _survivor_head;
_length = _survivor_length;
if (_survivor_head != NULL) {
assert(_survivor_tail != NULL, "cause it shouldn't be");
assert(_survivor_length > 0, "invariant");
_survivor_tail->set_next_young_region(NULL);
}
// Don't clear the survivor list handles until the start of
// the next evacuation pause - we need it in order to re-tag
// the survivor regions from this evacuation pause as 'young'
// at the start of the next.
_g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */);
assert(check_list_well_formed(), "young list should be well formed");
}
void YoungList::print() {
HeapRegion* lists[] = {_head, _survivor_head};
const char* names[] = {"YOUNG", "SURVIVOR"};
for (uint list = 0; list < ARRAY_SIZE(lists); ++list) {
gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]);
HeapRegion *curr = lists[list];
if (curr == NULL)
gclog_or_tty->print_cr(" empty");
while (curr != NULL) {
gclog_or_tty->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT ", N: " PTR_FORMAT ", age: %4d",
HR_FORMAT_PARAMS(curr),
p2i(curr->prev_top_at_mark_start()),
p2i(curr->next_top_at_mark_start()),
curr->age_in_surv_rate_group_cond());
curr = curr->get_next_young_region();
}
}
gclog_or_tty->cr();
}
void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) {
HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions);
@ -2469,14 +2263,11 @@ void G1CollectedHeap::check_gc_time_stamps() {
}
#endif // PRODUCT
void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl,
DirtyCardQueue* into_cset_dcq,
bool concurrent,
uint worker_i) {
// Clean cards in the hot card cache
G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
hot_card_cache->drain(worker_i, g1_rem_set(), into_cset_dcq);
void G1CollectedHeap::iterate_hcc_closure(CardTableEntryClosure* cl, uint worker_i) {
_cg1r->hot_card_cache()->drain(cl, worker_i);
}
void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, uint worker_i) {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
size_t n_completed_buffers = 0;
while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) {
@ -4355,80 +4146,6 @@ void G1CollectedHeap::preserve_mark_during_evac_failure(uint worker_id, oop obj,
}
}
void G1ParCopyHelper::mark_object(oop obj) {
assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet");
// We know that the object is not moving so it's safe to read its size.
_cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
}
void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
assert(from_obj->is_forwarded(), "from obj should be forwarded");
assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
assert(from_obj != to_obj, "should not be self-forwarded");
assert(_g1->heap_region_containing(from_obj)->in_collection_set(), "from obj should be in the CSet");
assert(!_g1->heap_region_containing(to_obj)->in_collection_set(), "should not mark objects in the CSet");
// The object might be in the process of being copied by another
// worker so we cannot trust that its to-space image is
// well-formed. So we have to read its size from its from-space
// image which we know should not be changing.
_cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id);
}
template <class T>
void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) {
if (_g1->heap_region_containing_raw(new_obj)->is_young()) {
_scanned_klass->record_modified_oops();
}
}
template <G1Barrier barrier, G1Mark do_mark_object>
template <class T>
void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (oopDesc::is_null(heap_oop)) {
return;
}
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(_worker_id == _par_scan_state->worker_id(), "sanity");
const InCSetState state = _g1->in_cset_state(obj);
if (state.is_in_cset()) {
oop forwardee;
markOop m = obj->mark();
if (m->is_marked()) {
forwardee = (oop) m->decode_pointer();
} else {
forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
}
assert(forwardee != NULL, "forwardee should not be NULL");
oopDesc::encode_store_heap_oop(p, forwardee);
if (do_mark_object != G1MarkNone && forwardee != obj) {
// If the object is self-forwarded we don't need to explicitly
// mark it, the evacuation failure protocol will do so.
mark_forwarded_object(obj, forwardee);
}
if (barrier == G1BarrierKlass) {
do_klass_barrier(p, forwardee);
}
} else {
if (state.is_humongous()) {
_g1->set_humongous_is_live(obj);
}
// The object is not in collection set. If we're a root scanning
// closure during an initial mark pause then attempt to mark the object.
if (do_mark_object == G1MarkFromRoot) {
mark_object(obj);
}
}
}
class G1ParEvacuateFollowersClosure : public VoidClosure {
private:
double _start_term;
@ -4481,32 +4198,6 @@ void G1ParEvacuateFollowersClosure::do_void() {
} while (!offer_termination());
}
class G1KlassScanClosure : public KlassClosure {
G1ParCopyHelper* _closure;
bool _process_only_dirty;
int _count;
public:
G1KlassScanClosure(G1ParCopyHelper* closure, bool process_only_dirty)
: _process_only_dirty(process_only_dirty), _closure(closure), _count(0) {}
void do_klass(Klass* klass) {
// If the klass has not been dirtied we know that there's
// no references into the young gen and we can skip it.
if (!_process_only_dirty || klass->has_modified_oops()) {
// Clean the klass since we're going to scavenge all the metadata.
klass->clear_modified_oops();
// Tell the closure that this klass is the Klass to scavenge
// and is the one to dirty if oops are left pointing into the young gen.
_closure->set_scanned_klass(klass);
klass->oops_do(_closure);
_closure->set_scanned_klass(NULL);
}
_count++;
}
};
class G1ParTask : public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
@ -4527,42 +4218,6 @@ public:
_n_workers(n_workers)
{}
RefToScanQueueSet* queues() { return _queues; }
RefToScanQueue *work_queue(int i) {
return queues()->queue(i);
}
ParallelTaskTerminator* terminator() { return &_terminator; }
// Helps out with CLD processing.
//
// During InitialMark we need to:
// 1) Scavenge all CLDs for the young GC.
// 2) Mark all objects directly reachable from strong CLDs.
template <G1Mark do_mark_object>
class G1CLDClosure : public CLDClosure {
G1ParCopyClosure<G1BarrierNone, do_mark_object>* _oop_closure;
G1ParCopyClosure<G1BarrierKlass, do_mark_object> _oop_in_klass_closure;
G1KlassScanClosure _klass_in_cld_closure;
bool _claim;
public:
G1CLDClosure(G1ParCopyClosure<G1BarrierNone, do_mark_object>* oop_closure,
bool only_young, bool claim)
: _oop_closure(oop_closure),
_oop_in_klass_closure(oop_closure->g1(),
oop_closure->pss()),
_klass_in_cld_closure(&_oop_in_klass_closure, only_young),
_claim(claim) {
}
void do_cld(ClassLoaderData* cld) {
cld->oops_do(_oop_closure, &_klass_in_cld_closure, _claim);
}
};
void work(uint worker_id) {
if (worker_id >= _n_workers) return; // no work needed this round
@ -4578,62 +4233,18 @@ public:
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(rp);
bool only_young = _g1h->collector_state()->gcs_are_young();
// Non-IM young GC.
G1ParCopyClosure<G1BarrierNone, G1MarkNone> scan_only_root_cl(_g1h, pss);
G1CLDClosure<G1MarkNone> scan_only_cld_cl(&scan_only_root_cl,
only_young, // Only process dirty klasses.
false); // No need to claim CLDs.
// IM young GC.
// Strong roots closures.
G1ParCopyClosure<G1BarrierNone, G1MarkFromRoot> scan_mark_root_cl(_g1h, pss);
G1CLDClosure<G1MarkFromRoot> scan_mark_cld_cl(&scan_mark_root_cl,
false, // Process all klasses.
true); // Need to claim CLDs.
// Weak roots closures.
G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> scan_mark_weak_root_cl(_g1h, pss);
G1CLDClosure<G1MarkPromotedFromRoot> scan_mark_weak_cld_cl(&scan_mark_weak_root_cl,
false, // Process all klasses.
true); // Need to claim CLDs.
OopClosure* strong_root_cl;
OopClosure* weak_root_cl;
CLDClosure* strong_cld_cl;
CLDClosure* weak_cld_cl;
bool trace_metadata = false;
if (_g1h->collector_state()->during_initial_mark_pause()) {
// We also need to mark copied objects.
strong_root_cl = &scan_mark_root_cl;
strong_cld_cl = &scan_mark_cld_cl;
if (ClassUnloadingWithConcurrentMark) {
weak_root_cl = &scan_mark_weak_root_cl;
weak_cld_cl = &scan_mark_weak_cld_cl;
trace_metadata = true;
} else {
weak_root_cl = &scan_mark_root_cl;
weak_cld_cl = &scan_mark_cld_cl;
}
} else {
strong_root_cl = &scan_only_root_cl;
weak_root_cl = &scan_only_root_cl;
strong_cld_cl = &scan_only_cld_cl;
weak_cld_cl = &scan_only_cld_cl;
}
double start_strong_roots_sec = os::elapsedTime();
_root_processor->evacuate_roots(strong_root_cl,
weak_root_cl,
strong_cld_cl,
weak_cld_cl,
trace_metadata,
worker_id);
_root_processor->evacuate_roots(pss->closures(), worker_id);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss);
// We pass a weak code blobs closure to the remembered set scanning because we want to avoid
// treating the nmethods visited to act as roots for concurrent marking.
// We only want to make sure that the oops in the nmethods are adjusted with regard to the
// objects copied by the current evacuation.
size_t cards_scanned = _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
weak_root_cl,
pss->closures()->weak_codeblobs(),
worker_id);
_pss->add_cards_scanned(worker_id, cards_scanned);
@ -5294,19 +4905,8 @@ public:
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL);
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
if (_g1h->collector_state()->during_initial_mark_pause()) {
// We also need to mark copied objects.
copy_non_heap_cl = &copy_mark_non_heap_cl;
}
// Keep alive closure.
G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, pss);
G1CopyingKeepAliveClosure keep_alive(_g1h, pss->closures()->raw_strong_oops(), pss);
// Complete GC closure
G1ParEvacuateFollowersClosure drain_queue(_g1h, pss, _task_queues, _terminator);
@ -5394,23 +4994,12 @@ public:
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
if (_g1h->collector_state()->during_initial_mark_pause()) {
// We also need to mark copied objects.
copy_non_heap_cl = &copy_mark_non_heap_cl;
}
// Is alive closure
G1AlwaysAliveClosure always_alive(_g1h);
// Copying keep alive closure. Applied to referent objects that need
// to be copied.
G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, pss);
G1CopyingKeepAliveClosure keep_alive(_g1h, pss->closures()->raw_strong_oops(), pss);
ReferenceProcessor* rp = _g1h->ref_processor_cm();
@ -5500,23 +5089,8 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "pre-condition");
// We do not embed a reference processor in the copying/scanning
// closures while we're actually processing the discovered
// reference objects.
G1ParScanExtRootClosure only_copy_non_heap_cl(this, pss);
G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
if (collector_state()->during_initial_mark_pause()) {
// We also need to mark copied objects.
copy_non_heap_cl = &copy_mark_non_heap_cl;
}
// Keep alive closure.
G1CopyingKeepAliveClosure keep_alive(this, copy_non_heap_cl, pss);
G1CopyingKeepAliveClosure keep_alive(this, pss->closures()->raw_strong_oops(), pss);
// Serial Complete GC closure
G1STWDrainQueueClosure drain_queue(this, pss);

@ -39,6 +39,7 @@
#include "gc/g1/hSpaceCounters.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/g1/heapRegionSet.hpp"
#include "gc/g1/youngList.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/plab.hpp"
@ -64,7 +65,6 @@ class SpaceClosure;
class CompactibleSpaceClosure;
class Space;
class G1CollectorPolicy;
class GenRemSet;
class G1RemSet;
class HeapRegionRemSetIterator;
class ConcurrentMark;
@ -88,79 +88,6 @@ typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet;
typedef int RegionIdx_t; // needs to hold [ 0..max_regions() )
typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion )
class YoungList : public CHeapObj<mtGC> {
private:
G1CollectedHeap* _g1h;
HeapRegion* _head;
HeapRegion* _survivor_head;
HeapRegion* _survivor_tail;
HeapRegion* _curr;
uint _length;
uint _survivor_length;
size_t _last_sampled_rs_lengths;
size_t _sampled_rs_lengths;
void empty_list(HeapRegion* list);
public:
YoungList(G1CollectedHeap* g1h);
void push_region(HeapRegion* hr);
void add_survivor_region(HeapRegion* hr);
void empty_list();
bool is_empty() { return _length == 0; }
uint length() { return _length; }
uint eden_length() { return length() - survivor_length(); }
uint survivor_length() { return _survivor_length; }
// Currently we do not keep track of the used byte sum for the
// young list and the survivors and it'd be quite a lot of work to
// do so. When we'll eventually replace the young list with
// instances of HeapRegionLinkedList we'll get that for free. So,
// we'll report the more accurate information then.
size_t eden_used_bytes() {
assert(length() >= survivor_length(), "invariant");
return (size_t) eden_length() * HeapRegion::GrainBytes;
}
size_t survivor_used_bytes() {
return (size_t) survivor_length() * HeapRegion::GrainBytes;
}
void rs_length_sampling_init();
bool rs_length_sampling_more();
void rs_length_sampling_next();
void reset_sampled_info() {
_last_sampled_rs_lengths = 0;
}
size_t sampled_rs_lengths() { return _last_sampled_rs_lengths; }
// for development purposes
void reset_auxilary_lists();
void clear() { _head = NULL; _length = 0; }
void clear_survivors() {
_survivor_head = NULL;
_survivor_tail = NULL;
_survivor_length = 0;
}
HeapRegion* first_region() { return _head; }
HeapRegion* first_survivor_region() { return _survivor_head; }
HeapRegion* last_survivor_region() { return _survivor_tail; }
// debugging
bool check_list_well_formed();
bool check_list_empty(bool check_sample = true);
void print();
};
// The G1 STW is alive closure.
// An instance is embedded into the G1CH and used as the
// (optional) _is_alive_non_header closure in the STW
@ -1083,9 +1010,11 @@ public:
// continues humongous regions too.
void reset_gc_time_stamps(HeapRegion* hr);
void iterate_dirty_card_closure(CardTableEntryClosure* cl,
DirtyCardQueue* into_cset_dcq,
bool concurrent, uint worker_i);
// Apply the given closure on all cards in the Hot Card Cache, emptying it.
void iterate_hcc_closure(CardTableEntryClosure* cl, uint worker_i);
// Apply the given closure on all cards in the Dirty Card Queue Set, emptying it.
void iterate_dirty_card_closure(CardTableEntryClosure* cl, uint worker_i);
// The shared block offset table array.
G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; }

@ -80,6 +80,7 @@ static double non_young_other_cost_per_region_ms_defaults[] = {
};
G1CollectorPolicy::G1CollectorPolicy() :
_predictor(G1ConfidencePercent / 100.0),
_parallel_gc_threads(ParallelGCThreads),
_recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
@ -92,6 +93,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
_prev_collection_pause_end_ms(0.0),
_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_scan_hcc_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
@ -126,8 +128,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
_survivor_cset_region_length(0),
_old_cset_region_length(0),
_sigma(G1ConfidencePercent / 100.0),
_collection_set(NULL),
_collection_set_bytes_used_before(0),
@ -150,12 +150,12 @@ G1CollectorPolicy::G1CollectorPolicy() :
_gc_overhead_perc(0.0) {
// SurvRateGroups below must be initialized after '_sigma' because they
// indirectly access '_sigma' through this object passed to their constructor.
// SurvRateGroups below must be initialized after the predictor because they
// indirectly use it through this object passed to their constructor.
_short_lived_surv_rate_group =
new SurvRateGroup(this, "Short Lived", G1YoungSurvRateNumRegionsSummary);
new SurvRateGroup(&_predictor, "Short Lived", G1YoungSurvRateNumRegionsSummary);
_survivor_surv_rate_group =
new SurvRateGroup(this, "Survivor", G1YoungSurvRateNumRegionsSummary);
new SurvRateGroup(&_predictor, "Survivor", G1YoungSurvRateNumRegionsSummary);
// Set up the region size and associated fields. Given that the
// policy is created before the heap, we have to set this up here,
@ -192,6 +192,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
_cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]);
_cost_scan_hcc_seq->add(0.0);
_young_cards_per_entry_ratio_seq->add(
young_cards_per_entry_ratio_defaults[index]);
_cost_per_entry_ms_seq->add(cost_per_entry_ms_defaults[index]);
@ -287,9 +288,13 @@ G1CollectorPolicy::G1CollectorPolicy() :
_collectionSetChooser = new CollectionSetChooser();
}
double G1CollectorPolicy::get_new_prediction(TruncatedSeq const* seq) const {
return _predictor.get_new_prediction(seq);
}
void G1CollectorPolicy::initialize_alignments() {
_space_alignment = HeapRegion::GrainBytes;
size_t card_table_alignment = GenRemSet::max_alignment_constraint();
size_t card_table_alignment = CardTableRS::ct_max_alignment_constraint();
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
_heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size);
}
@ -314,8 +319,7 @@ void G1CollectorPolicy::post_heap_initialize() {
}
}
const G1CollectorState* G1CollectorPolicy::collector_state() const { return _g1->collector_state(); }
G1CollectorState* G1CollectorPolicy::collector_state() { return _g1->collector_state(); }
G1CollectorState* G1CollectorPolicy::collector_state() const { return _g1->collector_state(); }
G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
_min_desired_young_length(0), _max_desired_young_length(0) {
@ -426,8 +430,8 @@ void G1CollectorPolicy::init() {
_young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
}
_free_regions_at_end_of_collection = _g1->num_free_regions();
update_young_list_target_length();
update_young_list_target_length();
// We may immediately start allocating regions and placing them on the
// collection set list. Initialize the per-collection set info
start_incremental_cset_building();
@ -458,9 +462,8 @@ bool G1CollectorPolicy::predict_will_fit(uint young_length,
return false;
}
size_t free_bytes =
(base_free_regions - young_length) * HeapRegion::GrainBytes;
if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) {
size_t free_bytes = (base_free_regions - young_length) * HeapRegion::GrainBytes;
if ((2.0 /* magic */ * _predictor.sigma()) * bytes_to_copy > free_bytes) {
// end condition 3: out-of-space (conservatively!)
return false;
}
@ -1046,10 +1049,12 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t
if (update_stats) {
double cost_per_card_ms = 0.0;
double cost_scan_hcc = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC);
if (_pending_cards > 0) {
cost_per_card_ms = phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) / (double) _pending_cards;
cost_per_card_ms = (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards;
_cost_per_card_ms_seq->add(cost_per_card_ms);
}
_cost_scan_hcc_seq->add(cost_scan_hcc);
double cost_per_entry_ms = 0.0;
if (cards_scanned > 10) {
@ -1146,8 +1151,25 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t
// Note that _mmu_tracker->max_gc_time() returns the time in seconds.
double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
adjust_concurrent_refinement(phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS),
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS), update_rs_time_goal_ms);
double scan_hcc_time_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC);
if (update_rs_time_goal_ms < scan_hcc_time_ms) {
ergo_verbose2(ErgoTiming,
"adjust concurrent refinement thresholds",
ergo_format_reason("Scanning the HCC expected to take longer than Update RS time goal")
ergo_format_ms("Update RS time goal")
ergo_format_ms("Scan HCC time"),
update_rs_time_goal_ms,
scan_hcc_time_ms);
update_rs_time_goal_ms = 0;
} else {
update_rs_time_goal_ms -= scan_hcc_time_ms;
}
adjust_concurrent_refinement(phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
update_rs_time_goal_ms);
_collectionSetChooser->verify();
}
@ -1248,7 +1270,7 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
cg1r->set_red_zone(g * k_gr);
cg1r->reinitialize_threads();
int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * sigma()), 1);
int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * _predictor.sigma()), 1);
int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta,
cg1r->yellow_zone());
// Change the barrier params
@ -1265,17 +1287,125 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
dcqs.notify_if_necessary();
}
double
G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards,
size_t scanned_cards) const {
size_t G1CollectorPolicy::predict_rs_length_diff() const {
return (size_t) get_new_prediction(_rs_length_diff_seq);
}
double G1CollectorPolicy::predict_alloc_rate_ms() const {
return get_new_prediction(_alloc_rate_ms_seq);
}
double G1CollectorPolicy::predict_cost_per_card_ms() const {
return get_new_prediction(_cost_per_card_ms_seq);
}
double G1CollectorPolicy::predict_scan_hcc_ms() const {
return get_new_prediction(_cost_scan_hcc_seq);
}
double G1CollectorPolicy::predict_rs_update_time_ms(size_t pending_cards) const {
return pending_cards * predict_cost_per_card_ms() + predict_scan_hcc_ms();
}
double G1CollectorPolicy::predict_young_cards_per_entry_ratio() const {
return get_new_prediction(_young_cards_per_entry_ratio_seq);
}
double G1CollectorPolicy::predict_mixed_cards_per_entry_ratio() const {
if (_mixed_cards_per_entry_ratio_seq->num() < 2) {
return predict_young_cards_per_entry_ratio();
} else {
return get_new_prediction(_mixed_cards_per_entry_ratio_seq);
}
}
size_t G1CollectorPolicy::predict_young_card_num(size_t rs_length) const {
return (size_t) (rs_length * predict_young_cards_per_entry_ratio());
}
size_t G1CollectorPolicy::predict_non_young_card_num(size_t rs_length) const {
return (size_t)(rs_length * predict_mixed_cards_per_entry_ratio());
}
double G1CollectorPolicy::predict_rs_scan_time_ms(size_t card_num) const {
if (collector_state()->gcs_are_young()) {
return card_num * get_new_prediction(_cost_per_entry_ms_seq);
} else {
return predict_mixed_rs_scan_time_ms(card_num);
}
}
double G1CollectorPolicy::predict_mixed_rs_scan_time_ms(size_t card_num) const {
if (_mixed_cost_per_entry_ms_seq->num() < 3) {
return card_num * get_new_prediction(_cost_per_entry_ms_seq);
} else {
return card_num * get_new_prediction(_mixed_cost_per_entry_ms_seq);
}
}
double G1CollectorPolicy::predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const {
if (_cost_per_byte_ms_during_cm_seq->num() < 3) {
return (1.1 * bytes_to_copy) * get_new_prediction(_cost_per_byte_ms_seq);
} else {
return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_during_cm_seq);
}
}
double G1CollectorPolicy::predict_object_copy_time_ms(size_t bytes_to_copy) const {
if (collector_state()->during_concurrent_mark()) {
return predict_object_copy_time_ms_during_cm(bytes_to_copy);
} else {
return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_seq);
}
}
double G1CollectorPolicy::predict_constant_other_time_ms() const {
return get_new_prediction(_constant_other_time_ms_seq);
}
double G1CollectorPolicy::predict_young_other_time_ms(size_t young_num) const {
return young_num * get_new_prediction(_young_other_cost_per_region_ms_seq);
}
double G1CollectorPolicy::predict_non_young_other_time_ms(size_t non_young_num) const {
return non_young_num * get_new_prediction(_non_young_other_cost_per_region_ms_seq);
}
double G1CollectorPolicy::predict_remark_time_ms() const {
return get_new_prediction(_concurrent_mark_remark_times_ms);
}
double G1CollectorPolicy::predict_cleanup_time_ms() const {
return get_new_prediction(_concurrent_mark_cleanup_times_ms);
}
double G1CollectorPolicy::predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
TruncatedSeq* seq = surv_rate_group->get_seq(age);
guarantee(seq->num() > 0, "There should be some young gen survivor samples available. Tried to access with age %d", age);
double pred = get_new_prediction(seq);
if (pred > 1.0) {
pred = 1.0;
}
return pred;
}
double G1CollectorPolicy::predict_yg_surv_rate(int age) const {
return predict_yg_surv_rate(age, _short_lived_surv_rate_group);
}
double G1CollectorPolicy::accum_yg_surv_rate_pred(int age) const {
return _short_lived_surv_rate_group->accum_surv_rate_pred(age);
}
double G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards,
size_t scanned_cards) const {
return
predict_rs_update_time_ms(pending_cards) +
predict_rs_scan_time_ms(scanned_cards) +
predict_constant_other_time_ms();
}
double
G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) const {
double G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) const {
size_t rs_length = predict_rs_length_diff();
size_t card_num;
if (collector_state()->gcs_are_young()) {
@ -1294,14 +1424,13 @@ size_t G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) const {
assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant");
int age = hr->age_in_surv_rate_group();
double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group());
bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate);
bytes_to_copy = (size_t) (hr->used() * yg_surv_rate);
}
return bytes_to_copy;
}
double
G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
bool for_young_gc) const {
double G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
bool for_young_gc) const {
size_t rs_length = hr->rem_set()->occupied();
size_t card_num;
@ -1328,9 +1457,8 @@ G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
return region_elapsed_time_ms;
}
void
G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length,
uint survivor_cset_region_length) {
void G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length,
uint survivor_cset_region_length) {
_eden_cset_region_length = eden_cset_region_length;
_survivor_cset_region_length = survivor_cset_region_length;
_old_cset_region_length = 0;

@ -29,6 +29,7 @@
#include "gc/g1/g1CollectorState.hpp"
#include "gc/g1/g1InCSetState.hpp"
#include "gc/g1/g1MMUTracker.hpp"
#include "gc/g1/g1Predictions.hpp"
#include "gc/shared/collectorPolicy.hpp"
// A G1CollectorPolicy makes policy decisions that determine the
@ -161,7 +162,11 @@ public:
};
class G1CollectorPolicy: public CollectorPolicy {
private:
private:
G1Predictions _predictor;
double get_new_prediction(TruncatedSeq const* seq) const;
// either equal to the number of parallel threads, if ParallelGCThreads
// has been set, or 1 otherwise
int _parallel_gc_threads;
@ -169,10 +174,6 @@ private:
// The number of GC threads currently active.
uintx _no_of_gc_threads;
enum SomePrivateConstants {
NumPrevPausesForHeuristics = 10
};
G1MMUTracker* _mmu_tracker;
void initialize_alignments();
@ -211,7 +212,8 @@ private:
uint _reserve_regions;
enum PredictionConstants {
TruncatedSeqLength = 10
TruncatedSeqLength = 10,
NumPrevPausesForHeuristics = 10
};
TruncatedSeq* _alloc_rate_ms_seq;
@ -219,6 +221,7 @@ private:
TruncatedSeq* _rs_length_diff_seq;
TruncatedSeq* _cost_per_card_ms_seq;
TruncatedSeq* _cost_scan_hcc_seq;
TruncatedSeq* _young_cards_per_entry_ratio_seq;
TruncatedSeq* _mixed_cards_per_entry_ratio_seq;
TruncatedSeq* _cost_per_entry_ms_seq;
@ -250,25 +253,9 @@ private:
size_t _recorded_rs_lengths;
size_t _max_rs_lengths;
double _sigma;
size_t _rs_lengths_prediction;
double sigma() const { return _sigma; }
// A function that prevents us putting too much stock in small sample
// sets. Returns a number between 2.0 and 1.0, depending on the number
// of samples. 5 or more samples yields one; fewer scales linearly from
// 2.0 at 1 sample to 1.0 at 5.
double confidence_factor(int samples) const {
if (samples > 4) return 1.0;
else return 1.0 + sigma() * ((double)(5 - samples))/2.0;
}
double get_new_neg_prediction(TruncatedSeq* seq) {
return seq->davg() - sigma() * seq->dsd();
}
#ifndef PRODUCT
bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
#endif // PRODUCT
@ -285,6 +272,8 @@ private:
size_t _pending_cards;
public:
G1Predictions& predictor() { return _predictor; }
// Accessors
void set_region_eden(HeapRegion* hr, int young_index_in_cset) {
@ -303,102 +292,41 @@ public:
bool verify_young_ages();
#endif // PRODUCT
double get_new_prediction(TruncatedSeq* seq) const {
return MAX2(seq->davg() + sigma() * seq->dsd(),
seq->davg() * confidence_factor(seq->num()));
}
void record_max_rs_lengths(size_t rs_lengths) {
_max_rs_lengths = rs_lengths;
}
size_t predict_rs_length_diff() const {
return (size_t) get_new_prediction(_rs_length_diff_seq);
}
size_t predict_rs_length_diff() const;
double predict_alloc_rate_ms() const {
return get_new_prediction(_alloc_rate_ms_seq);
}
double predict_alloc_rate_ms() const;
double predict_cost_per_card_ms() const {
return get_new_prediction(_cost_per_card_ms_seq);
}
double predict_cost_per_card_ms() const;
double predict_rs_update_time_ms(size_t pending_cards) const {
return (double) pending_cards * predict_cost_per_card_ms();
}
double predict_scan_hcc_ms() const;
double predict_young_cards_per_entry_ratio() const {
return get_new_prediction(_young_cards_per_entry_ratio_seq);
}
double predict_rs_update_time_ms(size_t pending_cards) const;
double predict_mixed_cards_per_entry_ratio() const {
if (_mixed_cards_per_entry_ratio_seq->num() < 2) {
return predict_young_cards_per_entry_ratio();
} else {
return get_new_prediction(_mixed_cards_per_entry_ratio_seq);
}
}
double predict_young_cards_per_entry_ratio() const;
size_t predict_young_card_num(size_t rs_length) const {
return (size_t) ((double) rs_length *
predict_young_cards_per_entry_ratio());
}
double predict_mixed_cards_per_entry_ratio() const;
size_t predict_non_young_card_num(size_t rs_length) const {
return (size_t) ((double) rs_length *
predict_mixed_cards_per_entry_ratio());
}
size_t predict_young_card_num(size_t rs_length) const;
double predict_rs_scan_time_ms(size_t card_num) const {
if (collector_state()->gcs_are_young()) {
return (double) card_num * get_new_prediction(_cost_per_entry_ms_seq);
} else {
return predict_mixed_rs_scan_time_ms(card_num);
}
}
size_t predict_non_young_card_num(size_t rs_length) const;
double predict_mixed_rs_scan_time_ms(size_t card_num) const {
if (_mixed_cost_per_entry_ms_seq->num() < 3) {
return (double) card_num * get_new_prediction(_cost_per_entry_ms_seq);
} else {
return (double) (card_num *
get_new_prediction(_mixed_cost_per_entry_ms_seq));
}
}
double predict_rs_scan_time_ms(size_t card_num) const;
double predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const {
if (_cost_per_byte_ms_during_cm_seq->num() < 3) {
return (1.1 * (double) bytes_to_copy) *
get_new_prediction(_cost_per_byte_ms_seq);
} else {
return (double) bytes_to_copy *
get_new_prediction(_cost_per_byte_ms_during_cm_seq);
}
}
double predict_mixed_rs_scan_time_ms(size_t card_num) const;
double predict_object_copy_time_ms(size_t bytes_to_copy) const {
if (collector_state()->during_concurrent_mark()) {
return predict_object_copy_time_ms_during_cm(bytes_to_copy);
} else {
return (double) bytes_to_copy *
get_new_prediction(_cost_per_byte_ms_seq);
}
}
double predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const;
double predict_constant_other_time_ms() const {
return get_new_prediction(_constant_other_time_ms_seq);
}
double predict_object_copy_time_ms(size_t bytes_to_copy) const;
double predict_young_other_time_ms(size_t young_num) const {
return (double) young_num *
get_new_prediction(_young_other_cost_per_region_ms_seq);
}
double predict_constant_other_time_ms() const;
double predict_non_young_other_time_ms(size_t non_young_num) const {
return (double) non_young_num *
get_new_prediction(_non_young_other_cost_per_region_ms_seq);
}
double predict_young_other_time_ms(size_t young_num) const;
double predict_non_young_other_time_ms(size_t non_young_num) const;
double predict_base_elapsed_time_ms(size_t pending_cards) const;
double predict_base_elapsed_time_ms(size_t pending_cards,
@ -415,11 +343,15 @@ public:
double predict_survivor_regions_evac_time() const;
bool should_update_surv_rate_group_predictors() {
return collector_state()->last_gc_was_young() && !collector_state()->in_marking_window();
}
void cset_regions_freed() {
bool propagate = collector_state()->should_propagate();
_short_lived_surv_rate_group->all_surviving_words_recorded(propagate);
_survivor_surv_rate_group->all_surviving_words_recorded(propagate);
// also call it on any more surv rate groups
bool update = should_update_surv_rate_group_predictors();
_short_lived_surv_rate_group->all_surviving_words_recorded(update);
_survivor_surv_rate_group->all_surviving_words_recorded(update);
}
G1MMUTracker* mmu_tracker() {
@ -434,34 +366,17 @@ public:
return _mmu_tracker->max_gc_time() * 1000.0;
}
double predict_remark_time_ms() const {
return get_new_prediction(_concurrent_mark_remark_times_ms);
}
double predict_remark_time_ms() const;
double predict_cleanup_time_ms() const {
return get_new_prediction(_concurrent_mark_cleanup_times_ms);
}
double predict_cleanup_time_ms() const;
// Returns an estimate of the survival rate of the region at yg-age
// "yg_age".
double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
TruncatedSeq* seq = surv_rate_group->get_seq(age);
if (seq->num() == 0)
gclog_or_tty->print("BARF! age is %d", age);
guarantee( seq->num() > 0, "invariant" );
double pred = get_new_prediction(seq);
if (pred > 1.0)
pred = 1.0;
return pred;
}
double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const;
double predict_yg_surv_rate(int age) const {
return predict_yg_surv_rate(age, _short_lived_surv_rate_group);
}
double predict_yg_surv_rate(int age) const;
double accum_yg_surv_rate_pred(int age) const {
return _short_lived_surv_rate_group->accum_surv_rate_pred(age);
}
double accum_yg_surv_rate_pred(int age) const;
private:
// Statistics kept per GC stoppage, pause or full.
@ -608,8 +523,7 @@ public:
virtual G1CollectorPolicy* as_g1_policy() { return this; }
const G1CollectorState* collector_state() const;
G1CollectorState* collector_state();
G1CollectorState* collector_state() const;
G1GCPhaseTimes* phase_times() const { return _phase_times; }
@ -883,15 +797,4 @@ public:
virtual void post_heap_initialize();
};
// This should move to some place more general...
// If we have "n" measurements, and we've kept track of their "sum" and the
// "sum_of_squares" of the measurements, this returns the variance of the
// sequence.
inline double variance(int n, double sum_of_squares, double sum) {
double n_d = (double)n;
double avg = sum/n_d;
return (sum_of_squares - 2.0 * avg * sum + n_d * avg * avg) / n_d;
}
#endif // SHARE_VM_GC_G1_G1COLLECTORPOLICY_HPP

@ -121,11 +121,7 @@ class G1CollectorState VALUE_OBJ_CLASS_SPEC {
return (_in_marking_window && !_in_marking_window_im);
}
bool should_propagate() const { // XXX should have a more suitable state name or abstraction for this
return (_last_young_gc && !_in_marking_window);
}
G1YCType yc_type() {
G1YCType yc_type() const {
if (during_initial_mark_pause()) {
return InitialMark;
} else if (mark_in_progress()) {

@ -56,6 +56,7 @@ const char* G1ErgoVerbose::to_string(int tag) {
case ErgoCSetConstruction: return "CSet Construction";
case ErgoConcCycles: return "Concurrent Cycles";
case ErgoMixedGCs: return "Mixed GCs";
case ErgoTiming: return "Timing";
default:
ShouldNotReachHere();
// Keep the Windows compiler happy

@ -70,6 +70,7 @@ typedef enum {
ErgoCSetConstruction,
ErgoConcCycles,
ErgoMixedGCs,
ErgoTiming,
ErgoHeuristicNum
} ErgoHeuristic;

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1Log.hpp"
@ -269,6 +270,8 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
_gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[ScanHCC] = new WorkerDataArray<double>(max_gc_threads, "Scan HCC (ms)", true, G1Log::LevelFiner, 3);
_gc_par_phases[ScanHCC]->set_enabled(ConcurrentG1Refine::hot_card_cache_enabled());
_gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms)", true, G1Log::LevelFiner, 2);

@ -56,6 +56,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
WeakCLDRoots,
SATBFiltering,
UpdateRS,
ScanHCC,
ScanRS,
CodeRoots,
ObjCopy,

@ -26,7 +26,6 @@
#include "gc/g1/dirtyCardQueue.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1HotCardCache.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "runtime/atomic.inline.hpp"
G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
@ -81,9 +80,7 @@ jbyte* G1HotCardCache::insert(jbyte* card_ptr) {
return (previous_ptr == current_ptr) ? previous_ptr : card_ptr;
}
void G1HotCardCache::drain(uint worker_i,
G1RemSet* g1rs,
DirtyCardQueue* into_cset_dcq) {
void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) {
if (!default_use_cache()) {
assert(_hot_cache == NULL, "Logic");
return;
@ -101,21 +98,8 @@ void G1HotCardCache::drain(uint worker_i,
for (size_t i = start_idx; i < end_idx; i++) {
jbyte* card_ptr = _hot_cache[i];
if (card_ptr != NULL) {
if (g1rs->refine_card(card_ptr, worker_i, true)) {
// The part of the heap spanned by the card contains references
// that point into the current collection set.
// We need to record the card pointer in the DirtyCardQueueSet
// that we use for such cards.
//
// The only time we care about recording cards that contain
// references that point into the collection set is during
// RSet updating while within an evacuation pause.
// In this case worker_i should be the id of a GC worker thread
assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
assert(worker_i < ParallelGCThreads, "incorrect worker id: %u", worker_i);
into_cset_dcq->enqueue(card_ptr);
}
bool result = cl->do_card_ptr(card_ptr, worker_i);
assert(result, "Closure should always return true");
} else {
break;
}

@ -32,9 +32,9 @@
#include "runtime/thread.hpp"
#include "utilities/globalDefinitions.hpp"
class CardTableEntryClosure;
class DirtyCardQueue;
class G1CollectedHeap;
class G1RemSet;
class HeapRegion;
// An evicting cache of cards that have been logged by the G1 post
@ -84,11 +84,11 @@ class G1HotCardCache: public CHeapObj<mtGC> {
// The number of cached cards a thread claims when flushing the cache
static const int ClaimChunkSize = 32;
bool default_use_cache() const {
public:
static bool default_use_cache() {
return (G1ConcRSLogCacheSize > 0);
}
public:
G1HotCardCache(G1CollectedHeap* g1h);
~G1HotCardCache();
@ -113,7 +113,7 @@ class G1HotCardCache: public CHeapObj<mtGC> {
// Refine the cards that have delayed as a result of
// being in the cache.
void drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
void drain(CardTableEntryClosure* cl, uint worker_i);
// Set up for parallel processing of the cards in the hot cache
void reset_hot_cache_claimed_index() {

@ -51,15 +51,11 @@ struct InCSetState {
enum {
// Selection of the values were driven to micro-optimize the encoding and
// frequency of the checks.
// The most common check is whether the region is in the collection set or not.
// This encoding allows us to use an != 0 check which in some architectures
// (x86*) can be encoded slightly more efficently than a normal comparison
// against zero.
// The same situation occurs when checking whether the region is humongous
// or not, which is encoded by values < 0.
// The most common check is whether the region is in the collection set or not,
// this encoding allows us to use an > 0 check.
// The other values are simply encoded in increasing generation order, which
// makes getting the next generation fast by a simple increment.
Humongous = -1, // The region is humongous - note that actually any value < 0 would be possible here.
Humongous = -1, // The region is humongous
NotInCSet = 0, // The region is not in the collection set.
Young = 1, // The region is in the collection set and a young region.
Old = 2, // The region is in the collection set and an old region.
@ -74,9 +70,10 @@ struct InCSetState {
void set_old() { _value = Old; }
bool is_in_cset_or_humongous() const { return _value != NotInCSet; }
bool is_in_cset_or_humongous() const { return is_in_cset() || is_humongous(); }
bool is_in_cset() const { return _value > NotInCSet; }
bool is_humongous() const { return _value < NotInCSet; }
bool is_humongous() const { return _value == Humongous; }
bool is_young() const { return _value == Young; }
bool is_old() const { return _value == Old; }

@ -31,31 +31,32 @@
#include "utilities/stack.inline.hpp"
G1ParCopyHelper::G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
G1ParClosureSuper(g1, par_scan_state), _scanned_klass(NULL),
_cm(_g1->concurrent_mark()) { }
G1ParCopyHelper::G1ParCopyHelper(G1CollectedHeap* g1) :
G1ParClosureSuper(g1), _scanned_klass(NULL),
_cm(_g1->concurrent_mark()) { }
G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1) :
_g1(g1), _par_scan_state(NULL), _worker_id(UINT_MAX) { }
G1ParClosureSuper(g1, par_scan_state),
_worker_id(par_scan_state->worker_id()),
_scanned_klass(NULL),
_cm(_g1->concurrent_mark())
{ }
G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
_g1(g1), _par_scan_state(NULL),
_worker_id(UINT_MAX) {
set_par_scan_thread_state(par_scan_state);
}
_g1(g1), _par_scan_state(par_scan_state)
{ }
void G1ParClosureSuper::set_par_scan_thread_state(G1ParScanThreadState* par_scan_state) {
assert(_par_scan_state == NULL, "_par_scan_state must only be set once");
assert(par_scan_state != NULL, "Must set par_scan_state to non-NULL.");
void G1KlassScanClosure::do_klass(Klass* klass) {
// If the klass has not been dirtied we know that there's
// no references into the young gen and we can skip it.
if (!_process_only_dirty || klass->has_modified_oops()) {
// Clean the klass since we're going to scavenge all the metadata.
klass->clear_modified_oops();
_par_scan_state = par_scan_state;
_worker_id = par_scan_state->worker_id();
// Tell the closure that this klass is the Klass to scavenge
// and is the one to dirty if oops are left pointing into the young gen.
_closure->set_scanned_klass(klass);
assert(_worker_id < ParallelGCThreads,
"The given worker id %u must be less than the number of threads %u", _worker_id, ParallelGCThreads);
klass->oops_do(_closure);
_closure->set_scanned_klass(NULL);
}
_count++;
}
// Generate G1 specialized oop_oop_iterate functions.

@ -52,15 +52,12 @@ class G1ParClosureSuper : public OopsInHeapRegionClosure {
protected:
G1CollectedHeap* _g1;
G1ParScanThreadState* _par_scan_state;
uint _worker_id;
public:
// Initializes the instance, leaving _par_scan_state uninitialized. Must be done
// later using the set_par_scan_thread_state() method.
G1ParClosureSuper(G1CollectedHeap* g1);
G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
bool apply_to_weak_ref_discovered_field() { return true; }
void set_par_scan_thread_state(G1ParScanThreadState* par_scan_state);
G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
~G1ParClosureSuper() { }
public:
virtual bool apply_to_weak_ref_discovered_field() { return true; }
};
class G1ParPushHeapRSClosure : public G1ParClosureSuper {
@ -76,36 +73,41 @@ public:
class G1ParScanClosure : public G1ParClosureSuper {
public:
G1ParScanClosure(G1CollectedHeap* g1) : G1ParClosureSuper(g1) { }
G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
G1ParClosureSuper(g1, par_scan_state) { }
template <class T> void do_oop_nv(T* p);
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
void set_ref_processor(ReferenceProcessor* ref_processor) { _ref_processor = ref_processor; }
void set_ref_processor(ReferenceProcessor* rp) {
set_ref_processor_internal(rp);
}
};
// Add back base class for metadata
class G1ParCopyHelper : public G1ParClosureSuper {
protected:
uint _worker_id; // Cache value from par_scan_state.
Klass* _scanned_klass;
ConcurrentMark* _cm;
// Mark the object if it's not already marked. This is used to mark
// objects pointed to by roots that are guaranteed not to move
// during the GC (i.e., non-CSet objects). It is MT-safe.
void mark_object(oop obj);
inline void mark_object(oop obj);
// Mark the object if it's not already marked. This is used to mark
// objects pointed to by roots that have been forwarded during a
// GC. It is MT-safe.
void mark_forwarded_object(oop from_obj, oop to_obj);
public:
G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
G1ParCopyHelper(G1CollectedHeap* g1);
inline void mark_forwarded_object(oop from_obj, oop to_obj);
G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
~G1ParCopyHelper() { }
public:
void set_scanned_klass(Klass* k) { _scanned_klass = k; }
template <class T> void do_klass_barrier(T* p, oop new_obj);
template <class T> inline void do_klass_barrier(T* p, oop new_obj);
};
enum G1Barrier {
@ -127,26 +129,23 @@ private:
public:
G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
G1ParCopyHelper(g1, par_scan_state) {
assert(_ref_processor == NULL, "sanity");
}
G1ParCopyClosure(G1CollectedHeap* g1) : G1ParCopyHelper(g1) {
assert(_ref_processor == NULL, "sanity");
assert(ref_processor() == NULL, "sanity");
}
template <class T> void do_oop_nv(T* p) { do_oop_work(p); }
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
G1CollectedHeap* g1() { return _g1; };
G1ParScanThreadState* pss() { return _par_scan_state; }
};
typedef G1ParCopyClosure<G1BarrierNone, G1MarkNone> G1ParScanExtRootClosure;
typedef G1ParCopyClosure<G1BarrierNone, G1MarkFromRoot> G1ParScanAndMarkExtRootClosure;
typedef G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> G1ParScanAndMarkWeakExtRootClosure;
// We use a separate closure to handle references during evacuation
// failure processing.
class G1KlassScanClosure : public KlassClosure {
G1ParCopyHelper* _closure;
bool _process_only_dirty;
int _count;
public:
G1KlassScanClosure(G1ParCopyHelper* closure, bool process_only_dirty)
: _process_only_dirty(process_only_dirty), _closure(closure), _count(0) {}
void do_klass(Klass* klass);
};
class FilterIntoCSClosure: public ExtendedOopClosure {
G1CollectedHeap* _g1;

@ -91,7 +91,7 @@ inline void G1ParScanClosure::do_oop_nv(T* p) {
if (state.is_humongous()) {
_g1->set_humongous_is_live(obj);
}
_par_scan_state->update_rs(_from, p, _worker_id);
_par_scan_state->update_rs(_from, p);
}
}
}
@ -225,4 +225,78 @@ inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) {
}
}
template <class T>
void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) {
if (_g1->heap_region_containing_raw(new_obj)->is_young()) {
_scanned_klass->record_modified_oops();
}
}
void G1ParCopyHelper::mark_object(oop obj) {
assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet");
// We know that the object is not moving so it's safe to read its size.
_cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
}
void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
assert(from_obj->is_forwarded(), "from obj should be forwarded");
assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
assert(from_obj != to_obj, "should not be self-forwarded");
assert(_g1->heap_region_containing(from_obj)->in_collection_set(), "from obj should be in the CSet");
assert(!_g1->heap_region_containing(to_obj)->in_collection_set(), "should not mark objects in the CSet");
// The object might be in the process of being copied by another
// worker so we cannot trust that its to-space image is
// well-formed. So we have to read its size from its from-space
// image which we know should not be changing.
_cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id);
}
template <G1Barrier barrier, G1Mark do_mark_object>
template <class T>
void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (oopDesc::is_null(heap_oop)) {
return;
}
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(_worker_id == _par_scan_state->worker_id(), "sanity");
const InCSetState state = _g1->in_cset_state(obj);
if (state.is_in_cset()) {
oop forwardee;
markOop m = obj->mark();
if (m->is_marked()) {
forwardee = (oop) m->decode_pointer();
} else {
forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
}
assert(forwardee != NULL, "forwardee should not be NULL");
oopDesc::encode_store_heap_oop(p, forwardee);
if (do_mark_object != G1MarkNone && forwardee != obj) {
// If the object is self-forwarded we don't need to explicitly
// mark it, the evacuation failure protocol will do so.
mark_forwarded_object(obj, forwardee);
}
if (barrier == G1BarrierKlass) {
do_klass_barrier(p, forwardee);
}
} else {
if (state.is_humongous()) {
_g1->set_humongous_is_live(obj);
}
// The object is not in collection set. If we're a root scanning
// closure during an initial mark pause then attempt to mark the object.
if (do_mark_object == G1MarkFromRoot) {
mark_object(obj);
}
}
}
#endif // SHARE_VM_GC_G1_G1OOPCLOSURES_INLINE_HPP

@ -27,6 +27,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "oops/oop.inline.hpp"
@ -37,15 +38,14 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id,
_refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()),
_ct_bs(g1h->g1_barrier_set()),
_g1_rem(g1h->g1_rem_set()),
_closures(NULL),
_hash_seed(17),
_worker_id(worker_id),
_tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
_age_table(false),
_scanner(g1h),
_scanner(g1h, this),
_old_gen_is_full(false)
{
_scanner.set_par_scan_thread_state(this);
// we allocate G1YoungSurvRateNumRegions plus one entries, since
// we "sacrifice" entry 0 to keep track of surviving bytes for
// non-young regions (where the age is -1)
@ -69,6 +69,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id,
// need to be moved to the next space.
_dest[InCSetState::Young] = InCSetState::Old;
_dest[InCSetState::Old] = InCSetState::Old;
_closures = G1EvacuationRootClosures::create_root_closures(this, _g1h);
}
// Pass locally gathered statistics to global state.
@ -86,6 +88,7 @@ void G1ParScanThreadState::flush(size_t* surviving_young_words) {
G1ParScanThreadState::~G1ParScanThreadState() {
delete _plab_allocator;
delete _closures;
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}

@ -36,6 +36,7 @@
#include "oops/oop.hpp"
class G1PLABAllocator;
class G1EvacuationRootClosures;
class HeapRegion;
class outputStream;
@ -45,7 +46,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
RefToScanQueue* _refs;
DirtyCardQueue _dcq;
G1SATBCardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
G1EvacuationRootClosures* _closures;
G1PLABAllocator* _plab_allocator;
@ -97,7 +98,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
template <class T> void push_on_queue(T* ref);
template <class T> void update_rs(HeapRegion* from, T* p, uint tid) {
template <class T> void update_rs(HeapRegion* from, T* p) {
// If the new value of the field points to the same region or
// is the to-space, we don't need to include it in the Rset updates.
if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
@ -109,6 +110,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
}
}
G1EvacuationRootClosures* closures() { return _closures; }
uint worker_id() { return _worker_id; }
// Returns the current amount of waste due to alignment or not being able to fit

@ -56,7 +56,7 @@ template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from
}
assert(obj != NULL, "Must be");
update_rs(from, p, _worker_id);
update_rs(from, p);
}
template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {

@ -0,0 +1,98 @@
/*
* Copyright (c) 2015, 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 "gc/g1/g1Predictions.hpp"
#ifndef PRODUCT
void G1Predictions::test() {
double const epsilon = 1e-6;
{
// Some basic formula tests with confidence = 0.0
G1Predictions predictor(0.0);
TruncatedSeq s;
double p0 = predictor.get_new_prediction(&s);
assert(p0 < epsilon, "Initial prediction of empty sequence must be 0.0 but is %f", p0);
s.add(5.0);
double p1 = predictor.get_new_prediction(&s);
assert(fabs(p1 - 5.0) < epsilon, "Prediction should be 5.0 but is %f", p1);
for (int i = 0; i < 40; i++) {
s.add(5.0);
}
double p2 = predictor.get_new_prediction(&s);
assert(fabs(p2 - 5.0) < epsilon, "Prediction should be 5.0 but is %f", p1);
}
{
// The following tests checks that the initial predictions are based on the
// average of the sequence and not on the stddev (which is 0).
G1Predictions predictor(0.5);
TruncatedSeq s;
s.add(1.0);
double p1 = predictor.get_new_prediction(&s);
assert(p1 > 1.0, "First prediction must be larger than average, but avg is %f and prediction %f", s.davg(), p1);
s.add(1.0);
double p2 = predictor.get_new_prediction(&s);
assert(p2 < p1, "First prediction must be larger than second, but they are %f %f", p1, p2);
s.add(1.0);
double p3 = predictor.get_new_prediction(&s);
assert(p3 < p2, "Second prediction must be larger than third, but they are %f %f", p2, p3);
s.add(1.0);
s.add(1.0); // Five elements are now in the sequence.
double p5 = predictor.get_new_prediction(&s);
assert(p5 < p3, "Fifth prediction must be smaller than third, but they are %f %f", p3, p5);
assert(fabs(p5 - 1.0) < epsilon, "Prediction must be 1.0+epsilon, but is %f", p5);
}
{
// The following tests checks that initially prediction based on the average is
// used, that gets overridden by the stddev prediction at the end.
G1Predictions predictor(0.5);
TruncatedSeq s;
s.add(0.5);
double p1 = predictor.get_new_prediction(&s);
assert(p1 > 0.5, "First prediction must be larger than average, but avg is %f and prediction %f", s.davg(), p1);
s.add(0.2);
double p2 = predictor.get_new_prediction(&s);
assert(p2 < p1, "First prediction must be larger than second, but they are %f %f", p1, p2);
s.add(0.5);
double p3 = predictor.get_new_prediction(&s);
assert(p3 < p2, "Second prediction must be larger than third, but they are %f %f", p2, p3);
s.add(0.2);
s.add(2.0);
double p5 = predictor.get_new_prediction(&s);
assert(p5 > p3, "Fifth prediction must be bigger than third, but they are %f %f", p3, p5);
}
}
void TestPredictions_test() {
G1Predictions::test();
}
#endif

@ -0,0 +1,67 @@
/*
* Copyright (c) 2015, 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.
*
*/
#ifndef SHARE_VM_GC_G1_G1PREDICTIONS_HPP
#define SHARE_VM_GC_G1_G1PREDICTIONS_HPP
#include "memory/allocation.inline.hpp"
#include "utilities/numberSeq.hpp"
// Utility class containing various helper methods for prediction.
class G1Predictions VALUE_OBJ_CLASS_SPEC {
private:
double _sigma;
// This function is used to estimate the stddev of sample sets. There is some
// special consideration of small sample sets: the actual stddev for them is
// not very useful, so we calculate some value based on the sample average.
// Five or more samples yields zero (at that point we use the stddev); fewer
// scale the sample set average linearly from two times the average to 0.5 times
// it.
double stddev_estimate(TruncatedSeq const* seq) const {
double estimate = seq->dsd();
int const samples = seq->num();
if (samples < 5) {
estimate = MAX2(seq->davg() * (5 - samples) / 2.0, estimate);
}
return estimate;
}
public:
G1Predictions(double sigma) : _sigma(sigma) {
assert(sigma >= 0.0, "Confidence must be larger than or equal to zero");
}
// Confidence factor.
double sigma() const { return _sigma; }
double get_new_prediction(TruncatedSeq const* seq) const {
return seq->davg() + _sigma * stddev_estimate(seq);
}
#ifndef PRODUCT
static void test();
#endif
};
#endif // SHARE_VM_GC_G1_G1PREDICTIONS_HPP

@ -26,7 +26,6 @@
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentG1RefineThread.hpp"
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
#include "gc/g1/g1CodeBlobClosure.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
@ -228,15 +227,13 @@ public:
};
size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
CodeBlobClosure* heap_region_codeblobs,
uint worker_i) {
double rs_time_start = os::elapsedTime();
G1CodeBlobClosure code_root_cl(non_heap_roots);
HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
ScanRSClosure scanRScl(oc, &code_root_cl, worker_i);
ScanRSClosure scanRScl(oc, heap_region_codeblobs, worker_i);
_g1->collection_set_iterate_from(startRegion, &scanRScl);
scanRScl.set_try_claimed();
@ -263,6 +260,7 @@ public:
DirtyCardQueue* into_cset_dcq) :
_g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
{}
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
// The only time we care about recording cards that
// contain references that point into the collection set
@ -285,11 +283,16 @@ public:
};
void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
// Apply the given closure to all remaining log entries.
RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
_g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
{
// Apply the closure to the entries of the hot card cache.
G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i);
_g1->iterate_hcc_closure(&into_cset_update_rs_cl, worker_i);
}
// Apply the closure to all remaining log entries.
_g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, worker_i);
}
void G1RemSet::cleanupHRRS() {
@ -297,7 +300,7 @@ void G1RemSet::cleanupHRRS() {
}
size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
CodeBlobClosure* heap_region_codeblobs,
uint worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
@ -320,7 +323,7 @@ size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
updateRS(&into_cset_dcq, worker_i);
size_t cards_scanned = scanRS(oc, non_heap_roots, worker_i);
size_t cards_scanned = scanRS(oc, heap_region_codeblobs, worker_i);
// We now clear the cached values of _cset_rs_update_cl for this worker
_cset_rs_update_cl[worker_i] = NULL;

@ -95,7 +95,7 @@ public:
// Returns the number of cards scanned while looking for pointers
// into the collection set.
size_t oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
OopClosure* non_heap_roots,
CodeBlobClosure* heap_region_codeblobs,
uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
@ -107,7 +107,7 @@ public:
void cleanup_after_oops_into_collection_set_do();
size_t scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
CodeBlobClosure* heap_region_codeblobs,
uint worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);

@ -0,0 +1,149 @@
/*
* Copyright (c) 2015, 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 "gc/g1/bufferingOopClosure.hpp"
#include "gc/g1/g1CodeBlobClosure.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1RootClosures.hpp"
class G1ParScanThreadState;
// Simple holder object for a complete set of closures used by the G1 evacuation code.
template <G1Mark Mark>
class G1SharedClosures VALUE_OBJ_CLASS_SPEC {
public:
G1ParCopyClosure<G1BarrierNone, Mark> _oops;
G1ParCopyClosure<G1BarrierKlass, Mark> _oop_in_klass;
G1KlassScanClosure _klass_in_cld_closure;
CLDToKlassAndOopClosure _clds;
G1CodeBlobClosure _codeblobs;
BufferingOopClosure _buffered_oops;
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty_klasses, bool must_claim_cld) :
_oops(g1h, pss),
_oop_in_klass(g1h, pss),
_klass_in_cld_closure(&_oop_in_klass, process_only_dirty_klasses),
_clds(&_klass_in_cld_closure, &_oops, must_claim_cld),
_codeblobs(&_oops),
_buffered_oops(&_oops) {}
};
class G1EvacuationClosures : public G1EvacuationRootClosures {
G1SharedClosures<G1MarkNone> _closures;
public:
G1EvacuationClosures(G1CollectedHeap* g1h,
G1ParScanThreadState* pss,
bool gcs_are_young) :
_closures(g1h, pss, gcs_are_young, /* must_claim_cld */ false) {}
OopClosure* weak_oops() { return &_closures._buffered_oops; }
OopClosure* strong_oops() { return &_closures._buffered_oops; }
CLDClosure* weak_clds() { return &_closures._clds; }
CLDClosure* strong_clds() { return &_closures._clds; }
CLDClosure* thread_root_clds() { return NULL; }
CLDClosure* second_pass_weak_clds() { return NULL; }
CodeBlobClosure* strong_codeblobs() { return &_closures._codeblobs; }
CodeBlobClosure* weak_codeblobs() { return &_closures._codeblobs; }
void flush() { _closures._buffered_oops.done(); }
double closure_app_seconds() { return _closures._buffered_oops.closure_app_seconds(); }
OopClosure* raw_strong_oops() { return &_closures._oops; }
bool trace_metadata() { return false; }
};
// Closures used during initial mark.
// The treatment of "weak" roots is selectable through the template parameter,
// this is usually used to control unloading of classes and interned strings.
template <G1Mark MarkWeak>
class G1InitalMarkClosures : public G1EvacuationRootClosures {
G1SharedClosures<G1MarkFromRoot> _strong;
G1SharedClosures<MarkWeak> _weak;
// Filter method to help with returning the appropriate closures
// depending on the class template parameter.
template <G1Mark Mark, typename T>
T* null_if(T* t) {
if (Mark == MarkWeak) {
return NULL;
}
return t;
}
public:
G1InitalMarkClosures(G1CollectedHeap* g1h,
G1ParScanThreadState* pss) :
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true),
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true) {}
OopClosure* weak_oops() { return &_weak._buffered_oops; }
OopClosure* strong_oops() { return &_strong._buffered_oops; }
// If MarkWeak is G1MarkPromotedFromRoot then the weak CLDs must be processed in a second pass.
CLDClosure* weak_clds() { return null_if<G1MarkPromotedFromRoot>(&_weak._clds); }
CLDClosure* strong_clds() { return &_strong._clds; }
// If MarkWeak is G1MarkFromRoot then all CLDs are processed by the weak and strong variants
// return a NULL closure for the following specialized versions in that case.
CLDClosure* thread_root_clds() { return null_if<G1MarkFromRoot>(&_strong._clds); }
CLDClosure* second_pass_weak_clds() { return null_if<G1MarkFromRoot>(&_weak._clds); }
CodeBlobClosure* strong_codeblobs() { return &_strong._codeblobs; }
CodeBlobClosure* weak_codeblobs() { return &_weak._codeblobs; }
void flush() {
_strong._buffered_oops.done();
_weak._buffered_oops.done();
}
double closure_app_seconds() {
return _strong._buffered_oops.closure_app_seconds() +
_weak._buffered_oops.closure_app_seconds();
}
OopClosure* raw_strong_oops() { return &_strong._oops; }
// If we are not marking all weak roots then we are tracing
// which metadata is alive.
bool trace_metadata() { return MarkWeak == G1MarkPromotedFromRoot; }
};
G1EvacuationRootClosures* G1EvacuationRootClosures::create_root_closures(G1ParScanThreadState* pss, G1CollectedHeap* g1h) {
if (g1h->collector_state()->during_initial_mark_pause()) {
if (ClassUnloadingWithConcurrentMark) {
return new G1InitalMarkClosures<G1MarkPromotedFromRoot>(g1h, pss);
} else {
return new G1InitalMarkClosures<G1MarkFromRoot>(g1h, pss);
}
} else {
return new G1EvacuationClosures(g1h, pss, g1h->collector_state()->gcs_are_young());
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, 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.
*
*/
#ifndef SHARE_VM_GC_G1_G1ROOTCLOSURESET_HPP
#define SHARE_VM_GC_G1_G1ROOTCLOSURESET_HPP
#include "memory/allocation.hpp"
#include "memory/iterator.hpp"
class G1CollectedHeap;
class G1ParScanThreadState;
class G1RootClosures : public CHeapObj<mtGC> {
public:
// Closures to process raw oops in the root set.
virtual OopClosure* weak_oops() = 0;
virtual OopClosure* strong_oops() = 0;
// Closures to process CLDs in the root set.
virtual CLDClosure* weak_clds() = 0;
virtual CLDClosure* strong_clds() = 0;
// Applied to the CLDs reachable from the thread stacks.
virtual CLDClosure* thread_root_clds() = 0;
// Applied to code blobs reachable as strong roots.
virtual CodeBlobClosure* strong_codeblobs() = 0;
};
class G1EvacuationRootClosures : public G1RootClosures {
public:
// Flush any buffered state and deferred processing
virtual void flush() = 0;
virtual double closure_app_seconds() = 0;
// Applied to the weakly reachable CLDs when all strongly reachable
// CLDs are guaranteed to have been processed.
virtual CLDClosure* second_pass_weak_clds() = 0;
// Get a raw oop closure for processing oops, bypassing the flushing above.
virtual OopClosure* raw_strong_oops() = 0;
// Applied to code blobs treated as weak roots.
virtual CodeBlobClosure* weak_codeblobs() = 0;
// Is this closure used for tracing metadata?
virtual bool trace_metadata() = 0;
static G1EvacuationRootClosures* create_root_closures(G1ParScanThreadState* pss, G1CollectedHeap* g1h);
};
#endif // SHARE_VM_GC_G1_G1ROOTCLOSURESET_HPP

@ -33,7 +33,7 @@
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "memory/allocation.inline.hpp"
@ -70,40 +70,19 @@ G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
_lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
_n_workers_discovered_strong_classes(0) {}
void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
OopClosure* scan_non_heap_weak_roots,
CLDClosure* scan_strong_clds,
CLDClosure* scan_weak_clds,
bool trace_metadata,
uint worker_i) {
// First scan the shared roots.
void G1RootProcessor::evacuate_roots(G1EvacuationRootClosures* closures, uint worker_i) {
double ext_roots_start = os::elapsedTime();
G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots;
OopClosure* const strong_roots = &buf_scan_non_heap_roots;
// CodeBlobClosures are not interoperable with BufferingOopClosures
G1CodeBlobClosure root_code_blobs(scan_non_heap_roots);
process_java_roots(strong_roots,
trace_metadata ? scan_strong_clds : NULL,
scan_strong_clds,
trace_metadata ? NULL : scan_weak_clds,
&root_code_blobs,
phase_times,
worker_i);
process_java_roots(closures, phase_times, worker_i);
// This is the point where this worker thread will not find more strong CLDs/nmethods.
// Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
if (trace_metadata) {
if (closures->trace_metadata()) {
worker_has_discovered_all_strong_classes();
}
process_vm_roots(strong_roots, weak_roots, phase_times, worker_i);
process_vm_roots(closures, phase_times, worker_i);
{
// Now the CM ref_processor roots.
@ -113,11 +92,11 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
// concurrent mark ref processor as roots and keep entries
// (which are added by the marking threads) on them live
// until they can be processed at the end of marking.
_g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
_g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops());
}
}
if (trace_metadata) {
if (closures->trace_metadata()) {
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
// Barrier to make sure all workers passed
@ -127,18 +106,18 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
// Now take the complement of the strong CLDs.
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
assert(closures->second_pass_weak_clds() != NULL, "Should be non-null if we are tracing metadata.");
ClassLoaderDataGraph::roots_cld_do(NULL, closures->second_pass_weak_clds());
} else {
phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0);
phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0);
assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata.");
}
// Finish up any enqueued closure apps (attributed as object copy time).
buf_scan_non_heap_roots.done();
buf_scan_non_heap_weak_roots.done();
closures->flush();
double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
+ buf_scan_non_heap_weak_roots.closure_app_seconds();
double obj_copy_time_sec = closures->closure_app_seconds();
phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec);
@ -159,22 +138,68 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
_process_strong_tasks.all_tasks_completed(n_workers());
}
// Adaptor to pass the closures to the strong roots in the VM.
class StrongRootsClosures : public G1RootClosures {
OopClosure* _roots;
CLDClosure* _clds;
CodeBlobClosure* _blobs;
public:
StrongRootsClosures(OopClosure* roots, CLDClosure* clds, CodeBlobClosure* blobs) :
_roots(roots), _clds(clds), _blobs(blobs) {}
OopClosure* weak_oops() { return NULL; }
OopClosure* strong_oops() { return _roots; }
CLDClosure* weak_clds() { return NULL; }
CLDClosure* strong_clds() { return _clds; }
CLDClosure* thread_root_clds() { return _clds; }
CodeBlobClosure* strong_codeblobs() { return _blobs; }
};
void G1RootProcessor::process_strong_roots(OopClosure* oops,
CLDClosure* clds,
CodeBlobClosure* blobs) {
StrongRootsClosures closures(oops, clds, blobs);
process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
process_vm_roots(oops, NULL, NULL, 0);
process_java_roots(&closures, NULL, 0);
process_vm_roots(&closures, NULL, 0);
_process_strong_tasks.all_tasks_completed(n_workers());
}
// Adaptor to pass the closures to all the roots in the VM.
class AllRootsClosures : public G1RootClosures {
OopClosure* _roots;
CLDClosure* _clds;
public:
AllRootsClosures(OopClosure* roots, CLDClosure* clds) :
_roots(roots), _clds(clds) {}
OopClosure* weak_oops() { return _roots; }
OopClosure* strong_oops() { return _roots; }
// By returning the same CLDClosure for both weak and strong CLDs we ensure
// that a single walk of the CLDG will invoke the closure on all CLDs i the
// system.
CLDClosure* weak_clds() { return _clds; }
CLDClosure* strong_clds() { return _clds; }
// We don't want to visit CLDs more than once, so we return NULL for the
// thread root CLDs.
CLDClosure* thread_root_clds() { return NULL; }
// We don't want to visit code blobs more than once, so we return NULL for the
// strong case and walk the entire code cache as a separate step.
CodeBlobClosure* strong_codeblobs() { return NULL; }
};
void G1RootProcessor::process_all_roots(OopClosure* oops,
CLDClosure* clds,
CodeBlobClosure* blobs) {
AllRootsClosures closures(oops, clds);
process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0);
process_vm_roots(oops, oops, NULL, 0);
process_java_roots(&closures, NULL, 0);
process_vm_roots(&closures, NULL, 0);
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_CodeCache_oops_do)) {
CodeCache::blobs_do(blobs);
@ -183,35 +208,36 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
_process_strong_tasks.all_tasks_completed(n_workers());
}
void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
CLDClosure* thread_stack_clds,
CLDClosure* strong_clds,
CLDClosure* weak_clds,
CodeBlobClosure* strong_code,
void G1RootProcessor::process_java_roots(G1RootClosures* closures,
G1GCPhaseTimes* phase_times,
uint worker_i) {
assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set");
assert(closures->thread_root_clds() == NULL || closures->weak_clds() == NULL, "There is overlap between those, only one may be set");
// Iterating over the CLDG and the Threads are done early to allow us to
// first process the strong CLDs and nmethods and then, after a barrier,
// let the thread process the weak CLDs and nmethods.
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds());
}
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
bool is_par = n_workers() > 1;
Threads::possibly_parallel_oops_do(is_par, strong_roots, thread_stack_clds, strong_code);
Threads::possibly_parallel_oops_do(is_par,
closures->strong_oops(),
closures->thread_root_clds(),
closures->strong_codeblobs());
}
}
void G1RootProcessor::process_vm_roots(OopClosure* strong_roots,
OopClosure* weak_roots,
void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
G1GCPhaseTimes* phase_times,
uint worker_i) {
OopClosure* strong_roots = closures->strong_oops();
OopClosure* weak_roots = closures->weak_oops();
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_Universe_oops_do)) {

@ -32,8 +32,10 @@
class CLDClosure;
class CodeBlobClosure;
class G1CollectedHeap;
class G1EvacuationRootClosures;
class G1GCPhaseTimes;
class G1ParPushHeapRSClosure;
class G1RootClosures;
class Monitor;
class OopClosure;
class SubTasksDone;
@ -71,16 +73,11 @@ class G1RootProcessor : public StackObj {
void worker_has_discovered_all_strong_classes();
void wait_until_all_strong_classes_discovered();
void process_java_roots(OopClosure* scan_non_heap_roots,
CLDClosure* thread_stack_clds,
CLDClosure* scan_strong_clds,
CLDClosure* scan_weak_clds,
CodeBlobClosure* scan_strong_code,
void process_java_roots(G1RootClosures* closures,
G1GCPhaseTimes* phase_times,
uint worker_i);
void process_vm_roots(OopClosure* scan_non_heap_roots,
OopClosure* scan_non_heap_weak_roots,
void process_vm_roots(G1RootClosures* closures,
G1GCPhaseTimes* phase_times,
uint worker_i);
@ -90,12 +87,7 @@ public:
// Apply closures to the strongly and weakly reachable roots in the system
// in a single pass.
// Record and report timing measurements for sub phases using the worker_i
void evacuate_roots(OopClosure* scan_non_heap_roots,
OopClosure* scan_non_heap_weak_roots,
CLDClosure* scan_strong_clds,
CLDClosure* scan_weak_clds,
bool trace_metadata,
uint worker_i);
void evacuate_roots(G1EvacuationRootClosures* closures, uint worker_i);
// Apply oops, clds and blobs to all strongly reachable roots in the system
void process_strong_roots(OopClosure* oops,

@ -31,7 +31,6 @@
#include "gc/g1/survRateGroup.hpp"
#include "gc/shared/ageTable.hpp"
#include "gc/shared/spaceDecorator.hpp"
#include "gc/shared/watermark.hpp"
#include "utilities/macros.hpp"
// A HeapRegion is the smallest piece of a G1CollectedHeap that

@ -24,15 +24,15 @@
#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1Predictions.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/survRateGroup.hpp"
#include "memory/allocation.hpp"
SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p,
SurvRateGroup::SurvRateGroup(G1Predictions* predictor,
const char* name,
size_t summary_surv_rates_len) :
_g1p(g1p), _name(name),
_predictor(predictor), _name(name),
_summary_surv_rates_len(summary_surv_rates_len),
_summary_surv_rates_max_len(0),
_summary_surv_rates(NULL),
@ -52,10 +52,13 @@ SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p,
start_adding_regions();
}
double SurvRateGroup::get_new_prediction(TruncatedSeq const* seq) const {
return _predictor->get_new_prediction(seq);
}
void SurvRateGroup::reset() {
_all_regions_allocated = 0;
_setup_seq_num = 0;
_accum_surv_rate = 0.0;
_last_pred = 0.0;
// the following will set up the arrays with length 1
_region_num = 1;
@ -76,15 +79,12 @@ void SurvRateGroup::reset() {
_region_num = 0;
}
void
SurvRateGroup::start_adding_regions() {
void SurvRateGroup::start_adding_regions() {
_setup_seq_num = _stats_arrays_length;
_region_num = 0;
_accum_surv_rate = 0.0;
}
void
SurvRateGroup::stop_adding_regions() {
void SurvRateGroup::stop_adding_regions() {
if (_region_num > _stats_arrays_length) {
double* old_surv_rate = _surv_rate;
double* old_accum_surv_rate_pred = _accum_surv_rate_pred;
@ -119,33 +119,12 @@ SurvRateGroup::stop_adding_regions() {
}
}
double
SurvRateGroup::accum_surv_rate(size_t adjustment) {
// we might relax this one in the future...
guarantee( adjustment == 0 || adjustment == 1, "pre-condition" );
double ret = _accum_surv_rate;
if (adjustment > 0) {
TruncatedSeq* seq = get_seq(_region_num+1);
double surv_rate = _g1p->get_new_prediction(seq);
ret += surv_rate;
}
return ret;
}
int
SurvRateGroup::next_age_index() {
TruncatedSeq* seq = get_seq(_region_num);
double surv_rate = _g1p->get_new_prediction(seq);
_accum_surv_rate += surv_rate;
int SurvRateGroup::next_age_index() {
++_region_num;
return (int) ++_all_regions_allocated;
}
void
SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) {
void SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) {
guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num,
"pre-condition" );
guarantee( _surv_rate[age_in_group] <= 0.00001,
@ -161,9 +140,8 @@ SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) {
}
}
void
SurvRateGroup::all_surviving_words_recorded(bool propagate) {
if (propagate && _region_num > 0) { // conservative
void SurvRateGroup::all_surviving_words_recorded(bool update_predictors) {
if (update_predictors && _region_num > 0) { // conservative
double surv_rate = _surv_rate_pred[_region_num-1]->last();
for (size_t i = _region_num; i < _stats_arrays_length; ++i) {
guarantee( _surv_rate[i] <= 0.00001,
@ -175,24 +153,22 @@ SurvRateGroup::all_surviving_words_recorded(bool propagate) {
double accum = 0.0;
double pred = 0.0;
for (size_t i = 0; i < _stats_arrays_length; ++i) {
pred = _g1p->get_new_prediction(_surv_rate_pred[i]);
pred = get_new_prediction(_surv_rate_pred[i]);
if (pred > 1.0) pred = 1.0;
accum += pred;
_accum_surv_rate_pred[i] = accum;
// gclog_or_tty->print_cr("age %3d, accum %10.2lf", i, accum);
}
_last_pred = pred;
}
#ifndef PRODUCT
void
SurvRateGroup::print() {
void SurvRateGroup::print() {
gclog_or_tty->print_cr("Surv Rate Group: %s (" SIZE_FORMAT " entries)",
_name, _region_num);
for (size_t i = 0; i < _region_num; ++i) {
gclog_or_tty->print_cr(" age " SIZE_FORMAT_W(4) " surv rate %6.2lf %% pred %6.2lf %%",
i, _surv_rate[i] * 100.0,
_g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0);
i, _surv_rate[i] * 100.0,
_predictor->get_new_prediction(_surv_rate_pred[i]) * 100.0);
}
}
@ -211,9 +187,9 @@ SurvRateGroup::print_surv_rate_summary() {
size_t limit = MIN2((int) length, 10);
while (index < limit) {
gclog_or_tty->print_cr(" " SIZE_FORMAT_W(4)
" %6.2lf%% %6.2lf",
index, _summary_surv_rates[index]->avg() * 100.0,
(double) _summary_surv_rates[index]->num());
" %6.2lf%% %6.2lf",
index, _summary_surv_rates[index]->avg() * 100.0,
(double) _summary_surv_rates[index]->num());
++index;
}
@ -230,9 +206,9 @@ SurvRateGroup::print_surv_rate_summary() {
if (index == length || num % 10 == 0) {
gclog_or_tty->print_cr(" " SIZE_FORMAT_W(4) " .. " SIZE_FORMAT_W(4)
" %6.2lf%% %6.2lf",
(index-1) / 10 * 10, index-1, sum / (double) num,
(double) samples / (double) num);
" %6.2lf%% %6.2lf",
(index-1) / 10 * 10, index-1, sum / (double) num,
(double) samples / (double) num);
sum = 0.0;
num = 0;
samples = 0;

@ -27,18 +27,20 @@
#include "utilities/numberSeq.hpp"
class G1CollectorPolicy;
class G1Predictions;
class SurvRateGroup : public CHeapObj<mtGC> {
private:
G1CollectorPolicy* _g1p;
G1Predictions* _predictor;
double get_new_prediction(TruncatedSeq const* seq) const;
const char* _name;
size_t _stats_arrays_length;
double* _surv_rate;
double* _accum_surv_rate_pred;
double _last_pred;
double _accum_surv_rate;
TruncatedSeq** _surv_rate_pred;
NumberSeq** _summary_surv_rates;
size_t _summary_surv_rates_len;
@ -49,18 +51,18 @@ private:
size_t _setup_seq_num;
public:
SurvRateGroup(G1CollectorPolicy* g1p,
SurvRateGroup(G1Predictions* predictor,
const char* name,
size_t summary_surv_rates_len);
void reset();
void start_adding_regions();
void stop_adding_regions();
void record_surviving_words(int age_in_group, size_t surv_words);
void all_surviving_words_recorded(bool propagate);
void all_surviving_words_recorded(bool update_predictors);
const char* name() { return _name; }
size_t region_num() { return _region_num; }
double accum_surv_rate_pred(int age) {
double accum_surv_rate_pred(int age) const {
assert(age >= 0, "must be");
if ((size_t)age < _stats_arrays_length)
return _accum_surv_rate_pred[age];
@ -70,9 +72,7 @@ public:
}
}
double accum_surv_rate(size_t adjustment);
TruncatedSeq* get_seq(size_t age) {
TruncatedSeq* get_seq(size_t age) const {
if (age >= _setup_seq_num) {
guarantee( _setup_seq_num > 0, "invariant" );
age = _setup_seq_num-1;

@ -0,0 +1,241 @@
/*
* Copyright (c) 2015, 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 "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/g1/youngList.hpp"
#include "utilities/ostream.hpp"
YoungList::YoungList(G1CollectedHeap* g1h) :
_g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0),
_survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) {
guarantee(check_list_empty(false), "just making sure...");
}
void YoungList::push_region(HeapRegion *hr) {
assert(!hr->is_young(), "should not already be young");
assert(hr->get_next_young_region() == NULL, "cause it should!");
hr->set_next_young_region(_head);
_head = hr;
_g1h->g1_policy()->set_region_eden(hr, (int) _length);
++_length;
}
void YoungList::add_survivor_region(HeapRegion* hr) {
assert(hr->is_survivor(), "should be flagged as survivor region");
assert(hr->get_next_young_region() == NULL, "cause it should!");
hr->set_next_young_region(_survivor_head);
if (_survivor_head == NULL) {
_survivor_tail = hr;
}
_survivor_head = hr;
++_survivor_length;
}
void YoungList::empty_list(HeapRegion* list) {
while (list != NULL) {
HeapRegion* next = list->get_next_young_region();
list->set_next_young_region(NULL);
list->uninstall_surv_rate_group();
// This is called before a Full GC and all the non-empty /
// non-humongous regions at the end of the Full GC will end up as
// old anyway.
list->set_old();
list = next;
}
}
void YoungList::empty_list() {
assert(check_list_well_formed(), "young list should be well formed");
empty_list(_head);
_head = NULL;
_length = 0;
empty_list(_survivor_head);
_survivor_head = NULL;
_survivor_tail = NULL;
_survivor_length = 0;
_last_sampled_rs_lengths = 0;
assert(check_list_empty(false), "just making sure...");
}
bool YoungList::check_list_well_formed() {
bool ret = true;
uint length = 0;
HeapRegion* curr = _head;
HeapRegion* last = NULL;
while (curr != NULL) {
if (!curr->is_young()) {
gclog_or_tty->print_cr("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " "
"incorrectly tagged (y: %d, surv: %d)",
p2i(curr->bottom()), p2i(curr->end()),
curr->is_young(), curr->is_survivor());
ret = false;
}
++length;
last = curr;
curr = curr->get_next_young_region();
}
ret = ret && (length == _length);
if (!ret) {
gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!");
gclog_or_tty->print_cr("### list has %u entries, _length is %u",
length, _length);
}
return ret;
}
bool YoungList::check_list_empty(bool check_sample) {
bool ret = true;
if (_length != 0) {
gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %u",
_length);
ret = false;
}
if (check_sample && _last_sampled_rs_lengths != 0) {
gclog_or_tty->print_cr("### YOUNG LIST has non-zero last sampled RS lengths");
ret = false;
}
if (_head != NULL) {
gclog_or_tty->print_cr("### YOUNG LIST does not have a NULL head");
ret = false;
}
if (!ret) {
gclog_or_tty->print_cr("### YOUNG LIST does not seem empty");
}
return ret;
}
void
YoungList::rs_length_sampling_init() {
_sampled_rs_lengths = 0;
_curr = _head;
}
bool
YoungList::rs_length_sampling_more() {
return _curr != NULL;
}
void
YoungList::rs_length_sampling_next() {
assert( _curr != NULL, "invariant" );
size_t rs_length = _curr->rem_set()->occupied();
_sampled_rs_lengths += rs_length;
// The current region may not yet have been added to the
// incremental collection set (it gets added when it is
// retired as the current allocation region).
if (_curr->in_collection_set()) {
// Update the collection set policy information for this region
_g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length);
}
_curr = _curr->get_next_young_region();
if (_curr == NULL) {
_last_sampled_rs_lengths = _sampled_rs_lengths;
// gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths);
}
}
void
YoungList::reset_auxilary_lists() {
guarantee( is_empty(), "young list should be empty" );
assert(check_list_well_formed(), "young list should be well formed");
// Add survivor regions to SurvRateGroup.
_g1h->g1_policy()->note_start_adding_survivor_regions();
_g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */);
int young_index_in_cset = 0;
for (HeapRegion* curr = _survivor_head;
curr != NULL;
curr = curr->get_next_young_region()) {
_g1h->g1_policy()->set_region_survivor(curr, young_index_in_cset);
// The region is a non-empty survivor so let's add it to
// the incremental collection set for the next evacuation
// pause.
_g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr);
young_index_in_cset += 1;
}
assert((uint) young_index_in_cset == _survivor_length, "post-condition");
_g1h->g1_policy()->note_stop_adding_survivor_regions();
_head = _survivor_head;
_length = _survivor_length;
if (_survivor_head != NULL) {
assert(_survivor_tail != NULL, "cause it shouldn't be");
assert(_survivor_length > 0, "invariant");
_survivor_tail->set_next_young_region(NULL);
}
// Don't clear the survivor list handles until the start of
// the next evacuation pause - we need it in order to re-tag
// the survivor regions from this evacuation pause as 'young'
// at the start of the next.
_g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */);
assert(check_list_well_formed(), "young list should be well formed");
}
void YoungList::print() {
HeapRegion* lists[] = {_head, _survivor_head};
const char* names[] = {"YOUNG", "SURVIVOR"};
for (uint list = 0; list < ARRAY_SIZE(lists); ++list) {
gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]);
HeapRegion *curr = lists[list];
if (curr == NULL) {
gclog_or_tty->print_cr(" empty");
}
while (curr != NULL) {
gclog_or_tty->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT ", N: " PTR_FORMAT ", age: %4d",
HR_FORMAT_PARAMS(curr),
p2i(curr->prev_top_at_mark_start()),
p2i(curr->next_top_at_mark_start()),
curr->age_in_surv_rate_group_cond());
curr = curr->get_next_young_region();
}
}
gclog_or_tty->cr();
}

@ -0,0 +1,104 @@
/*
* Copyright (c) 2015, 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.
*
*/
#ifndef SHARE_VM_GC_G1_YOUNGLIST_HPP
#define SHARE_VM_GC_G1_YOUNGLIST_HPP
#include "memory/allocation.hpp"
#include "runtime/globals.hpp"
class YoungList : public CHeapObj<mtGC> {
private:
G1CollectedHeap* _g1h;
HeapRegion* _head;
HeapRegion* _survivor_head;
HeapRegion* _survivor_tail;
HeapRegion* _curr;
uint _length;
uint _survivor_length;
size_t _last_sampled_rs_lengths;
size_t _sampled_rs_lengths;
void empty_list(HeapRegion* list);
public:
YoungList(G1CollectedHeap* g1h);
void push_region(HeapRegion* hr);
void add_survivor_region(HeapRegion* hr);
void empty_list();
bool is_empty() { return _length == 0; }
uint length() { return _length; }
uint eden_length() { return length() - survivor_length(); }
uint survivor_length() { return _survivor_length; }
// Currently we do not keep track of the used byte sum for the
// young list and the survivors and it'd be quite a lot of work to
// do so. When we'll eventually replace the young list with
// instances of HeapRegionLinkedList we'll get that for free. So,
// we'll report the more accurate information then.
size_t eden_used_bytes() {
assert(length() >= survivor_length(), "invariant");
return (size_t) eden_length() * HeapRegion::GrainBytes;
}
size_t survivor_used_bytes() {
return (size_t) survivor_length() * HeapRegion::GrainBytes;
}
void rs_length_sampling_init();
bool rs_length_sampling_more();
void rs_length_sampling_next();
void reset_sampled_info() {
_last_sampled_rs_lengths = 0;
}
size_t sampled_rs_lengths() { return _last_sampled_rs_lengths; }
// for development purposes
void reset_auxilary_lists();
void clear() { _head = NULL; _length = 0; }
void clear_survivors() {
_survivor_head = NULL;
_survivor_tail = NULL;
_survivor_length = 0;
}
HeapRegion* first_region() { return _head; }
HeapRegion* first_survivor_region() { return _survivor_head; }
HeapRegion* last_survivor_region() { return _survivor_tail; }
// debugging
bool check_list_well_formed();
bool check_list_empty(bool check_sample = true);
void print();
};
#endif // SHARE_VM_GC_G1_YOUNGLIST_HPP

@ -529,10 +529,7 @@ void PSAdaptiveSizePolicy::compute_old_gen_free_space(
set_decide_at_full_gc(decide_at_full_gc_true);
adjust_promo_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
}
} else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {
// Adjust only for the minor pause time goal
adjust_promo_for_minor_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
} else if(adjusted_mutator_cost() < _throughput_goal) {
} else if (adjusted_mutator_cost() < _throughput_goal) {
// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.
// This sometimes resulted in skipping to the minimize footprint
// code. Change this to try and reduce GC time if mutator time is
@ -670,36 +667,6 @@ void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) {
}
}
void PSAdaptiveSizePolicy::adjust_promo_for_minor_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr) {
if (PSAdjustTenuredGenForMinorPause) {
if (is_full_gc) {
set_decide_at_full_gc(decide_at_full_gc_true);
}
// If the desired eden size is as small as it will get,
// try to adjust the old gen size.
if (*desired_eden_size_ptr <= _space_alignment) {
// Vary the old gen size to reduce the young gen pause. This
// may not be a good idea. This is just a test.
if (minor_pause_old_estimator()->decrement_will_decrease()) {
set_change_old_gen_for_min_pauses(decrease_old_gen_for_min_pauses_true);
*desired_promo_size_ptr =
_promo_size - promo_decrement_aligned_down(*desired_promo_size_ptr);
} else {
set_change_old_gen_for_min_pauses(increase_old_gen_for_min_pauses_true);
size_t promo_heap_delta =
promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);
if ((*desired_promo_size_ptr + promo_heap_delta) >
*desired_promo_size_ptr) {
*desired_promo_size_ptr =
_promo_size + promo_heap_delta;
}
}
}
}
}
void PSAdaptiveSizePolicy::adjust_eden_for_minor_pause_time(bool is_full_gc,
size_t* desired_eden_size_ptr) {
@ -733,10 +700,7 @@ void PSAdaptiveSizePolicy::adjust_promo_for_pause_time(bool is_full_gc,
// a change less than the required alignment is probably not worth
// attempting.
if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {
adjust_promo_for_minor_pause_time(is_full_gc, desired_promo_size_ptr, desired_eden_size_ptr);
// major pause adjustments
} else if (is_full_gc) {
if (_avg_minor_pause->padded_average() <= _avg_major_pause->padded_average() && is_full_gc) {
// Adjust for the major pause time only at full gc's because the
// affects of a change can only be seen at full gc's.
@ -774,44 +738,8 @@ void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc,
// a change less than the required alignment is probably not worth
// attempting.
if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {
adjust_eden_for_minor_pause_time(is_full_gc,
desired_eden_size_ptr);
// major pause adjustments
} else if (is_full_gc) {
// Adjust for the major pause time only at full gc's because the
// affects of a change can only be seen at full gc's.
if (PSAdjustYoungGenForMajorPause) {
// If the promo size is at the minimum (i.e., the old gen
// size will not actually decrease), consider changing the
// young gen size.
if (*desired_promo_size_ptr < _space_alignment) {
// If increasing the young generation will decrease the old gen
// pause, do it.
// During startup there is noise in the statistics for deciding
// on whether to increase or decrease the young gen size. For
// some number of iterations, just try to increase the young
// gen size if the major pause is too long to try and establish
// good statistics for later decisions.
if (major_pause_young_estimator()->increment_will_decrease() ||
(_young_gen_change_for_major_pause_count
<= AdaptiveSizePolicyInitializingSteps)) {
set_change_young_gen_for_maj_pauses(
increase_young_gen_for_maj_pauses_true);
eden_heap_delta = eden_increment_aligned_up(*desired_eden_size_ptr);
*desired_eden_size_ptr = _eden_size + eden_heap_delta;
_young_gen_change_for_major_pause_count++;
} else {
// Record that decreasing the young gen size would decrease
// the major pause
set_change_young_gen_for_maj_pauses(
decrease_young_gen_for_maj_pauses_true);
eden_heap_delta = eden_decrement_aligned_down(*desired_eden_size_ptr);
*desired_eden_size_ptr = _eden_size - eden_heap_delta;
}
}
}
adjust_eden_for_minor_pause_time(is_full_gc, desired_eden_size_ptr);
}
if (PrintAdaptiveSizePolicy && Verbose) {
gclog_or_tty->print_cr(
"PSAdaptiveSizePolicy::adjust_eden_for_pause_time "

@ -134,10 +134,6 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
AdaptivePaddedAverage* avg_major_pause() const { return _avg_major_pause; }
double gc_minor_pause_goal_sec() const { return _gc_minor_pause_goal_sec; }
// Change the young generation size to achieve a minor GC pause time goal
void adjust_promo_for_minor_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr,
size_t* desired_eden_size_ptr);
void adjust_eden_for_minor_pause_time(bool is_full_gc,
size_t* desired_eden_size_ptr);
// Change the generation sizes to achieve a GC pause time goal

@ -1351,13 +1351,6 @@ HeapWord*
PSParallelCompact::compute_dense_prefix(const SpaceId id,
bool maximum_compaction)
{
if (ParallelOldGCSplitALot) {
if (_space_info[id].dense_prefix() != _space_info[id].space()->bottom()) {
// The value was chosen to provoke splitting a young gen space; use it.
return _space_info[id].dense_prefix();
}
}
const size_t region_size = ParallelCompactData::RegionSize;
const ParallelCompactData& sd = summary_data();
@ -1430,220 +1423,9 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id,
}
}
#if 0
// Something to consider: if the region with the best ratio is 'close to' the
// first region w/free space, choose the first region with free space
// ("first-free"). The first-free region is usually near the start of the
// heap, which means we are copying most of the heap already, so copy a bit
// more to get complete compaction.
if (pointer_delta(best_cp, full_cp, sizeof(RegionData)) < 4) {
_maximum_compaction_gc_num = total_invocations();
best_cp = full_cp;
}
#endif // #if 0
return sd.region_to_addr(best_cp);
}
#ifndef PRODUCT
void
PSParallelCompact::fill_with_live_objects(SpaceId id, HeapWord* const start,
size_t words)
{
if (TraceParallelOldGCSummaryPhase) {
tty->print_cr("fill_with_live_objects [" PTR_FORMAT " " PTR_FORMAT ") "
SIZE_FORMAT, p2i(start), p2i(start + words), words);
}
ObjectStartArray* const start_array = _space_info[id].start_array();
CollectedHeap::fill_with_objects(start, words);
for (HeapWord* p = start; p < start + words; p += oop(p)->size()) {
_mark_bitmap.mark_obj(p, words);
_summary_data.add_obj(p, words);
start_array->allocate_block(p);
}
}
void
PSParallelCompact::summarize_new_objects(SpaceId id, HeapWord* start)
{
ParallelCompactData& sd = summary_data();
MutableSpace* space = _space_info[id].space();
// Find the source and destination start addresses.
HeapWord* const src_addr = sd.region_align_down(start);
HeapWord* dst_addr;
if (src_addr < start) {
dst_addr = sd.addr_to_region_ptr(src_addr)->destination();
} else if (src_addr > space->bottom()) {
// The start (the original top() value) is aligned to a region boundary so
// the associated region does not have a destination. Compute the
// destination from the previous region.
RegionData* const cp = sd.addr_to_region_ptr(src_addr) - 1;
dst_addr = cp->destination() + cp->data_size();
} else {
// Filling the entire space.
dst_addr = space->bottom();
}
assert(dst_addr != NULL, "sanity");
// Update the summary data.
bool result = _summary_data.summarize(_space_info[id].split_info(),
src_addr, space->top(), NULL,
dst_addr, space->end(),
_space_info[id].new_top_addr());
assert(result, "should not fail: bad filler object size");
}
void
PSParallelCompact::provoke_split_fill_survivor(SpaceId id)
{
if (total_invocations() % (ParallelOldGCSplitInterval * 3) != 0) {
return;
}
MutableSpace* const space = _space_info[id].space();
if (space->is_empty()) {
HeapWord* b = space->bottom();
HeapWord* t = b + space->capacity_in_words() / 2;
space->set_top(t);
if (ZapUnusedHeapArea) {
space->set_top_for_allocations();
}
size_t min_size = CollectedHeap::min_fill_size();
size_t obj_len = min_size;
while (b + obj_len <= t) {
CollectedHeap::fill_with_object(b, obj_len);
mark_bitmap()->mark_obj(b, obj_len);
summary_data().add_obj(b, obj_len);
b += obj_len;
obj_len = (obj_len & (min_size*3)) + min_size; // 8 16 24 32 8 16 24 32 ...
}
if (b < t) {
// The loop didn't completely fill to t (top); adjust top downward.
space->set_top(b);
if (ZapUnusedHeapArea) {
space->set_top_for_allocations();
}
}
HeapWord** nta = _space_info[id].new_top_addr();
bool result = summary_data().summarize(_space_info[id].split_info(),
space->bottom(), space->top(), NULL,
space->bottom(), space->end(), nta);
assert(result, "space must fit into itself");
}
}
void
PSParallelCompact::provoke_split(bool & max_compaction)
{
if (total_invocations() % ParallelOldGCSplitInterval != 0) {
return;
}
const size_t region_size = ParallelCompactData::RegionSize;
ParallelCompactData& sd = summary_data();
MutableSpace* const eden_space = _space_info[eden_space_id].space();
MutableSpace* const from_space = _space_info[from_space_id].space();
const size_t eden_live = pointer_delta(eden_space->top(),
_space_info[eden_space_id].new_top());
const size_t from_live = pointer_delta(from_space->top(),
_space_info[from_space_id].new_top());
const size_t min_fill_size = CollectedHeap::min_fill_size();
const size_t eden_free = pointer_delta(eden_space->end(), eden_space->top());
const size_t eden_fillable = eden_free >= min_fill_size ? eden_free : 0;
const size_t from_free = pointer_delta(from_space->end(), from_space->top());
const size_t from_fillable = from_free >= min_fill_size ? from_free : 0;
// Choose the space to split; need at least 2 regions live (or fillable).
SpaceId id;
MutableSpace* space;
size_t live_words;
size_t fill_words;
if (eden_live + eden_fillable >= region_size * 2) {
id = eden_space_id;
space = eden_space;
live_words = eden_live;
fill_words = eden_fillable;
} else if (from_live + from_fillable >= region_size * 2) {
id = from_space_id;
space = from_space;
live_words = from_live;
fill_words = from_fillable;
} else {
return; // Give up.
}
assert(fill_words == 0 || fill_words >= min_fill_size, "sanity");
if (live_words < region_size * 2) {
// Fill from top() to end() w/live objects of mixed sizes.
HeapWord* const fill_start = space->top();
live_words += fill_words;
space->set_top(fill_start + fill_words);
if (ZapUnusedHeapArea) {
space->set_top_for_allocations();
}
HeapWord* cur_addr = fill_start;
while (fill_words > 0) {
const size_t r = (size_t)os::random() % (region_size / 2) + min_fill_size;
size_t cur_size = MIN2(align_object_size_(r), fill_words);
if (fill_words - cur_size < min_fill_size) {
cur_size = fill_words; // Avoid leaving a fragment too small to fill.
}
CollectedHeap::fill_with_object(cur_addr, cur_size);
mark_bitmap()->mark_obj(cur_addr, cur_size);
sd.add_obj(cur_addr, cur_size);
cur_addr += cur_size;
fill_words -= cur_size;
}
summarize_new_objects(id, fill_start);
}
max_compaction = false;
// Manipulate the old gen so that it has room for about half of the live data
// in the target young gen space (live_words / 2).
id = old_space_id;
space = _space_info[id].space();
const size_t free_at_end = space->free_in_words();
const size_t free_target = align_object_size(live_words / 2);
const size_t dead = pointer_delta(space->top(), _space_info[id].new_top());
if (free_at_end >= free_target + min_fill_size) {
// Fill space above top() and set the dense prefix so everything survives.
HeapWord* const fill_start = space->top();
const size_t fill_size = free_at_end - free_target;
space->set_top(space->top() + fill_size);
if (ZapUnusedHeapArea) {
space->set_top_for_allocations();
}
fill_with_live_objects(id, fill_start, fill_size);
summarize_new_objects(id, fill_start);
_space_info[id].set_dense_prefix(sd.region_align_down(space->top()));
} else if (dead + free_at_end > free_target) {
// Find a dense prefix that makes the right amount of space available.
HeapWord* cur = sd.region_align_down(space->top());
HeapWord* cur_destination = sd.addr_to_region_ptr(cur)->destination();
size_t dead_to_right = pointer_delta(space->end(), cur_destination);
while (dead_to_right < free_target) {
cur -= region_size;
cur_destination = sd.addr_to_region_ptr(cur)->destination();
dead_to_right = pointer_delta(space->end(), cur_destination);
}
_space_info[id].set_dense_prefix(cur);
}
}
#endif // #ifndef PRODUCT
void PSParallelCompact::summarize_spaces_quick()
{
for (unsigned int i = 0; i < last_space_id; ++i) {
@ -1655,12 +1437,6 @@ void PSParallelCompact::summarize_spaces_quick()
assert(result, "space must fit into itself");
_space_info[i].set_dense_prefix(space->bottom());
}
#ifndef PRODUCT
if (ParallelOldGCSplitALot) {
provoke_split_fill_survivor(to_space_id);
}
#endif // #ifndef PRODUCT
}
void PSParallelCompact::fill_dense_prefix_end(SpaceId id)
@ -1745,8 +1521,7 @@ void
PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction)
{
assert(id < last_space_id, "id out of range");
assert(_space_info[id].dense_prefix() == _space_info[id].space()->bottom() ||
ParallelOldGCSplitALot && id == old_space_id,
assert(_space_info[id].dense_prefix() == _space_info[id].space()->bottom(),
"should have been reset in summarize_spaces_quick()");
const MutableSpace* space = _space_info[id].space();
@ -1866,11 +1641,6 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
// XXX - should also try to expand
maximum_compaction = true;
}
#ifndef PRODUCT
if (ParallelOldGCSplitALot && old_space_total_live < old_capacity) {
provoke_split(maximum_compaction);
}
#endif // #ifndef PRODUCT
// Old generations.
summarize_space(old_space_id, maximum_compaction);

@ -1059,24 +1059,6 @@ class PSParallelCompact : AllStatic {
// Clear the summary data source_region field for the specified addresses.
static void clear_source_region(HeapWord* beg_addr, HeapWord* end_addr);
#ifndef PRODUCT
// Routines to provoke splitting a young gen space (ParallelOldGCSplitALot).
// Fill the region [start, start + words) with live object(s). Only usable
// for the old and permanent generations.
static void fill_with_live_objects(SpaceId id, HeapWord* const start,
size_t words);
// Include the new objects in the summary data.
static void summarize_new_objects(SpaceId id, HeapWord* start);
// Add live objects to a survivor space since it's rare that both survivors
// are non-empty.
static void provoke_split_fill_survivor(SpaceId id);
// Add live objects and/or choose the dense prefix to provoke splitting.
static void provoke_split(bool & maximum_compaction);
#endif
static void summarize_spaces_quick();
static void summarize_space(SpaceId id, bool maximum_compaction);
static void summary_phase(ParCompactionManager* cm, bool maximum_compaction);

@ -297,11 +297,6 @@ bool PSScavenge::invoke_no_policy() {
young_gen->eden_space()->accumulate_statistics();
}
if (ZapUnusedHeapArea) {
// Save information needed to minimize mangling
heap->record_gen_tops_before_GC();
}
heap->print_heap_before_gc();
heap->trace_heap_before_gc(&_gc_tracer);
@ -344,13 +339,10 @@ bool PSScavenge::invoke_no_policy() {
CardTableExtension::verify_all_young_refs_imprecise();
}
if (!ScavengeWithObjectsInToSpace) {
assert(young_gen->to_space()->is_empty(),
"Attempt to scavenge with live objects in to_space");
young_gen->to_space()->clear(SpaceDecorator::Mangle);
} else if (ZapUnusedHeapArea) {
young_gen->to_space()->mangle_unused_area();
}
assert(young_gen->to_space()->is_empty(),
"Attempt to scavenge with live objects in to_space");
young_gen->to_space()->clear(SpaceDecorator::Mangle);
save_to_space_top_before_gc();
#if defined(COMPILER2) || INCLUDE_JVMCI
@ -681,12 +673,6 @@ bool PSScavenge::invoke_no_policy() {
heap->print_heap_after_gc();
heap->trace_heap_after_gc(&_gc_tracer);
if (ZapUnusedHeapArea) {
young_gen->eden_space()->check_mangled_unused_area_complete();
young_gen->from_space()->check_mangled_unused_area_complete();
young_gen->to_space()->check_mangled_unused_area_complete();
}
scavenge_exit.update();
if (PrintGCTaskTimeStamps) {
@ -768,15 +754,13 @@ bool PSScavenge::should_attempt_scavenge() {
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
if (!ScavengeWithObjectsInToSpace) {
// Do not attempt to promote unless to_space is empty
if (!young_gen->to_space()->is_empty()) {
_consecutive_skipped_scavenges++;
if (UsePerfData) {
counters->update_scavenge_skipped(to_space_not_empty);
}
return false;
// Do not attempt to promote unless to_space is empty
if (!young_gen->to_space()->is_empty()) {
_consecutive_skipped_scavenges++;
if (UsePerfData) {
counters->update_scavenge_skipped(to_space_not_empty);
}
return false;
}
// Test to see if the scavenge will likely fail.

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/serial/defNewGeneration.inline.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/collectorCounters.hpp"
#include "gc/shared/gcHeapSummary.hpp"
#include "gc/shared/gcLocker.inline.hpp"
@ -33,7 +34,6 @@
#include "gc/shared/gcTraceTime.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/genRemSet.hpp"
#include "gc/shared/generationSpec.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/space.inline.hpp"
@ -69,8 +69,7 @@ bool DefNewGeneration::IsAliveClosure::do_object_b(oop p) {
DefNewGeneration::KeepAliveClosure::
KeepAliveClosure(ScanWeakRefClosure* cl) : _cl(cl) {
GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
_rs = (CardTableRS*)rs;
_rs = GenCollectedHeap::heap()->rem_set();
}
void DefNewGeneration::KeepAliveClosure::do_oop(oop* p) { DefNewGeneration::KeepAliveClosure::do_oop_work(p); }

@ -117,7 +117,7 @@ void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_so
// can clear the card table. Otherwise, we must invalidate
// it (consider all cards dirty). In the future, we might consider doing
// compaction within generations only, and doing card-table sliding.
GenRemSet* rs = gch->rem_set();
CardTableRS* rs = gch->rem_set();
Generation* old_gen = gch->old_gen();
// Clear/invalidate below make use of the "prev_used_regions" saved earlier.

@ -196,7 +196,9 @@ public:
virtual void do_cld(ClassLoaderData* cld);
void do_cld_nv(ClassLoaderData* cld);
void set_ref_processor(ReferenceProcessor* rp) { _ref_processor = rp; }
void set_ref_processor(ReferenceProcessor* rp) {
set_ref_processor_internal(rp);
}
};
class PreservedMark VALUE_OBJ_CLASS_SPEC {

@ -42,7 +42,7 @@
TenuredGeneration::TenuredGeneration(ReservedSpace rs,
size_t initial_byte_size,
GenRemSet* remset) :
CardTableRS* remset) :
CardGeneration(rs, initial_byte_size, remset)
{
HeapWord* bottom = (HeapWord*) _virtual_space.low();

@ -58,7 +58,7 @@ class TenuredGeneration: public CardGeneration {
public:
TenuredGeneration(ReservedSpace rs,
size_t initial_byte_size,
GenRemSet* remset);
CardTableRS* remset);
Generation::Name kind() { return Generation::MarkSweepCompact; }

@ -26,9 +26,9 @@
#include "gc/shared/blockOffsetTable.inline.hpp"
#include "gc/shared/cardGeneration.inline.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/genRemSet.hpp"
#include "gc/shared/generationSpec.hpp"
#include "gc/shared/space.inline.hpp"
#include "memory/iterator.hpp"
@ -37,7 +37,7 @@
CardGeneration::CardGeneration(ReservedSpace rs,
size_t initial_byte_size,
GenRemSet* remset) :
CardTableRS* remset) :
Generation(rs, initial_byte_size), _rs(remset),
_shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
_used_at_prologue()

@ -37,7 +37,7 @@ class CardGeneration: public Generation {
friend class VMStructs;
protected:
// This is shared with other generations.
GenRemSet* _rs;
CardTableRS* _rs;
// This is local to this generation.
BlockOffsetSharedArray* _bts;
@ -52,7 +52,7 @@ class CardGeneration: public Generation {
size_t _capacity_at_prologue;
size_t _used_at_prologue;
CardGeneration(ReservedSpace rs, size_t initial_byte_size, GenRemSet* remset);
CardGeneration(ReservedSpace rs, size_t initial_byte_size, CardTableRS* remset);
virtual void assert_correct_size_change_locking() = 0;

@ -34,8 +34,48 @@
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
class HasAccumulatedModifiedOopsClosure : public KlassClosure {
bool _found;
public:
HasAccumulatedModifiedOopsClosure() : _found(false) {}
void do_klass(Klass* klass) {
if (_found) {
return;
}
if (klass->has_accumulated_modified_oops()) {
_found = true;
}
}
bool found() {
return _found;
}
};
bool KlassRemSet::mod_union_is_clear() {
HasAccumulatedModifiedOopsClosure closure;
ClassLoaderDataGraph::classes_do(&closure);
return !closure.found();
}
class ClearKlassModUnionClosure : public KlassClosure {
public:
void do_klass(Klass* klass) {
if (klass->has_accumulated_modified_oops()) {
klass->clear_accumulated_modified_oops();
}
}
};
void KlassRemSet::clear_mod_union() {
ClearKlassModUnionClosure closure;
ClassLoaderDataGraph::classes_do(&closure);
}
CardTableRS::CardTableRS(MemRegion whole_heap) :
GenRemSet(),
_bs(NULL),
_cur_youngergen_card_val(youngergenP1_card)
{
_ct_bs = new CardTableModRefBSForCTRS(whole_heap);

@ -26,16 +26,26 @@
#define SHARE_VM_GC_SHARED_CARDTABLERS_HPP
#include "gc/shared/cardTableModRefBSForCTRS.hpp"
#include "gc/shared/genRemSet.hpp"
#include "memory/memRegion.hpp"
class Space;
class OopsInGenClosure;
// This kind of "GenRemSet" uses a card table both as shared data structure
// Helper to remember modified oops in all klasses.
class KlassRemSet {
bool _accumulate_modified_oops;
public:
KlassRemSet() : _accumulate_modified_oops(false) {}
void set_accumulate_modified_oops(bool value) { _accumulate_modified_oops = value; }
bool accumulate_modified_oops() { return _accumulate_modified_oops; }
bool mod_union_is_clear();
void clear_mod_union();
};
// This RemSet uses a card table both as shared data structure
// for a mod ref barrier set and for the rem set information.
class CardTableRS: public GenRemSet {
class CardTableRS: public CHeapObj<mtGC> {
friend class VMStructs;
// Below are private classes used in impl.
friend class VerifyCTSpaceClosure;
@ -54,9 +64,10 @@ class CardTableRS: public GenRemSet {
return CardTableModRefBSForCTRS::card_is_dirty_wrt_gen_iter(cv);
}
CardTableModRefBSForCTRS* _ct_bs;
KlassRemSet _klass_rem_set;
BarrierSet* _bs;
virtual void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl, uint n_threads);
CardTableModRefBSForCTRS* _ct_bs;
void verify_space(Space* s, HeapWord* gen_start);
@ -104,11 +115,18 @@ public:
CardTableRS(MemRegion whole_heap);
~CardTableRS();
// *** GenRemSet functions.
CardTableRS* as_CardTableRS() { return this; }
// Return the barrier set associated with "this."
BarrierSet* bs() { return _bs; }
// Set the barrier set.
void set_bs(BarrierSet* bs) { _bs = bs; }
KlassRemSet* klass_rem_set() { return &_klass_rem_set; }
CardTableModRefBSForCTRS* ct_bs() { return _ct_bs; }
void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl, uint n_threads);
// Override.
void prepare_for_younger_refs_iterate(bool parallel);

@ -152,7 +152,7 @@ bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
return result;
}
GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap) {
CardTableRS* CollectorPolicy::create_rem_set(MemRegion whole_heap) {
return new CardTableRS(whole_heap);
}
@ -173,7 +173,7 @@ size_t CollectorPolicy::compute_heap_alignment() {
// byte entry and the os page size is 4096, the maximum heap size should
// be 512*4096 = 2MB aligned.
size_t alignment = GenRemSet::max_alignment_constraint();
size_t alignment = CardTableRS::ct_max_alignment_constraint();
if (UseLargePages) {
// In presence of large pages we have to make sure that our

@ -26,7 +26,7 @@
#define SHARE_VM_GC_SHARED_COLLECTORPOLICY_HPP
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/genRemSet.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/generationSpec.hpp"
#include "memory/allocation.hpp"
#include "utilities/macros.hpp"
@ -143,7 +143,7 @@ class CollectorPolicy : public CHeapObj<mtGC> {
#endif // INCLUDE_ALL_GCS
virtual GenRemSet* create_rem_set(MemRegion reserved);
virtual CardTableRS* create_rem_set(MemRegion reserved);
// This method controls how a collector satisfies a request
// for a block of memory. "gc_time_limit_was_exceeded" will

@ -60,12 +60,12 @@ GCIdMark::~GCIdMark() {
}
GCIdMarkAndRestore::GCIdMarkAndRestore() : _gc_id(GCId::create()) {
_previous_gc_id = GCId::current(); // will assert that the GC Id is not undefined
_previous_gc_id = GCId::current_raw();
currentNamedthread()->set_gc_id(_gc_id);
}
GCIdMarkAndRestore::GCIdMarkAndRestore(uint gc_id) : _gc_id(gc_id) {
_previous_gc_id = GCId::current(); // will assert that the GC Id is not undefinied
_previous_gc_id = GCId::current_raw();
currentNamedthread()->set_gc_id(_gc_id);
}

@ -433,7 +433,7 @@ void GenCollectedHeap::do_collection(bool full,
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
}
GCIdMark gc_id_mark;
GCIdMarkAndRestore gc_id_mark;
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
collector_policy()->should_clear_all_soft_refs();
@ -823,7 +823,7 @@ bool GenCollectedHeap::create_cms_collector() {
assert(_gen_policy->is_concurrent_mark_sweep_policy(), "Unexpected policy type");
CMSCollector* collector =
new CMSCollector((ConcurrentMarkSweepGeneration*)_old_gen,
_rem_set->as_CardTableRS(),
_rem_set,
_gen_policy->as_concurrent_mark_sweep_policy());
if (collector == NULL || !collector->completed_initialization()) {

@ -64,8 +64,8 @@ private:
Generation* _young_gen;
Generation* _old_gen;
// The singleton Gen Remembered Set.
GenRemSet* _rem_set;
// The singleton CardTable Remembered Set.
CardTableRS* _rem_set;
// The generational collector policy.
GenCollectorPolicy* _gen_policy;
@ -361,9 +361,9 @@ public:
// collection.
virtual bool is_maximal_no_gc() const;
// This function returns the "GenRemSet" object that allows us to scan
// This function returns the CardTableRS object that allows us to scan
// generations in a fully generational heap.
GenRemSet* rem_set() { return _rem_set; }
CardTableRS* rem_set() { return _rem_set; }
// Convenience function to be used in situations where the heap type can be
// asserted to be this type.

@ -157,7 +157,7 @@ class FilteringClosure: public ExtendedOopClosure {
}
public:
FilteringClosure(HeapWord* boundary, ExtendedOopClosure* cl) :
ExtendedOopClosure(cl->_ref_processor), _boundary(boundary),
ExtendedOopClosure(cl->ref_processor()), _boundary(boundary),
_cl(cl) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);

@ -29,7 +29,6 @@
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.hpp"
#include "gc/shared/genRemSet.hpp"
#include "gc/shared/generation.hpp"
#include "gc/shared/space.hpp"
@ -43,8 +42,7 @@ inline void OopsInGenClosure::set_generation(Generation* gen) {
_gen_boundary = _gen->reserved().start();
// Barrier set for the heap, must be set after heap is initialized
if (_rs == NULL) {
GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
_rs = (CardTableRS*)rs;
_rs = GenCollectedHeap::heap()->rem_set();
}
}

@ -1,77 +0,0 @@
/*
* Copyright (c) 2001, 2015, 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 "classfile/classLoaderData.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/genRemSet.hpp"
#include "oops/klass.hpp"
// This kind of "BarrierSet" allows a "CollectedHeap" to detect and
// enumerate ref fields that have been modified (since the last
// enumeration.)
uintx GenRemSet::max_alignment_constraint() {
return CardTableRS::ct_max_alignment_constraint();
}
class HasAccumulatedModifiedOopsClosure : public KlassClosure {
bool _found;
public:
HasAccumulatedModifiedOopsClosure() : _found(false) {}
void do_klass(Klass* klass) {
if (_found) {
return;
}
if (klass->has_accumulated_modified_oops()) {
_found = true;
}
}
bool found() {
return _found;
}
};
bool KlassRemSet::mod_union_is_clear() {
HasAccumulatedModifiedOopsClosure closure;
ClassLoaderDataGraph::classes_do(&closure);
return !closure.found();
}
class ClearKlassModUnionClosure : public KlassClosure {
public:
void do_klass(Klass* klass) {
if (klass->has_accumulated_modified_oops()) {
klass->clear_accumulated_modified_oops();
}
}
};
void KlassRemSet::clear_mod_union() {
ClearKlassModUnionClosure closure;
ClassLoaderDataGraph::classes_do(&closure);
}

Some files were not shown because too many files have changed in this diff Show More