--- a/.hgtags Wed Oct 18 13:52:32 2017 -0700
+++ b/.hgtags Wed Oct 18 21:05:09 2017 +0000
@@ -450,3 +450,5 @@
22850b3a55240253841b9a425ad60a7fcdb22d47 jdk-10+23
3b201865d5c1f244f555cad58da599c9261286d8 jdk-10+24
8eb5e3ccee560c28ac9b1df2670adac2b3d36fad jdk-10+25
+1129253d3bc728a2963ba411ab9dd1adf358fb6b jdk-10+26
+b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27
--- a/bin/jib.sh Wed Oct 18 13:52:32 2017 -0700
+++ b/bin/jib.sh Wed Oct 18 21:05:09 2017 +0000
@@ -39,7 +39,7 @@
jib_repository="jdk-virtual"
jib_organization="jpg/infra/builddeps"
jib_module="jib"
- jib_revision="2.0-SNAPSHOT"
+ jib_revision="3.0-SNAPSHOT"
jib_ext="jib.sh.gz"
closed_script="${mydir}/../../closed/make/conf/jib-install.conf"
@@ -146,4 +146,9 @@
install_jib
fi
+# Provide a reasonable default for the --src-dir parameter if run out of tree
+if [ -z "${JIB_SRC_DIR}" ]; then
+ export JIB_SRC_DIR="${mydir}/../"
+fi
+
${installed_jib_script} "$@"
--- a/make/Bundles.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/Bundles.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -70,9 +70,14 @@
$$(call SetIfEmpty, $1_UNZIP_DEBUGINFO, false)
$(BUNDLES_OUTPUTDIR)/$$($1_BUNDLE_NAME): $$($1_FILES)
+ # If any of the files contain a space in the file name, CacheFind
+ # will have replaced it with ?. Tar does not accept that so need to
+ # switch it back.
$$(foreach d, $$($1_BASE_DIRS), \
$$(eval $$(call ListPathsSafely, \
$1_$$d_RELATIVE_FILES, $$($1_$$d_LIST_FILE))) \
+ $$(CAT) $$($1_$$d_LIST_FILE) | $$(TR) '?' ' ' > $$($1_$$d_LIST_FILE).tmp \
+ && $(MV) $$($1_$$d_LIST_FILE).tmp $$($1_$$d_LIST_FILE) $$(NEWLINE) \
)
$$(call MakeDir, $$(@D))
ifneq ($$($1_SPECIAL_INCLUDES), )
--- a/make/CompileDemos.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/CompileDemos.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -37,9 +37,13 @@
include TextFileProcessing.gmk
include ZipArchive.gmk
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, CompileDemos-pre.gmk))
+
# Prepare the find cache.
-$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/demo \
- $(TOPDIR)/src/*/demo)))
+DEMO_SRC_DIRS += $(TOPDIR)/src/demo
+
+$(eval $(call FillCacheFind, $(wildcard $(DEMO_SRC_DIRS))))
# Append demo goals to this variable.
TARGETS =
@@ -303,7 +307,7 @@
################################################################################
# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, CompileDemos.gmk))
+$(eval $(call IncludeCustomExtension, CompileDemos-post.gmk))
all: $(TARGETS)
images: $(IMAGES_TARGETS)
--- a/make/Init.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/Init.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -267,8 +267,9 @@
$(ECHO) "Re-running configure using default settings"
endif
( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \
+ CUSTOM_ROOT="$(CUSTOM_ROOT)" \
CUSTOM_CONFIG_DIR="$(CUSTOM_CONFIG_DIR)" \
- $(BASH) $(CONFIGURE_CMD) $(CONFIGURE_COMMAND_LINE) )
+ $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) )
##############################################################################
# The main target, for delegating into Main.gmk
--- a/make/InitSupport.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/InitSupport.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -70,10 +70,10 @@
$(subst \ ,\#,$(MAKEOVERRIDES))))
# Setup information about available configurations, if any.
- ifeq ($(CUSTOM_BUILD_DIR), )
+ ifneq ($(CUSTOM_ROOT), )
+ build_dir=$(CUSTOM_ROOT)/build
+ else
build_dir=$(topdir)/build
- else
- build_dir=$(CUSTOM_BUILD_DIR)
endif
all_spec_files=$(wildcard $(build_dir)/*/spec.gmk)
# Extract the configuration names from the path
@@ -227,7 +227,11 @@
else
# Use spec.gmk files in the build output directory
ifeq ($$(all_spec_files),)
- $$(info Error: No configurations found for $$(topdir).)
+ ifneq ($(CUSTOM_ROOT), )
+ $$(info Error: No configurations found for $$(CUSTOM_ROOT).)
+ else
+ $$(info Error: No configurations found for $$(topdir).)
+ endif
$$(info Please run 'bash configure' to create a configuration.)
$$(info )
$$(error Cannot continue)
--- a/make/MacBundles.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/MacBundles.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -49,22 +49,17 @@
BUNDLE_VENDOR := $(COMPANY_NAME)
endif
- JDK_FILE_LIST := $(shell $(FIND) $(JDK_IMAGE_DIR))
- JRE_FILE_LIST := $(shell $(FIND) $(JRE_IMAGE_DIR))
-
- JDK_TARGET_LIST := $(subst $(JDK_IMAGE_DIR)/,$(JDK_MACOSX_CONTENTS_DIR)/Home/,$(JDK_FILE_LIST))
- JRE_TARGET_LIST := $(subst $(JRE_IMAGE_DIR)/,$(JRE_MACOSX_CONTENTS_DIR)/Home/,$(JRE_FILE_LIST))
+ $(eval $(call SetupCopyFiles, COPY_JDK_IMAGE, \
+ SRC := $(JDK_IMAGE_DIR), \
+ DEST := $(JDK_MACOSX_CONTENTS_DIR)/Home, \
+ FILES := $(call CacheFind, $(JDK_IMAGE_DIR)), \
+ ))
- # Copy empty directories (jre/lib/applet).
- $(JDK_MACOSX_CONTENTS_DIR)/Home/%: $(JDK_IMAGE_DIR)/%
- $(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
- $(MKDIR) -p $(@D)
- if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi
-
- $(JRE_MACOSX_CONTENTS_DIR)/Home/%: $(JRE_IMAGE_DIR)/%
- $(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
- $(MKDIR) -p $(@D)
- if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi
+ $(eval $(call SetupCopyFiles, COPY_JRE_IMAGE, \
+ SRC := $(JRE_IMAGE_DIR), \
+ DEST := $(JRE_MACOSX_CONTENTS_DIR)/Home, \
+ FILES := $(call CacheFind, $(JRE_IMAGE_DIR)), \
+ ))
$(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib:
$(call LogInfo, Creating link $(patsubst $(OUTPUTDIR)/%,%,$@))
@@ -102,11 +97,11 @@
@@VENDOR@@ => $(BUNDLE_VENDOR) , \
))
- jdk-bundle: $(JDK_TARGET_LIST) $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \
+ jdk-bundle: $(COPY_JDK_IMAGE) $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \
$(BUILD_JDK_PLIST)
$(SETFILE) -a B $(dir $(JDK_MACOSX_CONTENTS_DIR))
- jre-bundle: $(JRE_TARGET_LIST) $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \
+ jre-bundle: $(COPY_JRE_IMAGE) $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \
$(BUILD_JRE_PLIST)
$(SETFILE) -a B $(dir $(JRE_MACOSX_CONTENTS_DIR))
--- a/make/RunTests.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/RunTests.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -351,6 +351,9 @@
$1_JTREG_BASIC_OPTIONS += -automatic -keywords:\!ignore -ignore:quiet
+ # Make it possible to specify the JIB_DATA_DIR for tests using the
+ # JIB Artifact resolver
+ $1_JTREG_BASIC_OPTIONS += -e:JIB_DATA_DIR
# Some tests needs to find a boot JDK using the JDK8_HOME variable.
$1_JTREG_BASIC_OPTIONS += -e:JDK8_HOME=$$(BOOT_JDK)
--- a/make/autoconf/basics.m4 Wed Oct 18 13:52:32 2017 -0700
+++ b/make/autoconf/basics.m4 Wed Oct 18 21:05:09 2017 +0000
@@ -766,13 +766,10 @@
AC_ARG_WITH(conf-name, [AS_HELP_STRING([--with-conf-name],
[use this as the name of the configuration @<:@generated from important configuration options@:>@])],
[ CONF_NAME=${with_conf_name} ])
- AC_ARG_WITH(output-base-dir, [AS_HELP_STRING([--with-output-base-dir],
- [override the default output base directory @<:@./build@:>@])],
- [ OUTPUT_BASE=${with_output_base_dir} ], [ OUTPUT_BASE="$TOPDIR/build" ] )
# Test from where we are running configure, in or outside of src root.
AC_MSG_CHECKING([where to store configuration])
- if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$TOPDIR/common" \
+ if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$CUSTOM_ROOT" \
|| test "x$CURDIR" = "x$TOPDIR/make/autoconf" \
|| test "x$CURDIR" = "x$TOPDIR/make" ; then
# We are running configure from the src root.
@@ -783,7 +780,12 @@
else
AC_MSG_RESULT([in build directory with custom name])
fi
- OUTPUTDIR="${OUTPUT_BASE}/${CONF_NAME}"
+
+ if test "x$CUSTOM_ROOT" != x; then
+ OUTPUTDIR="${CUSTOM_ROOT}/build/${CONF_NAME}"
+ else
+ OUTPUTDIR="${TOPDIR}/build/${CONF_NAME}"
+ fi
$MKDIR -p "$OUTPUTDIR"
if test ! -d "$OUTPUTDIR"; then
AC_MSG_ERROR([Could not create build directory $OUTPUTDIR])
--- a/make/autoconf/boot-jdk.m4 Wed Oct 18 13:52:32 2017 -0700
+++ b/make/autoconf/boot-jdk.m4 Wed Oct 18 21:05:09 2017 +0000
@@ -325,6 +325,27 @@
fi
AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
AC_MSG_RESULT([$BOOT_JDK_BITS])
+
+ # Try to enable CDS
+ AC_MSG_CHECKING([for local Boot JDK Class Data Sharing (CDS)])
+ BOOT_JDK_CDS_ARCHIVE=$CONFIGURESUPPORT_OUTPUTDIR/classes.jsa
+ ADD_JVM_ARG_IF_OK([-XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE],boot_jdk_cds_args,[$JAVA])
+
+ if test "x$boot_jdk_cds_args" != x; then
+ # Try creating a CDS archive
+ "$JAVA" $boot_jdk_cds_args -Xshare:dump > /dev/null 2>&1
+ if test $? -eq 0; then
+ BOOTJDK_USE_LOCAL_CDS=true
+ AC_MSG_RESULT([yes, created])
+ else
+ # Generation failed, don't use CDS.
+ BOOTJDK_USE_LOCAL_CDS=false
+ AC_MSG_RESULT([no, creation failed])
+ fi
+ else
+ BOOTJDK_USE_LOCAL_CDS=false
+ AC_MSG_RESULT([no, -XX:SharedArchiveFile not supported])
+ fi
])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
@@ -346,6 +367,14 @@
# Force en-US environment
ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA])
+ if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then
+ # Use our own CDS archive
+ ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA])
+ else
+ # Otherwise optimistically use the system-wide one, if one is present
+ ADD_JVM_ARG_IF_OK([-Xshare:auto],boot_jdk_jvmargs,[$JAVA])
+ fi
+
# Apply user provided options.
ADD_JVM_ARG_IF_OK([$with_boot_jdk_jvmargs],boot_jdk_jvmargs,[$JAVA])
@@ -355,7 +384,6 @@
JAVA_FLAGS=$boot_jdk_jvmargs
AC_SUBST(JAVA_FLAGS)
-
AC_MSG_CHECKING([flags for boot jdk java command for big workloads])
# Starting amount of heap memory.
--- a/make/autoconf/configure Wed Oct 18 13:52:32 2017 -0700
+++ b/make/autoconf/configure Wed Oct 18 21:05:09 2017 +0000
@@ -23,19 +23,18 @@
#
if test "x$1" != xCHECKME; then
- echo "WARNING: Calling the wrapper script directly is deprecated and unsupported."
- echo "Not all features of configure will be available."
+ echo "ERROR: Calling this wrapper script directly is not supported."
echo "Use the 'configure' script in the top-level directory instead."
- TOPDIR=$(cd $(dirname $0)/../.. > /dev/null && pwd)
-else
- # Now the next argument is the absolute top-level directory path.
- # The TOPDIR variable is passed on to configure.ac.
- TOPDIR="$2"
- # Remove these two arguments to get to the user supplied arguments
- shift
- shift
+ exit 1
fi
+# The next argument is the absolute top-level directory path.
+# The TOPDIR variable is passed on to configure.ac.
+TOPDIR="$2"
+# Remove these two arguments to get to the user supplied arguments
+shift
+shift
+
if test "x$BASH" = x; then
echo "Error: This script must be run using bash." 1>&2
exit 1
--- a/make/autoconf/generated-configure.sh Wed Oct 18 13:52:32 2017 -0700
+++ b/make/autoconf/generated-configure.sh Wed Oct 18 21:05:09 2017 +0000
@@ -1134,7 +1134,6 @@
with_extra_path
with_sdk_name
with_conf_name
-with_output_base_dir
with_output_sync
with_default_make_target
enable_headless_only
@@ -2043,7 +2042,6 @@
--with-sdk-name use the platform SDK of the given name. [macosx]
--with-conf-name use this as the name of the configuration [generated
from important configuration options]
- --with-output-base-dir override the default output base directory [./build]
--with-output-sync set make output sync type if supported by make.
[recurse]
--with-default-make-target
@@ -5117,7 +5115,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1506397140
+DATE_WHEN_GENERATED=1508136203
###############################################################################
#
@@ -17554,18 +17552,10 @@
fi
-# Check whether --with-output-base-dir was given.
-if test "${with_output_base_dir+set}" = set; then :
- withval=$with_output_base_dir; OUTPUT_BASE=${with_output_base_dir}
-else
- OUTPUT_BASE="$TOPDIR/build"
-fi
-
-
# Test from where we are running configure, in or outside of src root.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to store configuration" >&5
$as_echo_n "checking where to store configuration... " >&6; }
- if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$TOPDIR/common" \
+ if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$CUSTOM_ROOT" \
|| test "x$CURDIR" = "x$TOPDIR/make/autoconf" \
|| test "x$CURDIR" = "x$TOPDIR/make" ; then
# We are running configure from the src root.
@@ -17578,7 +17568,12 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5
$as_echo "in build directory with custom name" >&6; }
fi
- OUTPUTDIR="${OUTPUT_BASE}/${CONF_NAME}"
+
+ if test "x$CUSTOM_ROOT" != x; then
+ OUTPUTDIR="${CUSTOM_ROOT}/build/${CONF_NAME}"
+ else
+ OUTPUTDIR="${TOPDIR}/build/${CONF_NAME}"
+ fi
$MKDIR -p "$OUTPUTDIR"
if test ! -d "$OUTPUTDIR"; then
as_fn_error $? "Could not create build directory $OUTPUTDIR" "$LINENO" 5
@@ -31483,6 +31478,45 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BOOT_JDK_BITS" >&5
$as_echo "$BOOT_JDK_BITS" >&6; }
+ # Try to enable CDS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local Boot JDK Class Data Sharing (CDS)" >&5
+$as_echo_n "checking for local Boot JDK Class Data Sharing (CDS)... " >&6; }
+ BOOT_JDK_CDS_ARCHIVE=$CONFIGURESUPPORT_OUTPUTDIR/classes.jsa
+
+ $ECHO "Check if jvm arg is ok: -XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE" >&5
+ $ECHO "Command: $JAVA -XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE -version" >&5
+ OUTPUT=`$JAVA -XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE -version 2>&1`
+ FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn`
+ FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""`
+ if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+ boot_jdk_cds_args="$boot_jdk_cds_args -XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE"
+ JVM_ARG_OK=true
+ else
+ $ECHO "Arg failed:" >&5
+ $ECHO "$OUTPUT" >&5
+ JVM_ARG_OK=false
+ fi
+
+
+ if test "x$boot_jdk_cds_args" != x; then
+ # Try creating a CDS archive
+ "$JAVA" $boot_jdk_cds_args -Xshare:dump > /dev/null 2>&1
+ if test $? -eq 0; then
+ BOOTJDK_USE_LOCAL_CDS=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, created" >&5
+$as_echo "yes, created" >&6; }
+ else
+ # Generation failed, don't use CDS.
+ BOOTJDK_USE_LOCAL_CDS=false
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, creation failed" >&5
+$as_echo "no, creation failed" >&6; }
+ fi
+ else
+ BOOTJDK_USE_LOCAL_CDS=false
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, -XX:SharedArchiveFile not supported" >&5
+$as_echo "no, -XX:SharedArchiveFile not supported" >&6; }
+ fi
+
# Check whether --with-build-jdk was given.
@@ -66232,6 +66266,42 @@
fi
+ if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then
+ # Use our own CDS archive
+
+ $ECHO "Check if jvm arg is ok: $boot_jdk_cds_args -Xshare:auto" >&5
+ $ECHO "Command: $JAVA $boot_jdk_cds_args -Xshare:auto -version" >&5
+ OUTPUT=`$JAVA $boot_jdk_cds_args -Xshare:auto -version 2>&1`
+ FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn`
+ FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""`
+ if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+ boot_jdk_jvmargs="$boot_jdk_jvmargs $boot_jdk_cds_args -Xshare:auto"
+ JVM_ARG_OK=true
+ else
+ $ECHO "Arg failed:" >&5
+ $ECHO "$OUTPUT" >&5
+ JVM_ARG_OK=false
+ fi
+
+ else
+ # Otherwise optimistically use the system-wide one, if one is present
+
+ $ECHO "Check if jvm arg is ok: -Xshare:auto" >&5
+ $ECHO "Command: $JAVA -Xshare:auto -version" >&5
+ OUTPUT=`$JAVA -Xshare:auto -version 2>&1`
+ FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn`
+ FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""`
+ if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+ boot_jdk_jvmargs="$boot_jdk_jvmargs -Xshare:auto"
+ JVM_ARG_OK=true
+ else
+ $ECHO "Arg failed:" >&5
+ $ECHO "$OUTPUT" >&5
+ JVM_ARG_OK=false
+ fi
+
+ fi
+
# Apply user provided options.
$ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5
@@ -66256,7 +66326,6 @@
JAVA_FLAGS=$boot_jdk_jvmargs
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for big workloads" >&5
$as_echo_n "checking flags for boot jdk java command for big workloads... " >&6; }
--- a/make/autoconf/spec.gmk.in Wed Oct 18 13:52:32 2017 -0700
+++ b/make/autoconf/spec.gmk.in Wed Oct 18 21:05:09 2017 +0000
@@ -842,8 +842,6 @@
TEST_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(TEST_BUNDLE_NAME)
DOCS_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_BUNDLE_NAME)
-CONFIGURE_CMD := $(TOPDIR)/configure
-
# This macro is called to allow inclusion of closed source counterparts.
# Unless overridden in closed sources, it expands to nothing.
# Usage: This function is called in an open makefile, with the following
--- a/make/common/MakeBase.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/common/MakeBase.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -463,11 +463,22 @@
endef
################################################################################
+# Replace question marks with space in string. This macro needs to be called on
+# files from CacheFind in case any of them contains space in their file name,
+# since CacheFind replaces space with ?.
+# Param 1 - String to replace in
+DecodeSpace = \
+ $(subst ?,$(SPACE),$(strip $1))
+EncodeSpace = \
+ $(subst $(SPACE),?,$(strip $1))
+
+################################################################################
# Make directory without forking mkdir if not needed
# 1: List of directories to create
MakeDir = \
$(strip \
- $(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, $(if $(wildcard $d), , $d)))) \
+ $(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, $(if $(wildcard $d), , \
+ "$(call DecodeSpace, $d)")))) \
$(if $(MakeDir_dirs_to_make), $(shell $(MKDIR) -p $(MakeDir_dirs_to_make))) \
)
@@ -479,6 +490,7 @@
$(if $($(strip $1)),,$(eval $(strip $1) := $2))
################################################################################
+# All install-file and related macros automatically call DecodeSpace when needed.
ifeq ($(OPENJDK_TARGET_OS),solaris)
# On Solaris, if the target is a symlink and exists, cp won't overwrite.
@@ -487,19 +499,21 @@
# If the source and target parent directories are the same, recursive copy doesn't work
# so we fall back on regular copy, which isn't preserving symlinks.
define install-file
- $(MKDIR) -p '$(@D)'
- $(RM) '$@'
- if [ "$(@D)" != "$(<D)" ]; then \
- $(CP) -f -r -P '$<' '$(@D)'; \
- if [ "$(@F)" != "$(<F)" ]; then \
- $(MV) '$(@D)/$(<F)' '$@'; \
+ $(call MakeDir, $(@D))
+ $(RM) '$(call DecodeSpace, $@)'
+ if [ '$(call DecodeSpace, $(dir $@))' != \
+ '$(call DecodeSpace, $(dir $(call EncodeSpace, $<)))' ]; then \
+ $(CP) -f -r -P '$(call DecodeSpace, $<)' '$(call DecodeSpace, $(@D))'; \
+ if [ '$(call DecodeSpace, $(@F))' != \
+ '$(call DecodeSpace, $(notdir $(call EncodeSpace, $(<))))' ]; then \
+ $(MV) '$(call DecodeSpace, $(@D)/$(<F))' '$(call DecodeSpace, $@)'; \
fi; \
else \
- if [ -L '$<' ]; then \
+ if [ -L '$(call DecodeSpace, $<)' ]; then \
$(ECHO) "Source file is a symlink and target is in the same directory: $< $@" ; \
exit 1; \
fi; \
- $(CP) -f '$<' '$@'; \
+ $(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \
fi
endef
else ifeq ($(OPENJDK_TARGET_OS),macosx)
@@ -512,22 +526,22 @@
# If copying a soft link to a directory, need to delete the target first to avoid
# weird errors.
define install-file
- $(MKDIR) -p '$(@D)'
- $(RM) '$@'
- $(CP) -fRP '$<' '$@'
- if [ -n "`$(XATTR) -l '$@'`" ]; then $(XATTR) -c '$@'; fi
+ $(call MakeDir, $(@D))
+ $(RM) '$(call DecodeSpace, $@)'
+ $(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
+ if [ -n "`$(XATTR) -l '$(call DecodeSpace, $@)'`" ]; then $(XATTR) -c '$(call DecodeSpace, $@)'; fi
endef
else
define install-file
$(call MakeDir, $(@D))
- $(CP) -fP '$<' '$@'
+ $(CP) -fP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
endif
# Variant of install file that does not preserve symlinks
define install-file-nolink
$(call MakeDir, $(@D))
- $(CP) -f '$<' '$@'
+ $(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
################################################################################
@@ -577,14 +591,14 @@
# the unix emulation environment.
define link-file-relative
$(call MakeDir, $(@D))
- $(RM) $@
- $(LN) -s $(call RelativePath, $<, $(@D)) $@
+ $(RM) '$(call DecodeSpace, $@)'
+ $(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)'
endef
define link-file-absolute
$(call MakeDir, $(@D))
- $(RM) $@
- $(LN) -s $< $@
+ $(RM) '$(call DecodeSpace, $@)'
+ $(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
################################################################################
@@ -651,6 +665,13 @@
# This macro can be called multiple times to add to the cache. Only finds files
# with no filters.
#
+ # Files containing space will get spaces replaced with ? because GNU Make
+ # cannot handle lists of files with space in them. By using ?, make will match
+ # the wildcard to space in many situations so we don't need to replace back
+ # to space on every use. While not a complete solution it does allow some uses
+ # of CacheFind to function with spaces in file names, including for
+ # SetupCopyFiles.
+ #
# Needs to be called with $(eval )
#
# Even if the performance benifit is negligible on other platforms, keep the
@@ -668,7 +689,8 @@
ifneq ($$(FIND_CACHE_NEW_DIRS), )
# Remove any trailing slash from dirs in the cache dir list
FIND_CACHE_DIRS += $$(patsubst %/,%, $$(FIND_CACHE_NEW_DIRS))
- FIND_CACHE := $$(sort $$(FIND_CACHE) $$(shell $(FIND) $$(FIND_CACHE_NEW_DIRS) \( -type f -o -type l \) $2))
+ FIND_CACHE := $$(sort $$(FIND_CACHE) $$(shell $(FIND) $$(FIND_CACHE_NEW_DIRS) \
+ \( -type f -o -type l \) $2 | $(TR) ' ' '?'))
endif
endef
@@ -684,7 +706,8 @@
# Param 2 - (optional) specialization. Normally "-a \( ... \)" expression.
define CacheFind
$(if $(filter-out $(addsuffix /%,- $(FIND_CACHE_DIRS)) $(FIND_CACHE_DIRS),$1), \
- $(if $(wildcard $1), $(shell $(FIND) $1 \( -type f -o -type l \) $2)), \
+ $(if $(wildcard $1), $(shell $(FIND) $1 \( -type f -o -type l \) $2 \
+ | $(TR) ' ' '?')), \
$(filter $(addsuffix /%,$(patsubst %/,%,$1)) $1,$(FIND_CACHE)))
endef
@@ -693,7 +716,7 @@
# Param 1 - Dirs to find in
# Param 2 - (optional) specialization. Normally "-a \( ... \)" expression.
define CacheFind
- $(shell $(FIND) $1 \( -type f -o -type l \) $2)
+ $(shell $(FIND) $1 \( -type f -o -type l \) $2 | $(TR) ' ' '?')
endef
endif
@@ -707,7 +730,7 @@
# 4 : Macro to call for copy operation
# 5 : Action text to log
$2: $1
- $$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUTDIR)/%,%,$$@))
+ $$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUTDIR)/%,%,$$(call DecodeSpace, $$@)))
$$($$(strip $4))
$3 += $2
--- a/make/corba/Makefile Wed Oct 18 13:52:32 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#
-# Copyright (c) 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.
-#
-
-# Locate this Makefile
-ifeq ($(filter /%, $(lastword $(MAKEFILE_LIST))), )
- makefile_path := $(CURDIR)/$(lastword $(MAKEFILE_LIST))
-else
- makefile_path := $(lastword $(MAKEFILE_LIST))
-endif
-repo_dir := $(patsubst %/make/Makefile, %, $(makefile_path))
-
-# What is the name of this subsystem (langtools, corba, etc)?
-subsystem_name := $(notdir $(repo_dir))
-
-# Try to locate top-level makefile
-top_level_makefile := $(repo_dir)/../Makefile
-ifneq ($(wildcard $(top_level_makefile)), )
- $(info Will run $(subsystem_name) target on top-level Makefile)
- $(info WARNING: This is a non-recommended way of building!)
- $(info ===================================================)
-else
- $(info Cannot locate top-level Makefile. Is this repo not checked out as part of a complete forest?)
- $(error Build from top-level Makefile instead)
-endif
-
-all:
- @$(MAKE) -f $(top_level_makefile) $(subsystem_name)
--- a/make/hotspot/lib/CompileJvm.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/hotspot/lib/CompileJvm.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -58,6 +58,7 @@
-I$(JVM_VARIANT_OUTPUTDIR)/gensrc \
-I$(TOPDIR)/src/hotspot/share/precompiled \
-I$(TOPDIR)/src/hotspot/share/prims \
+ -I$(TOPDIR)/src/java.base/share/native/include \
#
# INCLUDE_SUFFIX_* is only meant for including the proper
--- a/make/lib/Lib-java.base.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/lib/Lib-java.base.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -25,9 +25,13 @@
include LibCommon.gmk
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, lib/Lib-java.base.gmk))
+
# Prepare the find cache.
-$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.base/*/native \
- $(TOPDIR)/src/*/java.base/*/native)))
+LIB_java.base_SRC_DIRS += $(TOPDIR)/src/java.base/*/native
+
+$(eval $(call FillCacheFind, $(wildcard $(LIB_java.base_SRC_DIRS))))
include CoreLibraries.gmk
include NetworkingLibraries.gmk
--- a/make/lib/Lib-java.desktop.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/lib/Lib-java.desktop.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -25,9 +25,13 @@
include LibCommon.gmk
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, lib/Lib-java.desktop.gmk))
+
# Prepare the find cache.
-$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.desktop/*/native \
- $(TOPDIR)/src/*/java.desktop/*/native)))
+LIB_java.desktop_SRC_DIRS += $(TOPDIR)/src/java.desktop/*/native
+
+$(eval $(call FillCacheFind, $(wildcard $(LIB_java.desktop_SRC_DIRS))))
include LibosxLibraries.gmk
include PlatformLibraries.gmk
--- a/make/test/JtregNativeHotspot.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/test/JtregNativeHotspot.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -35,7 +35,7 @@
include MakeBase.gmk
include TestFilesCompilation.gmk
-$(eval $(call IncludeCustomExtension, hotspot/test/JtregNative.gmk))
+$(eval $(call IncludeCustomExtension, test/JtregNativeHotspot.gmk))
################################################################################
# Targets for building the native tests themselves.
--- a/make/test/JtregNativeJdk.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/make/test/JtregNativeJdk.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -35,7 +35,7 @@
include MakeBase.gmk
include TestFilesCompilation.gmk
-$(eval $(call IncludeCustomExtension, test/JtregNative.gmk))
+$(eval $(call IncludeCustomExtension, test/JtregNativeJdk.gmk))
################################################################################
# Targets for building the native tests themselves.
--- a/src/hotspot/.mx.jvmci/hotspot/templates/eclipse/cproject Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/.mx.jvmci/hotspot/templates/eclipse/cproject Wed Oct 18 21:05:09 2017 +0000
@@ -70,7 +70,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
- <entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+ <entry excluding="cpu/x86/templateTable_x86_32.cpp|cpu/x86/templateInterpreter_x86_32.cpp|cpu/x86/stubRoutines_x86_32.cpp|cpu/x86/stubGenerator_x86_32.cpp|cpu/x86/sharedRuntime_x86_32.cpp|cpu/x86/jniFastGetField_x86_32.cpp|cpu/x86/interpreterRT_x86_32.cpp|cpu/x86/interpreter_x86_32.cpp|cpu/x86/interp_masm_x86_32.cpp|cpu/x86/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
--- a/src/hotspot/.mx.jvmci/mx_jvmci.py Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/.mx.jvmci/mx_jvmci.py Wed Oct 18 21:05:09 2017 +0000
@@ -256,14 +256,10 @@
"""
roots = [
- 'ASSEMBLY_EXCEPTION',
- 'LICENSE',
- 'README',
- 'THIRD_PARTY_README',
- 'agent',
- 'make',
- 'src',
- 'test'
+ 'cpu',
+ 'os',
+ 'os_cpu',
+ 'share'
]
for jvmVariant in _jdkJvmVariants:
@@ -605,6 +601,16 @@
def _get_openjdk_os_cpu():
return _get_openjdk_os() + '-' + _get_openjdk_cpu()
+def _get_jdk_dir():
+ suiteParentDir = dirname(_suite.dir)
+ # suitParentDir is now something like: /some_prefix/jdk10-hs/open/src
+ pathComponents = suiteParentDir.split(os.sep)
+ for i in range(0, len(pathComponents)):
+ if pathComponents[i] in ["open", "src"]:
+ del pathComponents[i:]
+ break
+ return os.path.join(os.sep, *pathComponents)
+
def _get_jdk_build_dir(debugLevel=None):
"""
Gets the directory into which the JDK is built. This directory contains
@@ -613,7 +619,7 @@
if debugLevel is None:
debugLevel = _vm.debugLevel
name = '{}-{}-{}-{}'.format(_get_openjdk_os_cpu(), 'normal', _vm.jvmVariant, debugLevel)
- return join(dirname(_suite.dir), 'build', name)
+ return join(_get_jdk_dir(), 'build', name)
_jvmci_bootclasspath_prepends = []
--- a/src/hotspot/.mx.jvmci/suite.py Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/.mx.jvmci/suite.py Wed Oct 18 21:05:09 2017 +0000
@@ -24,9 +24,7 @@
"defaultLicense" : "GPLv2-CPE",
- # This puts mx/ as a sibling of the JDK build configuration directories
- # (e.g., macosx-x86_64-normal-server-release).
- "outputRoot" : "../build/mx/hotspot",
+ "outputRoot" : "../../build/mx/hotspot",
# ------------- Libraries -------------
@@ -43,7 +41,7 @@
# ------------- JVMCI:Service -------------
"jdk.vm.ci.services" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"javaCompliance" : "9",
"workingSets" : "API,JVMCI",
@@ -52,7 +50,7 @@
# ------------- JVMCI:API -------------
"jdk.vm.ci.common" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"checkstyle" : "jdk.vm.ci.services",
"javaCompliance" : "9",
@@ -60,7 +58,7 @@
},
"jdk.vm.ci.meta" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"checkstyle" : "jdk.vm.ci.services",
"javaCompliance" : "9",
@@ -68,7 +66,7 @@
},
"jdk.vm.ci.code" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.meta"],
"checkstyle" : "jdk.vm.ci.services",
@@ -77,7 +75,7 @@
},
"jdk.vm.ci.code.test" : {
- "subDir" : "test/compiler/jvmci",
+ "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
"sourceDirs" : ["src"],
"dependencies" : [
"mx:JUNIT",
@@ -92,7 +90,7 @@
},
"jdk.vm.ci.runtime" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.code",
@@ -104,7 +102,7 @@
},
"jdk.vm.ci.runtime.test" : {
- "subDir" : "test/compiler/jvmci",
+ "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
"sourceDirs" : ["src"],
"dependencies" : [
"mx:JUNIT",
@@ -119,7 +117,7 @@
# ------------- JVMCI:HotSpot -------------
"jdk.vm.ci.aarch64" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
@@ -128,7 +126,7 @@
},
"jdk.vm.ci.amd64" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
@@ -137,7 +135,7 @@
},
"jdk.vm.ci.sparc" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : ["jdk.vm.ci.code"],
"checkstyle" : "jdk.vm.ci.services",
@@ -146,7 +144,7 @@
},
"jdk.vm.ci.hotspot" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.common",
@@ -163,7 +161,7 @@
},
"jdk.vm.ci.hotspot.test" : {
- "subDir" : "test/compiler/jvmci",
+ "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
"sourceDirs" : ["src"],
"dependencies" : [
"TESTNG",
@@ -175,7 +173,7 @@
},
"jdk.vm.ci.hotspot.aarch64" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.aarch64",
@@ -187,7 +185,7 @@
},
"jdk.vm.ci.hotspot.amd64" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.amd64",
@@ -199,7 +197,7 @@
},
"jdk.vm.ci.hotspot.sparc" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.sparc",
@@ -221,12 +219,12 @@
# ------------- Distributions -------------
"JVMCI_SERVICES" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"dependencies" : ["jdk.vm.ci.services"],
},
"JVMCI_API" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"dependencies" : [
"jdk.vm.ci.runtime",
"jdk.vm.ci.common",
@@ -240,7 +238,7 @@
},
"JVMCI_HOTSPOT" : {
- "subDir" : "src/jdk.internal.vm.ci/share/classes",
+ "subDir" : "../jdk.internal.vm.ci/share/classes",
"dependencies" : [
"jdk.vm.ci.hotspot.aarch64",
"jdk.vm.ci.hotspot.amd64",
@@ -253,7 +251,7 @@
},
"JVMCI_TEST" : {
- "subDir" : "test/compiler/jvmci",
+ "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
"dependencies" : [
"jdk.vm.ci.runtime.test",
],
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -863,7 +863,7 @@
//
// markOop displaced_header = obj->mark().set_unlocked();
// monitor->lock()->set_displaced_header(displaced_header);
- // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
+ // if (Atomic::cmpxchg(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
// // We stored the monitor address into the object's mark word.
// } else if (THREAD->is_lock_owned((address)displaced_header))
// // Simple recursive case.
@@ -901,7 +901,7 @@
std(displaced_header, BasicObjectLock::lock_offset_in_bytes() +
BasicLock::displaced_header_offset_in_bytes(), monitor);
- // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
+ // if (Atomic::cmpxchg(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
// Store stack address of the BasicObjectLock (this is monitor) into object.
addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes());
@@ -977,7 +977,7 @@
// if ((displaced_header = monitor->displaced_header()) == NULL) {
// // Recursive unlock. Mark the monitor unlocked by setting the object field to NULL.
// monitor->set_obj(NULL);
- // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) {
+ // } else if (Atomic::cmpxchg(displaced_header, obj->mark_addr(), monitor) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(NULL);
// } else {
@@ -1010,7 +1010,7 @@
cmpdi(CCR0, displaced_header, 0);
beq(CCR0, free_slot); // recursive unlock
- // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) {
+ // } else if (Atomic::cmpxchg(displaced_header, obj->mark_addr(), monitor) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(NULL);
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -149,8 +149,7 @@
print_features();
}
- // PPC64 supports 8-byte compare-exchange operations (see
- // Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr)
+ // PPC64 supports 8-byte compare-exchange operations (see Atomic::cmpxchg)
// and 'atomic long memory ops' (see Unsafe_GetLongVolatile).
_supports_cx8 = true;
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -914,7 +914,7 @@
//
// markOop displaced_header = obj->mark().set_unlocked();
// monitor->lock()->set_displaced_header(displaced_header);
- // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
+ // if (Atomic::cmpxchg(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
// // We stored the monitor address into the object's mark word.
// } else if (THREAD->is_lock_owned((address)displaced_header))
// // Simple recursive case.
@@ -949,7 +949,7 @@
z_stg(displaced_header, BasicObjectLock::lock_offset_in_bytes() +
BasicLock::displaced_header_offset_in_bytes(), monitor);
- // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
+ // if (Atomic::cmpxchg(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) {
// Store stack address of the BasicObjectLock (this is monitor) into object.
add2reg(object_mark_addr, oopDesc::mark_offset_in_bytes(), object);
@@ -1021,7 +1021,7 @@
// if ((displaced_header = monitor->displaced_header()) == NULL) {
// // Recursive unlock. Mark the monitor unlocked by setting the object field to NULL.
// monitor->set_obj(NULL);
- // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) {
+ // } else if (Atomic::cmpxchg(displaced_header, obj->mark_addr(), monitor) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(NULL);
// } else {
@@ -1062,7 +1062,7 @@
BasicLock::displaced_header_offset_in_bytes()));
z_bre(done); // displaced_header == 0 -> goto done
- // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) {
+ // } else if (Atomic::cmpxchg(displaced_header, obj->mark_addr(), monitor) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(NULL);
--- a/src/hotspot/cpu/s390/vm_version_s390.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/s390/vm_version_s390.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -224,7 +224,7 @@
}
// z/Architecture supports 8-byte compare-exchange operations
- // (see Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr)
+ // (see Atomic::cmpxchg)
// and 'atomic long memory ops' (see Unsafe_GetLongVolatile).
_supports_cx8 = true;
--- a/src/hotspot/cpu/x86/frame_x86.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/x86/frame_x86.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -383,6 +383,7 @@
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
+#ifdef ASSERT
void frame::adjust_unextended_sp() {
// On x86, sites calling method handle intrinsics and lambda forms are treated
// as any other call site. Therefore, no special action is needed when we are
@@ -394,11 +395,12 @@
// If the sender PC is a deoptimization point, get the original PC.
if (sender_cm->is_deopt_entry(_pc) ||
sender_cm->is_deopt_mh_entry(_pc)) {
- DEBUG_ONLY(verify_deopt_original_pc(sender_cm, _unextended_sp));
+ verify_deopt_original_pc(sender_cm, _unextended_sp);
}
}
}
}
+#endif
//------------------------------------------------------------------------------
// frame::update_map_with_saved_link
--- a/src/hotspot/cpu/x86/frame_x86.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/x86/frame_x86.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -117,7 +117,7 @@
// original sp we use that convention.
intptr_t* _unextended_sp;
- void adjust_unextended_sp();
+ void adjust_unextended_sp() NOT_DEBUG_RETURN;
intptr_t* ptr_at_addr(int offset) const {
return (intptr_t*) addr_at(offset);
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -566,7 +566,7 @@
return start;
}
- // Support for intptr_t atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest)
+ // Support for intptr_t atomic::xchg_long(jlong exchange_value, volatile jlong* dest)
//
// Arguments :
// c_rarg0: exchange_value
@@ -574,8 +574,8 @@
//
// Result:
// *dest <- ex, return (orig *dest)
- address generate_atomic_xchg_ptr() {
- StubCodeMark mark(this, "StubRoutines", "atomic_xchg_ptr");
+ address generate_atomic_xchg_long() {
+ StubCodeMark mark(this, "StubRoutines", "atomic_xchg_long");
address start = __ pc();
__ movptr(rax, c_rarg0); // Copy to eax we need a return value anyhow
@@ -4998,7 +4998,7 @@
// atomic calls
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
- StubRoutines::_atomic_xchg_ptr_entry = generate_atomic_xchg_ptr();
+ StubRoutines::_atomic_xchg_long_entry = generate_atomic_xchg_long();
StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg();
StubRoutines::_atomic_cmpxchg_byte_entry = generate_atomic_cmpxchg_byte();
StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long();
--- a/src/hotspot/cpu/zero/cppInterpreter_zero.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/zero/cppInterpreter_zero.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -276,7 +276,7 @@
markOop disp = lockee->mark()->set_unlocked();
monitor->lock()->set_displaced_header(disp);
- if (Atomic::cmpxchg_ptr(monitor, lockee->mark_addr(), disp) != disp) {
+ if (Atomic::cmpxchg((markOop)monitor, lockee->mark_addr(), disp) != disp) {
if (thread->is_lock_owned((address) disp->clear_lock_bits())) {
monitor->lock()->set_displaced_header(NULL);
}
@@ -420,7 +420,8 @@
monitor->set_obj(NULL);
if (header != NULL) {
- if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) {
+ markOop old_header = markOopDesc::encode(lock);
+ if (rcvr->cas_set_mark(header, old_header) != old_header) {
monitor->set_obj(rcvr); {
HandleMark hm(thread);
CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(thread, monitor));
--- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -253,9 +253,8 @@
// atomic calls
StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub();
- StubRoutines::_atomic_xchg_ptr_entry = ShouldNotCallThisStub();
+ StubRoutines::_atomic_xchg_long_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub();
- StubRoutines::_atomic_cmpxchg_ptr_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
--- a/src/hotspot/os/aix/os_aix.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os/aix/os_aix.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -889,8 +889,12 @@
stack_size / K);
}
- // Configure libc guard page.
- ret = pthread_attr_setguardsize(&attr, os::Aix::default_guard_size(thr_type));
+ // Save some cycles and a page by disabling OS guard pages where we have our own
+ // VM guard pages (in java threads). For other threads, keep system default guard
+ // pages in place.
+ if (thr_type == java_thread || thr_type == compiler_thread) {
+ ret = pthread_attr_setguardsize(&attr, 0);
+ }
pthread_t tid = 0;
if (ret == 0) {
@@ -3019,19 +3023,6 @@
return chained;
}
-size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
- // Creating guard page is very expensive. Java thread has HotSpot
- // guard pages, only enable glibc guard page for non-Java threads.
- // (Remember: compiler thread is a Java thread, too!)
- //
- // Aix can have different page sizes for stack (4K) and heap (64K).
- // As Hotspot knows only one page size, we assume the stack has
- // the same page size as the heap. Returning page_size() here can
- // cause 16 guard pages which we want to avoid. Thus we return 4K
- // which will be rounded to the real page size by the OS.
- return ((thr_type == java_thread || thr_type == compiler_thread) ? 0 : 4 * K);
-}
-
struct sigaction* os::Aix::get_preinstalled_handler(int sig) {
if (sigismember(&sigs, sig)) {
return &sigact[sig];
--- a/src/hotspot/os/aix/os_aix.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os/aix/os_aix.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -139,9 +139,6 @@
// libpthread version string
static void libpthread_init();
- // Return default libc guard size for the specified thread type.
- static size_t default_guard_size(os::ThreadType thr_type);
-
// Function returns true if we run on OS/400 (pase), false if we run
// on AIX.
static bool on_pase() {
--- a/src/hotspot/os/linux/os_linux.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os/linux/os_linux.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -98,6 +98,11 @@
inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
{
+// readdir_r has been deprecated since glibc 2.24.
+// See https://sourceware.org/bugzilla/show_bug.cgi?id=19056 for more details.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
dirent* p;
int status;
assert(dirp != NULL, "just checking");
@@ -111,6 +116,8 @@
return NULL;
} else
return p;
+
+#pragma GCC diagnostic pop
}
inline int os::closedir(DIR *dirp) {
--- a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -137,7 +137,7 @@
inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
T volatile* dest) const {
STATIC_ASSERT(4 == sizeof(T));
- // Note that xchg_ptr doesn't necessarily do an acquire
+ // Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
@@ -176,7 +176,7 @@
inline T Atomic::PlatformXchg<8>::operator()(T exchange_value,
T volatile* dest) const {
STATIC_ASSERT(8 == sizeof(T));
- // Note that xchg_ptr doesn't necessarily do an acquire
+ // Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
--- a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -134,7 +134,7 @@
template<typename T>
inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
T volatile* dest) const {
- // Note that xchg_ptr doesn't necessarily do an acquire
+ // Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
@@ -173,7 +173,7 @@
inline T Atomic::PlatformXchg<8>::operator()(T exchange_value,
T volatile* dest) const {
STATIC_ASSERT(8 == sizeof(T));
- // Note that xchg_ptr doesn't necessarily do an acquire
+ // Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
--- a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -73,7 +73,7 @@
}
DEFINE_STUB_XCHG(4, jint, os::atomic_xchg_func)
-DEFINE_STUB_XCHG(8, jlong, os::atomic_xchg_ptr_func)
+DEFINE_STUB_XCHG(8, jlong, os::atomic_xchg_long_func)
#undef DEFINE_STUB_XCHG
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -219,7 +219,7 @@
// Atomics and Stub Functions
typedef jint xchg_func_t (jint, volatile jint*);
-typedef intptr_t xchg_ptr_func_t (intptr_t, volatile intptr_t*);
+typedef intptr_t xchg_long_func_t (jlong, volatile jlong*);
typedef jint cmpxchg_func_t (jint, volatile jint*, jint);
typedef jbyte cmpxchg_byte_func_t (jbyte, volatile jbyte*, jbyte);
typedef jlong cmpxchg_long_func_t (jlong, volatile jlong*, jlong);
@@ -243,12 +243,12 @@
return old_value;
}
-intptr_t os::atomic_xchg_ptr_bootstrap(intptr_t exchange_value, volatile intptr_t* dest) {
+intptr_t os::atomic_xchg_long_bootstrap(jlong exchange_value, volatile jlong* dest) {
// try to use the stub:
- xchg_ptr_func_t* func = CAST_TO_FN_PTR(xchg_ptr_func_t*, StubRoutines::atomic_xchg_ptr_entry());
+ xchg_long_func_t* func = CAST_TO_FN_PTR(xchg_long_func_t*, StubRoutines::atomic_xchg_long_entry());
if (func != NULL) {
- os::atomic_xchg_ptr_func = func;
+ os::atomic_xchg_long_func = func;
return (*func)(exchange_value, dest);
}
assert(Threads::number_of_threads() == 0, "for bootstrap only");
@@ -338,7 +338,7 @@
}
xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap;
-xchg_ptr_func_t* os::atomic_xchg_ptr_func = os::atomic_xchg_ptr_bootstrap;
+xchg_long_func_t* os::atomic_xchg_long_func = os::atomic_xchg_long_bootstrap;
cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap;
cmpxchg_byte_func_t* os::atomic_cmpxchg_byte_func = os::atomic_cmpxchg_byte_bootstrap;
add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
//
#ifdef AMD64
static jint (*atomic_xchg_func) (jint, volatile jint*);
- static intptr_t (*atomic_xchg_ptr_func) (intptr_t, volatile intptr_t*);
+ static intptr_t (*atomic_xchg_long_func) (jlong, volatile jlong*);
static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint);
static jbyte (*atomic_cmpxchg_byte_func) (jbyte, volatile jbyte*, jbyte);
@@ -40,7 +40,7 @@
static intptr_t (*atomic_add_ptr_func) (intptr_t, volatile intptr_t*);
static jint atomic_xchg_bootstrap (jint, volatile jint*);
- static intptr_t atomic_xchg_ptr_bootstrap (intptr_t, volatile intptr_t*);
+ static intptr_t atomic_xchg_long_bootstrap (jlong, volatile jlong*);
static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint);
static jbyte atomic_cmpxchg_byte_bootstrap(jbyte, volatile jbyte*, jbyte);
--- a/src/hotspot/share/asm/assembler.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/asm/assembler.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -236,11 +236,9 @@
if (dcon->match(type, cfn))
return dcon;
if (dcon->value_fn == NULL) {
- // (cmpxchg not because this is multi-threaded but because I'm paranoid)
- if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) {
+ dcon->value_fn = cfn;
dcon->type = type;
return dcon;
- }
}
}
// If this assert is hit (in pre-integration testing!) then re-evaluate
--- a/src/hotspot/share/c1/c1_Runtime1.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1221,11 +1221,6 @@
MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
guarantee(nm != NULL, "only nmethods can contain non-perm oops");
- if (!nm->on_scavenge_root_list() &&
- ((mirror.not_null() && mirror()->is_scavengable()) ||
- (appendix.not_null() && appendix->is_scavengable()))) {
- CodeCache::add_scavenge_root_nmethod(nm);
- }
// Since we've patched some oops in the nmethod,
// (re)register it with the heap.
--- a/src/hotspot/share/classfile/classLoader.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/classfile/classLoader.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -48,13 +48,11 @@
ClassPathEntry* volatile _next;
public:
// Next entry in class path
- ClassPathEntry* next() const {
- return (ClassPathEntry*) OrderAccess::load_ptr_acquire(&_next);
- }
+ ClassPathEntry* next() const { return OrderAccess::load_acquire(&_next); }
virtual ~ClassPathEntry() {}
void set_next(ClassPathEntry* next) {
// may have unlocked readers, so ensure visibility.
- OrderAccess::release_store_ptr(&_next, next);
+ OrderAccess::release_store(&_next, next);
}
virtual bool is_jrt() = 0;
virtual bool is_jar_file() const = 0;
--- a/src/hotspot/share/classfile/classLoaderData.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -82,11 +82,6 @@
#include "trace/tracing.hpp"
#endif
-// helper function to avoid in-line casts
-template <typename T> static T* load_ptr_acquire(T* volatile *p) {
- return static_cast<T*>(OrderAccess::load_ptr_acquire(p));
-}
-
ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) :
@@ -152,7 +147,7 @@
oop* ClassLoaderData::ChunkedHandleList::add(oop o) {
if (_head == NULL || _head->_size == Chunk::CAPACITY) {
Chunk* next = new Chunk(_head);
- OrderAccess::release_store_ptr(&_head, next);
+ OrderAccess::release_store(&_head, next);
}
oop* handle = &_head->_data[_head->_size];
*handle = o;
@@ -169,7 +164,7 @@
}
void ClassLoaderData::ChunkedHandleList::oops_do(OopClosure* f) {
- Chunk* head = (Chunk*) OrderAccess::load_ptr_acquire(&_head);
+ Chunk* head = OrderAccess::load_acquire(&_head);
if (head != NULL) {
// Must be careful when reading size of head
oops_do_chunk(f, head, OrderAccess::load_acquire(&head->_size));
@@ -257,24 +252,24 @@
}
void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
klass_closure->do_klass(k);
assert(k != k->next_link(), "no loops!");
}
}
void ClassLoaderData::classes_do(void f(Klass * const)) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
f(k);
assert(k != k->next_link(), "no loops!");
}
}
void ClassLoaderData::methods_do(void f(Method*)) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
if (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded()) {
InstanceKlass::cast(k)->methods_do(f);
}
@@ -282,8 +277,8 @@
}
void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
// Do not filter ArrayKlass oops here...
if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
klass_closure->do_klass(k);
@@ -292,8 +287,8 @@
}
void ClassLoaderData::classes_do(void f(InstanceKlass*)) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
if (k->is_instance_klass()) {
f(InstanceKlass::cast(k));
}
@@ -449,7 +444,7 @@
k->set_next_link(old_value);
// Link the new item into the list, making sure the linked class is stable
// since the list can be walked without a lock
- OrderAccess::release_store_ptr(&_klasses, k);
+ OrderAccess::release_store(&_klasses, k);
}
if (publicize && k->class_loader_data() != NULL) {
@@ -589,8 +584,8 @@
ModuleEntryTable* ClassLoaderData::modules() {
// Lazily create the module entry table at first request.
- // Lock-free access requires load_ptr_acquire.
- ModuleEntryTable* modules = load_ptr_acquire(&_modules);
+ // Lock-free access requires load_acquire.
+ ModuleEntryTable* modules = OrderAccess::load_acquire(&_modules);
if (modules == NULL) {
MutexLocker m1(Module_lock);
// Check if _modules got allocated while we were waiting for this lock.
@@ -600,7 +595,7 @@
{
MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
// Ensure _modules is stable, since it is examined without a lock
- OrderAccess::release_store_ptr(&_modules, modules);
+ OrderAccess::release_store(&_modules, modules);
}
}
}
@@ -737,8 +732,8 @@
// to create smaller arena for Reflection class loaders also.
// The reason for the delayed allocation is because some class loaders are
// simply for delegating with no metadata of their own.
- // Lock-free access requires load_ptr_acquire.
- Metaspace* metaspace = load_ptr_acquire(&_metaspace);
+ // Lock-free access requires load_acquire.
+ Metaspace* metaspace = OrderAccess::load_acquire(&_metaspace);
if (metaspace == NULL) {
MutexLockerEx ml(_metaspace_lock, Mutex::_no_safepoint_check_flag);
// Check if _metaspace got allocated while we were waiting for this lock.
@@ -760,7 +755,7 @@
metaspace = new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType);
}
// Ensure _metaspace is stable, since it is examined without a lock
- OrderAccess::release_store_ptr(&_metaspace, metaspace);
+ OrderAccess::release_store(&_metaspace, metaspace);
}
}
return metaspace;
@@ -914,8 +909,8 @@
}
bool ClassLoaderData::contains_klass(Klass* klass) {
- // Lock-free access requires load_ptr_acquire
- for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
+ // Lock-free access requires load_acquire
+ for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
if (k == klass) return true;
}
return false;
@@ -948,7 +943,7 @@
if (!is_anonymous) {
ClassLoaderData** cld_addr = java_lang_ClassLoader::loader_data_addr(loader());
// First, Atomically set it
- ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
+ ClassLoaderData* old = Atomic::cmpxchg(cld, cld_addr, (ClassLoaderData*)NULL);
if (old != NULL) {
delete cld;
// Returns the data.
@@ -963,7 +958,7 @@
do {
cld->set_next(next);
- ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next);
+ ClassLoaderData* exchanged = Atomic::cmpxchg(cld, list_head, next);
if (exchanged == next) {
LogTarget(Debug, class, loader, data) lt;
if (lt.is_enabled()) {
@@ -1387,7 +1382,7 @@
while (head != NULL) {
Klass* next = next_klass_in_cldg(head);
- Klass* old_head = (Klass*)Atomic::cmpxchg_ptr(next, &_next_klass, head);
+ Klass* old_head = Atomic::cmpxchg(next, &_next_klass, head);
if (old_head == head) {
return head; // Won the CAS.
--- a/src/hotspot/share/classfile/classLoaderData.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -194,7 +194,7 @@
Chunk(Chunk* c) : _next(c), _size(0) { }
};
- Chunk* _head;
+ Chunk* volatile _head;
void oops_do_chunk(OopClosure* f, Chunk* c, const juint size);
--- a/src/hotspot/share/classfile/dictionary.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/classfile/dictionary.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -161,10 +161,10 @@
void set_pd_set(ProtectionDomainEntry* new_head) { _pd_set = new_head; }
ProtectionDomainEntry* pd_set_acquire() const {
- return (ProtectionDomainEntry*)OrderAccess::load_ptr_acquire(&_pd_set);
+ return OrderAccess::load_acquire(&_pd_set);
}
void release_set_pd_set(ProtectionDomainEntry* new_head) {
- OrderAccess::release_store_ptr(&_pd_set, new_head);
+ OrderAccess::release_store(&_pd_set, new_head);
}
// Tells whether the initiating class' protection domain can access the klass in this entry
--- a/src/hotspot/share/classfile/verifier.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/classfile/verifier.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -69,14 +69,14 @@
static volatile jint _is_new_verify_byte_codes_fn = (jint) true;
static void* verify_byte_codes_fn() {
- if (OrderAccess::load_ptr_acquire(&_verify_byte_codes_fn) == NULL) {
+ if (OrderAccess::load_acquire(&_verify_byte_codes_fn) == NULL) {
void *lib_handle = os::native_java_library();
void *func = os::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion");
- OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
+ OrderAccess::release_store(&_verify_byte_codes_fn, func);
if (func == NULL) {
_is_new_verify_byte_codes_fn = false;
func = os::dll_lookup(lib_handle, "VerifyClassCodes");
- OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
+ OrderAccess::release_store(&_verify_byte_codes_fn, func);
}
}
return (void*)_verify_byte_codes_fn;
--- a/src/hotspot/share/code/codeCache.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/code/codeCache.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -683,22 +683,19 @@
if (cb->is_alive()) {
f->do_code_blob(cb);
#ifdef ASSERT
- if (cb->is_nmethod())
- ((nmethod*)cb)->verify_scavenge_root_oops();
+ if (cb->is_nmethod()) {
+ Universe::heap()->verify_nmethod((nmethod*)cb);
+ }
#endif //ASSERT
}
}
}
}
-// Walk the list of methods which might contain non-perm oops.
+// Walk the list of methods which might contain oops to the java heap.
void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
- if (UseG1GC) {
- return;
- }
-
const bool fix_relocations = f->fix_relocations();
debug_only(mark_scavenge_root_nmethods());
@@ -735,13 +732,20 @@
debug_only(verify_perm_nmethods(NULL));
}
+void CodeCache::register_scavenge_root_nmethod(nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ if (!nm->on_scavenge_root_list() && nm->detect_scavenge_root_oops()) {
+ add_scavenge_root_nmethod(nm);
+ }
+}
+
+void CodeCache::verify_scavenge_root_nmethod(nmethod* nm) {
+ nm->verify_scavenge_root_oops();
+}
+
void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
- if (UseG1GC) {
- return;
- }
-
nm->set_on_scavenge_root_list();
nm->set_scavenge_root_link(_scavenge_root_nmethods);
set_scavenge_root_nmethods(nm);
@@ -754,8 +758,6 @@
assert((prev == NULL && scavenge_root_nmethods() == nm) ||
(prev != NULL && prev->scavenge_root_link() == nm), "precondition");
- assert(!UseG1GC, "G1 does not use the scavenge_root_nmethods list");
-
print_trace("unlink_scavenge_root", nm);
if (prev == NULL) {
set_scavenge_root_nmethods(nm->scavenge_root_link());
@@ -769,10 +771,6 @@
void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
- if (UseG1GC) {
- return;
- }
-
print_trace("drop_scavenge_root", nm);
nmethod* prev = NULL;
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
@@ -788,10 +786,6 @@
void CodeCache::prune_scavenge_root_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
- if (UseG1GC) {
- return;
- }
-
debug_only(mark_scavenge_root_nmethods());
nmethod* last = NULL;
@@ -820,10 +814,6 @@
#ifndef PRODUCT
void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
- if (UseG1GC) {
- return;
- }
-
// While we are here, verify the integrity of the list.
mark_scavenge_root_nmethods();
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
@@ -833,7 +823,7 @@
verify_perm_nmethods(f);
}
-// Temporarily mark nmethods that are claimed to be on the non-perm list.
+// Temporarily mark nmethods that are claimed to be on the scavenge list.
void CodeCache::mark_scavenge_root_nmethods() {
NMethodIterator iter;
while(iter.next_alive()) {
@@ -854,7 +844,7 @@
assert(nm->scavenge_root_not_marked(), "must be already processed");
if (nm->on_scavenge_root_list())
call_f = false; // don't show this one to the client
- nm->verify_scavenge_root_oops();
+ Universe::heap()->verify_nmethod(nm);
if (call_f) f_or_null->do_code_blob(nm);
}
}
@@ -1640,4 +1630,3 @@
blob_count(), nmethod_count(), adapter_count(),
unallocated_capacity());
}
-
--- a/src/hotspot/share/code/codeCache.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/code/codeCache.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -181,6 +181,10 @@
static void scavenge_root_nmethods_do(CodeBlobToOopClosure* f);
static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; }
+ // register_scavenge_root_nmethod() conditionally adds the nmethod to the list
+ // if it is not already on the list and has a scavengeable root
+ static void register_scavenge_root_nmethod(nmethod* nm);
+ static void verify_scavenge_root_nmethod(nmethod* nm);
static void add_scavenge_root_nmethod(nmethod* nm);
static void drop_scavenge_root_nmethod(nmethod* nm);
--- a/src/hotspot/share/code/compiledMethod.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/code/compiledMethod.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -288,7 +288,7 @@
// Note: _exception_cache may be read concurrently. We rely on memory_order_consume here.
ExceptionCache* exception_cache() const { return _exception_cache; }
void set_exception_cache(ExceptionCache *ec) { _exception_cache = ec; }
- void release_set_exception_cache(ExceptionCache *ec) { OrderAccess::release_store_ptr(&_exception_cache, ec); }
+ void release_set_exception_cache(ExceptionCache *ec) { OrderAccess::release_store(&_exception_cache, ec); }
address handler_for_exception_and_pc(Handle exception, address pc);
void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
void clean_exception_cache(BoolObjectClosure* is_alive);
--- a/src/hotspot/share/code/jvmticmlr.h Wed Oct 18 13:52:32 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-/*
- * This header file defines the data structures sent by the VM
- * through the JVMTI CompiledMethodLoad callback function via the
- * "void * compile_info" parameter. The memory pointed to by the
- * compile_info parameter may not be referenced after returning from
- * the CompiledMethodLoad callback. These are VM implementation
- * specific data structures that may evolve in future releases. A
- * JVMTI agent should interpret a non-NULL compile_info as a pointer
- * to a region of memory containing a list of records. In a typical
- * usage scenario, a JVMTI agent would cast each record to a
- * jvmtiCompiledMethodLoadRecordHeader, a struct that represents
- * arbitrary information. This struct contains a kind field to indicate
- * the kind of information being passed, and a pointer to the next
- * record. If the kind field indicates inlining information, then the
- * agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord.
- * This record contains an array of PCStackInfo structs, which indicate
- * for every pc address what are the methods on the invocation stack.
- * The "methods" and "bcis" fields in each PCStackInfo struct specify a
- * 1-1 mapping between these inlined methods and their bytecode indices.
- * This can be used to derive the proper source lines of the inlined
- * methods.
- */
-
-#ifndef _JVMTI_CMLR_H_
-#define _JVMTI_CMLR_H_
-
-enum {
- JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001,
- JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000,
-
- JVMTI_CMLR_MAJOR_VERSION = 0x00000001,
- JVMTI_CMLR_MINOR_VERSION = 0x00000000
-
- /*
- * This comment is for the "JDK import from HotSpot" sanity check:
- * version: 1.0.0
- */
-};
-
-typedef enum {
- JVMTI_CMLR_DUMMY = 1,
- JVMTI_CMLR_INLINE_INFO = 2
-} jvmtiCMLRKind;
-
-/*
- * Record that represents arbitrary information passed through JVMTI
- * CompiledMethodLoadEvent void pointer.
- */
-typedef struct _jvmtiCompiledMethodLoadRecordHeader {
- jvmtiCMLRKind kind; /* id for the kind of info passed in the record */
- jint majorinfoversion; /* major and minor info version values. Init'ed */
- jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */
-
- struct _jvmtiCompiledMethodLoadRecordHeader* next;
-} jvmtiCompiledMethodLoadRecordHeader;
-
-/*
- * Record that gives information about the methods on the compile-time
- * stack at a specific pc address of a compiled method. Each element in
- * the methods array maps to same element in the bcis array.
- */
-typedef struct _PCStackInfo {
- void* pc; /* the pc address for this compiled method */
- jint numstackframes; /* number of methods on the stack */
- jmethodID* methods; /* array of numstackframes method ids */
- jint* bcis; /* array of numstackframes bytecode indices */
-} PCStackInfo;
-
-/*
- * Record that contains inlining information for each pc address of
- * an nmethod.
- */
-typedef struct _jvmtiCompiledMethodLoadInlineRecord {
- jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
- jint numpcs; /* number of pc descriptors in this nmethod */
- PCStackInfo* pcinfo; /* array of numpcs pc descriptors */
-} jvmtiCompiledMethodLoadInlineRecord;
-
-/*
- * Dummy record used to test that we can pass records with different
- * information through the void pointer provided that they can be cast
- * to a jvmtiCompiledMethodLoadRecordHeader.
- */
-
-typedef struct _jvmtiCompiledMethodLoadDummyRecord {
- jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
- char message[50];
-} jvmtiCompiledMethodLoadDummyRecord;
-
-#endif
--- a/src/hotspot/share/code/nmethod.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/code/nmethod.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -411,11 +411,8 @@
_oops_do_mark_link = NULL;
_jmethod_id = NULL;
_osr_link = NULL;
- if (UseG1GC) {
- _unloading_next = NULL;
- } else {
- _scavenge_root_link = NULL;
- }
+ _unloading_next = NULL;
+ _scavenge_root_link = NULL;
_scavenge_root_state = 0;
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM;
@@ -599,12 +596,9 @@
code_buffer->copy_code_and_locs_to(this);
code_buffer->copy_values_to(this);
if (ScavengeRootsInCode) {
- if (detect_scavenge_root_oops()) {
- CodeCache::add_scavenge_root_nmethod(this);
- }
Universe::heap()->register_nmethod(this);
}
- debug_only(verify_scavenge_root_oops());
+ debug_only(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
}
@@ -754,12 +748,9 @@
debug_info->copy_to(this);
dependencies->copy_to(this);
if (ScavengeRootsInCode) {
- if (detect_scavenge_root_oops()) {
- CodeCache::add_scavenge_root_nmethod(this);
- }
Universe::heap()->register_nmethod(this);
}
- debug_only(verify_scavenge_root_oops());
+ debug_only(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
@@ -1661,20 +1652,16 @@
// This code must be MP safe, because it is used from parallel GC passes.
bool nmethod::test_set_oops_do_mark() {
assert(nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called");
- nmethod* observed_mark_link = _oops_do_mark_link;
- if (observed_mark_link == NULL) {
+ if (_oops_do_mark_link == NULL) {
// Claim this nmethod for this thread to mark.
- observed_mark_link = (nmethod*)
- Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_link, NULL);
- if (observed_mark_link == NULL) {
-
+ if (Atomic::cmpxchg(NMETHOD_SENTINEL, &_oops_do_mark_link, (nmethod*)NULL) == NULL) {
// Atomically append this nmethod (now claimed) to the head of the list:
nmethod* observed_mark_nmethods = _oops_do_mark_nmethods;
for (;;) {
nmethod* required_mark_nmethods = observed_mark_nmethods;
_oops_do_mark_link = required_mark_nmethods;
- observed_mark_nmethods = (nmethod*)
- Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods);
+ observed_mark_nmethods =
+ Atomic::cmpxchg(this, &_oops_do_mark_nmethods, required_mark_nmethods);
if (observed_mark_nmethods == required_mark_nmethods)
break;
}
@@ -1690,9 +1677,9 @@
void nmethod::oops_do_marking_prologue() {
if (TraceScavenge) { tty->print_cr("[oops_do_marking_prologue"); }
assert(_oops_do_mark_nmethods == NULL, "must not call oops_do_marking_prologue twice in a row");
- // We use cmpxchg_ptr instead of regular assignment here because the user
+ // We use cmpxchg instead of regular assignment here because the user
// may fork a bunch of threads, and we need them all to see the same state.
- void* observed = Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_nmethods, NULL);
+ nmethod* observed = Atomic::cmpxchg(NMETHOD_SENTINEL, &_oops_do_mark_nmethods, (nmethod*)NULL);
guarantee(observed == NULL, "no races in this sequential code");
}
@@ -1707,8 +1694,8 @@
NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark"));
cur = next;
}
- void* required = _oops_do_mark_nmethods;
- void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required);
+ nmethod* required = _oops_do_mark_nmethods;
+ nmethod* observed = Atomic::cmpxchg((nmethod*)NULL, &_oops_do_mark_nmethods, required);
guarantee(observed == required, "no races in this sequential code");
if (TraceScavenge) { tty->print_cr("oops_do_marking_epilogue]"); }
}
@@ -2137,7 +2124,7 @@
VerifyOopsClosure voc(this);
oops_do(&voc);
assert(voc.ok(), "embedded oops must be OK");
- verify_scavenge_root_oops();
+ Universe::heap()->verify_nmethod(this);
verify_scopes();
}
@@ -2230,10 +2217,6 @@
};
void nmethod::verify_scavenge_root_oops() {
- if (UseG1GC) {
- return;
- }
-
if (!on_scavenge_root_list()) {
// Actually look inside, to verify the claim that it's clean.
DebugScavengeRoot debug_scavenge_root(this);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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/cms/concurrentMarkSweepThread.hpp"
+#include "gc/cms/cmsHeap.hpp"
+#include "gc/cms/vmCMSOperations.hpp"
+#include "gc/shared/genOopClosures.inline.hpp"
+#include "gc/shared/strongRootsScope.hpp"
+#include "gc/shared/workgroup.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/vmThread.hpp"
+#include "utilities/stack.inline.hpp"
+
+CMSHeap::CMSHeap(GenCollectorPolicy *policy) : GenCollectedHeap(policy) {
+ _workers = new WorkGang("GC Thread", ParallelGCThreads,
+ /* are_GC_task_threads */true,
+ /* are_ConcurrentGC_threads */false);
+ _workers->initialize_workers();
+}
+
+jint CMSHeap::initialize() {
+ jint status = GenCollectedHeap::initialize();
+ if (status != JNI_OK) return status;
+
+ // If we are running CMS, create the collector responsible
+ // for collecting the CMS generations.
+ assert(collector_policy()->is_concurrent_mark_sweep_policy(), "must be CMS policy");
+ create_cms_collector();
+
+ return JNI_OK;
+}
+
+void CMSHeap::check_gen_kinds() {
+ assert(young_gen()->kind() == Generation::ParNew,
+ "Wrong youngest generation type");
+ assert(old_gen()->kind() == Generation::ConcurrentMarkSweep,
+ "Wrong generation kind");
+}
+
+CMSHeap* CMSHeap::heap() {
+ CollectedHeap* heap = Universe::heap();
+ assert(heap != NULL, "Uninitialized access to CMSHeap::heap()");
+ assert(heap->kind() == CollectedHeap::CMSHeap, "Not a CMSHeap");
+ return (CMSHeap*) heap;
+}
+
+void CMSHeap::gc_threads_do(ThreadClosure* tc) const {
+ assert(workers() != NULL, "should have workers here");
+ workers()->threads_do(tc);
+ ConcurrentMarkSweepThread::threads_do(tc);
+}
+
+void CMSHeap::print_gc_threads_on(outputStream* st) const {
+ assert(workers() != NULL, "should have workers here");
+ workers()->print_worker_threads_on(st);
+ ConcurrentMarkSweepThread::print_all_on(st);
+}
+
+void CMSHeap::print_on_error(outputStream* st) const {
+ GenCollectedHeap::print_on_error(st);
+ st->cr();
+ CMSCollector::print_on_error(st);
+}
+
+void CMSHeap::create_cms_collector() {
+ assert(old_gen()->kind() == Generation::ConcurrentMarkSweep,
+ "Unexpected generation kinds");
+ assert(gen_policy()->is_concurrent_mark_sweep_policy(), "Unexpected policy type");
+ CMSCollector* collector =
+ new CMSCollector((ConcurrentMarkSweepGeneration*) old_gen(),
+ rem_set(),
+ gen_policy()->as_concurrent_mark_sweep_policy());
+
+ if (!collector->completed_initialization()) {
+ vm_shutdown_during_initialization("Could not create CMS collector");
+ }
+}
+
+void CMSHeap::collect(GCCause::Cause cause) {
+ if (should_do_concurrent_full_gc(cause)) {
+ // Mostly concurrent full collection.
+ collect_mostly_concurrent(cause);
+ } else {
+ GenCollectedHeap::collect(cause);
+ }
+}
+
+bool CMSHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
+ switch (cause) {
+ case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
+ case GCCause::_java_lang_system_gc:
+ case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
+ default: return false;
+ }
+}
+
+void CMSHeap::collect_mostly_concurrent(GCCause::Cause cause) {
+ assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock");
+
+ MutexLocker ml(Heap_lock);
+ // Read the GC counts while holding the Heap_lock
+ unsigned int full_gc_count_before = total_full_collections();
+ unsigned int gc_count_before = total_collections();
+ {
+ MutexUnlocker mu(Heap_lock);
+ VM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause);
+ VMThread::execute(&op);
+ }
+}
+
+void CMSHeap::stop() {
+ ConcurrentMarkSweepThread::cmst()->stop();
+}
+
+void CMSHeap::safepoint_synchronize_begin() {
+ ConcurrentMarkSweepThread::synchronize(false);
+}
+
+void CMSHeap::safepoint_synchronize_end() {
+ ConcurrentMarkSweepThread::desynchronize(false);
+}
+
+void CMSHeap::cms_process_roots(StrongRootsScope* scope,
+ bool young_gen_as_roots,
+ ScanningOption so,
+ bool only_strong_roots,
+ OopsInGenClosure* root_closure,
+ CLDClosure* cld_closure) {
+ MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations);
+ OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure;
+ CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
+
+ process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure);
+ if (!only_strong_roots) {
+ process_string_table_roots(scope, root_closure);
+ }
+
+ if (young_gen_as_roots &&
+ !_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
+ root_closure->set_generation(young_gen());
+ young_gen()->oop_iterate(root_closure);
+ root_closure->reset_generation();
+ }
+
+ _process_strong_tasks->all_tasks_completed(scope->n_threads());
+}
+
+void CMSHeap::gc_prologue(bool full) {
+ always_do_update_barrier = false;
+ GenCollectedHeap::gc_prologue(full);
+};
+
+void CMSHeap::gc_epilogue(bool full) {
+ GenCollectedHeap::gc_epilogue(full);
+ always_do_update_barrier = true;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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_CMS_CMSHEAP_HPP
+#define SHARE_VM_GC_CMS_CMSHEAP_HPP
+
+#include "gc/cms/concurrentMarkSweepGeneration.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/gcCause.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
+
+class CLDClosure;
+class GenCollectorPolicy;
+class OopsInGenClosure;
+class outputStream;
+class StrongRootsScope;
+class ThreadClosure;
+class WorkGang;
+
+class CMSHeap : public GenCollectedHeap {
+public:
+ CMSHeap(GenCollectorPolicy *policy);
+
+ // Returns JNI_OK on success
+ virtual jint initialize();
+
+ virtual void check_gen_kinds();
+
+ // Convenience function to be used in situations where the heap type can be
+ // asserted to be this type.
+ static CMSHeap* heap();
+
+ virtual Name kind() const {
+ return CollectedHeap::CMSHeap;
+ }
+
+ virtual const char* name() const {
+ return "Concurrent Mark Sweep";
+ }
+
+ WorkGang* workers() const { return _workers; }
+
+ virtual void print_gc_threads_on(outputStream* st) const;
+ virtual void gc_threads_do(ThreadClosure* tc) const;
+ virtual void print_on_error(outputStream* st) const;
+
+ // Perform a full collection of the heap; intended for use in implementing
+ // "System.gc". This implies as full a collection as the CollectedHeap
+ // supports. Caller does not hold the Heap_lock on entry.
+ void collect(GCCause::Cause cause);
+
+ bool is_in_closed_subset(const void* p) const {
+ return is_in_reserved(p);
+ }
+
+ bool card_mark_must_follow_store() const {
+ return true;
+ }
+
+ void stop();
+ void safepoint_synchronize_begin();
+ void safepoint_synchronize_end();
+
+ // If "young_gen_as_roots" is false, younger generations are
+ // not scanned as roots; in this case, the caller must be arranging to
+ // scan the younger generations itself. (For example, a generation might
+ // explicitly mark reachable objects in younger generations, to avoid
+ // excess storage retention.)
+ void cms_process_roots(StrongRootsScope* scope,
+ bool young_gen_as_roots,
+ ScanningOption so,
+ bool only_strong_roots,
+ OopsInGenClosure* root_closure,
+ CLDClosure* cld_closure);
+
+private:
+ WorkGang* _workers;
+
+ virtual void gc_prologue(bool full);
+ virtual void gc_epilogue(bool full);
+
+ // Accessor for memory state verification support
+ NOT_PRODUCT(
+ virtual size_t skip_header_HeapWords() { return CMSCollector::skip_header_HeapWords(); }
+ )
+
+ // Returns success or failure.
+ void create_cms_collector();
+
+ // In support of ExplicitGCInvokesConcurrent functionality
+ bool should_do_concurrent_full_gc(GCCause::Cause cause);
+
+ void collect_mostly_concurrent(GCCause::Cause cause);
+};
+
+#endif // SHARE_VM_GC_CMS_CMSHEAP_HPP
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -23,13 +23,13 @@
*/
#include "precompiled.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/cmsLockVerifier.hpp"
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/shared/blockOffsetTable.inline.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/space.inline.hpp"
#include "gc/shared/spaceDecorator.hpp"
#include "logging/log.hpp"
@@ -154,7 +154,7 @@
cp->space->set_compaction_top(compact_top);
cp->space = cp->space->next_compaction_space();
if (cp->space == NULL) {
- cp->gen = GenCollectedHeap::heap()->young_gen();
+ cp->gen = CMSHeap::heap()->young_gen();
assert(cp->gen != NULL, "compaction must succeed");
cp->space = cp->gen->first_compaction_space();
assert(cp->space != NULL, "generation must have a first compaction space");
@@ -2298,7 +2298,7 @@
// Iterate over all oops in the heap. Uses the _no_header version
// since we are not interested in following the klass pointers.
- GenCollectedHeap::heap()->oop_iterate_no_header(&cl);
+ CMSHeap::heap()->oop_iterate_no_header(&cl);
}
if (VerifyObjectStartArray) {
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -29,6 +29,7 @@
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/cms/cmsCollectorPolicy.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/cmsOopClosures.inline.hpp"
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
@@ -298,14 +299,14 @@
}
AdaptiveSizePolicy* CMSCollector::size_policy() {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- return gch->gen_policy()->size_policy();
+ CMSHeap* heap = CMSHeap::heap();
+ return heap->gen_policy()->size_policy();
}
void ConcurrentMarkSweepGeneration::initialize_performance_counters() {
const char* gen_name = "old";
- GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
+ GenCollectorPolicy* gcp = CMSHeap::heap()->gen_policy();
// Generation Counters - generation 1, 1 subspace
_gen_counters = new GenerationCounters(gen_name, 1, 1,
gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);
@@ -354,8 +355,8 @@
// young generation collection.
double CMSStats::time_until_cms_gen_full() const {
size_t cms_free = _cms_gen->cmsSpace()->free();
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- size_t expected_promotion = MIN2(gch->young_gen()->capacity(),
+ CMSHeap* heap = CMSHeap::heap();
+ size_t expected_promotion = MIN2(heap->young_gen()->capacity(),
(size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average());
if (cms_free > expected_promotion) {
// Start a cms collection if there isn't enough space to promote
@@ -595,12 +596,12 @@
assert(CGC_lock != NULL, "Where's the CGC_lock?");
// Support for parallelizing young gen rescan
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- assert(gch->young_gen()->kind() == Generation::ParNew, "CMS can only be used with ParNew");
- _young_gen = (ParNewGeneration*)gch->young_gen();
- if (gch->supports_inline_contig_alloc()) {
- _top_addr = gch->top_addr();
- _end_addr = gch->end_addr();
+ CMSHeap* heap = CMSHeap::heap();
+ assert(heap->young_gen()->kind() == Generation::ParNew, "CMS can only be used with ParNew");
+ _young_gen = (ParNewGeneration*)heap->young_gen();
+ if (heap->supports_inline_contig_alloc()) {
+ _top_addr = heap->top_addr();
+ _end_addr = heap->end_addr();
assert(_young_gen != NULL, "no _young_gen");
_eden_chunk_index = 0;
_eden_chunk_capacity = (_young_gen->max_capacity() + CMSSamplingGrain) / CMSSamplingGrain;
@@ -762,9 +763,9 @@
log.trace(" Maximum free fraction %f", maximum_free_percentage);
log.trace(" Capacity " SIZE_FORMAT, capacity() / 1000);
log.trace(" Desired capacity " SIZE_FORMAT, desired_capacity / 1000);
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- assert(gch->is_old_gen(this), "The CMS generation should always be the old generation");
- size_t young_size = gch->young_gen()->capacity();
+ CMSHeap* heap = CMSHeap::heap();
+ assert(heap->is_old_gen(this), "The CMS generation should always be the old generation");
+ size_t young_size = heap->young_gen()->capacity();
log.trace(" Young gen size " SIZE_FORMAT, young_size / 1000);
log.trace(" unsafe_max_alloc_nogc " SIZE_FORMAT, unsafe_max_alloc_nogc() / 1000);
log.trace(" contiguous available " SIZE_FORMAT, contiguous_available() / 1000);
@@ -923,7 +924,7 @@
assert_lock_strong(freelistLock());
#ifndef PRODUCT
- if (GenCollectedHeap::heap()->promotion_should_fail()) {
+ if (CMSHeap::heap()->promotion_should_fail()) {
return NULL;
}
#endif // #ifndef PRODUCT
@@ -1000,7 +1001,7 @@
oop old, markOop m,
size_t word_sz) {
#ifndef PRODUCT
- if (GenCollectedHeap::heap()->promotion_should_fail()) {
+ if (CMSHeap::heap()->promotion_should_fail()) {
return NULL;
}
#endif // #ifndef PRODUCT
@@ -1076,7 +1077,7 @@
NOT_PRODUCT(
Atomic::inc(&_numObjectsPromoted);
- Atomic::add_ptr(alloc_sz, &_numWordsPromoted);
+ Atomic::add(alloc_sz, &_numWordsPromoted);
)
return obj;
@@ -1179,10 +1180,10 @@
// We start a collection if we believe an incremental collection may fail;
// this is not likely to be productive in practice because it's probably too
// late anyway.
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- assert(gch->collector_policy()->is_generation_policy(),
+ CMSHeap* heap = CMSHeap::heap();
+ assert(heap->collector_policy()->is_generation_policy(),
"You may want to check the correctness of the following");
- if (gch->incremental_collection_will_fail(true /* consult_young */)) {
+ if (heap->incremental_collection_will_fail(true /* consult_young */)) {
log.print("CMSCollector: collect because incremental collection will fail ");
return true;
}
@@ -1294,8 +1295,8 @@
}
void CMSCollector::request_full_gc(unsigned int full_gc_count, GCCause::Cause cause) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- unsigned int gc_count = gch->total_full_collections();
+ CMSHeap* heap = CMSHeap::heap();
+ unsigned int gc_count = heap->total_full_collections();
if (gc_count == full_gc_count) {
MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
_full_gc_requested = true;
@@ -1307,7 +1308,7 @@
}
bool CMSCollector::is_external_interruption() {
- GCCause::Cause cause = GenCollectedHeap::heap()->gc_cause();
+ GCCause::Cause cause = CMSHeap::heap()->gc_cause();
return GCCause::is_user_requested_gc(cause) ||
GCCause::is_serviceability_requested_gc(cause);
}
@@ -1456,8 +1457,8 @@
// Inform cms gen if this was due to partial collection failing.
// The CMS gen may use this fact to determine its expansion policy.
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- if (gch->incremental_collection_will_fail(false /* don't consult_young */)) {
+ CMSHeap* heap = CMSHeap::heap();
+ if (heap->incremental_collection_will_fail(false /* don't consult_young */)) {
assert(!_cmsGen->incremental_collection_failed(),
"Should have been noticed, reacted to and cleared");
_cmsGen->set_incremental_collection_failed();
@@ -1489,14 +1490,14 @@
// Has the GC time limit been exceeded?
size_t max_eden_size = _young_gen->max_eden_size();
- GCCause::Cause gc_cause = gch->gc_cause();
+ GCCause::Cause gc_cause = heap->gc_cause();
size_policy()->check_gc_overhead_limit(_young_gen->used(),
_young_gen->eden()->used(),
_cmsGen->max_capacity(),
max_eden_size,
full,
gc_cause,
- gch->collector_policy());
+ heap->collector_policy());
// Reset the expansion cause, now that we just completed
// a collection cycle.
@@ -1518,21 +1519,21 @@
// A work method used by the foreground collector to do
// a mark-sweep-compact.
void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
- gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
-
- gch->pre_full_gc_dump(gc_timer);
+ gc_tracer->report_gc_start(heap->gc_cause(), gc_timer->gc_start());
+
+ heap->pre_full_gc_dump(gc_timer);
GCTraceTime(Trace, gc, phases) t("CMS:MSC");
// Temporarily widen the span of the weak reference processing to
// the entire heap.
- MemRegion new_span(GenCollectedHeap::heap()->reserved_region());
+ MemRegion new_span(CMSHeap::heap()->reserved_region());
ReferenceProcessorSpanMutator rp_mut_span(ref_processor(), new_span);
// Temporarily, clear the "is_alive_non_header" field of the
// reference processor.
@@ -1608,7 +1609,7 @@
// No longer a need to do a concurrent collection for Metaspace.
MetaspaceGC::set_should_concurrent_collect(false);
- gch->post_full_gc_dump(gc_timer);
+ heap->post_full_gc_dump(gc_timer);
gc_timer->register_gc_end();
@@ -1702,7 +1703,7 @@
assert(Thread::current()->is_ConcurrentGC_thread(),
"A CMS asynchronous collection is only allowed on a CMS thread.");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
{
bool safepoint_check = Mutex::_no_safepoint_check_flag;
MutexLockerEx hl(Heap_lock, safepoint_check);
@@ -1731,8 +1732,8 @@
_full_gc_requested = false; // acks all outstanding full gc requests
_full_gc_cause = GCCause::_no_gc;
// Signal that we are about to start a collection
- gch->increment_total_full_collections(); // ... starting a collection cycle
- _collection_count_start = gch->total_full_collections();
+ heap->increment_total_full_collections(); // ... starting a collection cycle
+ _collection_count_start = heap->total_full_collections();
}
size_t prev_used = _cmsGen->used();
@@ -1925,9 +1926,9 @@
}
void CMSCollector::save_heap_summary() {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- _last_heap_summary = gch->create_heap_summary();
- _last_metaspace_summary = gch->create_metaspace_summary();
+ CMSHeap* heap = CMSHeap::heap();
+ _last_heap_summary = heap->create_heap_summary();
+ _last_metaspace_summary = heap->create_metaspace_summary();
}
void CMSCollector::report_heap_summary(GCWhen::Type when) {
@@ -2303,10 +2304,10 @@
assert(verification_mark_stack()->isEmpty(), "markStack should be empty");
verify_work_stacks_empty();
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- gch->ensure_parsability(false); // fill TLABs, but no need to retire them
+ CMSHeap* heap = CMSHeap::heap();
+ heap->ensure_parsability(false); // fill TLABs, but no need to retire them
// Update the saved marks which may affect the root scans.
- gch->save_marks();
+ heap->save_marks();
if (CMSRemarkVerifyVariant == 1) {
// In this first variant of verification, we complete
@@ -2329,19 +2330,19 @@
void CMSCollector::verify_after_remark_work_1() {
ResourceMark rm;
HandleMark hm;
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
// Get a clear set of claim bits for the roots processing to work with.
ClassLoaderDataGraph::clear_claimed_marks();
// Mark from roots one level into CMS
MarkRefsIntoClosure notOlder(_span, verification_mark_bm());
- gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
+ heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
{
StrongRootsScope srs(1);
- gch->cms_process_roots(&srs,
+ heap->cms_process_roots(&srs,
true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
@@ -2376,7 +2377,7 @@
log.error("Failed marking verification after remark");
ResourceMark rm;
LogStream ls(log.error());
- gch->print_on(&ls);
+ heap->print_on(&ls);
fatal("CMS: failed marking verification after remark");
}
}
@@ -2399,7 +2400,7 @@
void CMSCollector::verify_after_remark_work_2() {
ResourceMark rm;
HandleMark hm;
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
// Get a clear set of claim bits for the roots processing to work with.
ClassLoaderDataGraph::clear_claimed_marks();
@@ -2409,12 +2410,12 @@
markBitMap());
CLDToOopClosure cld_closure(¬Older, true);
- gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
+ heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
{
StrongRootsScope srs(1);
- gch->cms_process_roots(&srs,
+ heap->cms_process_roots(&srs,
true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
@@ -2803,7 +2804,7 @@
void CMSCollector::checkpointRootsInitial() {
assert(_collectorState == InitialMarking, "Wrong collector state");
check_correct_thread_executing();
- TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
+ TraceCMSMemoryManagerStats tms(_collectorState, CMSHeap::heap()->gc_cause());
save_heap_summary();
report_heap_summary(GCWhen::BeforeGC);
@@ -2844,14 +2845,14 @@
HandleMark hm;
MarkRefsIntoClosure notOlder(_span, &_markBitMap);
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
verify_work_stacks_empty();
verify_overflow_empty();
- gch->ensure_parsability(false); // fill TLABs, but no need to retire them
+ heap->ensure_parsability(false); // fill TLABs, but no need to retire them
// Update the saved marks which may affect the root scans.
- gch->save_marks();
+ heap->save_marks();
// weak reference processing has not started yet.
ref_processor()->set_enqueuing_is_done(false);
@@ -2872,7 +2873,7 @@
#endif
if (CMSParallelInitialMarkEnabled) {
// The parallel version.
- WorkGang* workers = gch->workers();
+ WorkGang* workers = heap->workers();
assert(workers != NULL, "Need parallel worker threads.");
uint n_workers = workers->active_workers();
@@ -2891,11 +2892,11 @@
} else {
// The serial version.
CLDToOopClosure cld_closure(¬Older, true);
- gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
+ heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
StrongRootsScope srs(1);
- gch->cms_process_roots(&srs,
+ heap->cms_process_roots(&srs,
true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
@@ -3179,7 +3180,7 @@
HeapWord* cur = read;
while (f > read) {
cur = read;
- read = (HeapWord*) Atomic::cmpxchg_ptr(f, &_global_finger, cur);
+ read = Atomic::cmpxchg(f, &_global_finger, cur);
if (cur == read) {
// our cas succeeded
assert(_global_finger >= f, "protocol consistency");
@@ -3800,7 +3801,7 @@
bitMapLock());
startTimer();
unsigned int before_count =
- GenCollectedHeap::heap()->total_collections();
+ CMSHeap::heap()->total_collections();
SurvivorSpacePrecleanClosure
sss_cl(this, _span, &_markBitMap, &_markStack,
&pam_cl, before_count, CMSYield);
@@ -4103,7 +4104,7 @@
// world is stopped at this checkpoint
assert(SafepointSynchronize::is_at_safepoint(),
"world should be stopped");
- TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
+ TraceCMSMemoryManagerStats tms(_collectorState, CMSHeap::heap()->gc_cause());
verify_work_stacks_empty();
verify_overflow_empty();
@@ -4112,16 +4113,16 @@
_young_gen->used() / K, _young_gen->capacity() / K);
{
if (CMSScavengeBeforeRemark) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
// Temporarily set flag to false, GCH->do_collection will
// expect it to be false and set to true
- FlagSetting fl(gch->_is_gc_active, false);
-
- gch->do_collection(true, // full (i.e. force, see below)
- false, // !clear_all_soft_refs
- 0, // size
- false, // is_tlab
- GenCollectedHeap::YoungGen // type
+ FlagSetting fl(heap->_is_gc_active, false);
+
+ heap->do_collection(true, // full (i.e. force, see below)
+ false, // !clear_all_soft_refs
+ 0, // size
+ false, // is_tlab
+ GenCollectedHeap::YoungGen // type
);
}
FreelistLocker x(this);
@@ -4142,7 +4143,7 @@
ResourceMark rm;
HandleMark hm;
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
if (should_unload_classes()) {
CodeCache::gc_prologue();
@@ -4162,9 +4163,9 @@
// or of an indication of whether the scavenge did indeed occur,
// we cannot rely on TLAB's having been filled and must do
// so here just in case a scavenge did not happen.
- gch->ensure_parsability(false); // fill TLAB's, but no need to retire them
+ heap->ensure_parsability(false); // fill TLAB's, but no need to retire them
// Update the saved marks which may affect the root scans.
- gch->save_marks();
+ heap->save_marks();
print_eden_and_survivor_chunk_arrays();
@@ -4240,7 +4241,7 @@
_markStack._failed_double = 0;
if ((VerifyAfterGC || VerifyDuringGC) &&
- GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
+ CMSHeap::heap()->total_collections() >= VerifyGCStartAt) {
verify_after_remark();
}
@@ -4262,7 +4263,7 @@
// ---------- scan from roots --------------
_timer.start();
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
ParMarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap));
// ---------- young gen roots --------------
@@ -4278,12 +4279,12 @@
CLDToOopClosure cld_closure(&par_mri_cl, true);
- gch->cms_process_roots(_strong_roots_scope,
- false, // yg was scanned above
- GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
- _collector->should_unload_classes(),
- &par_mri_cl,
- &cld_closure);
+ heap->cms_process_roots(_strong_roots_scope,
+ false, // yg was scanned above
+ GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+ _collector->should_unload_classes(),
+ &par_mri_cl,
+ &cld_closure);
assert(_collector->should_unload_classes()
|| (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
@@ -4387,7 +4388,7 @@
// ---------- rescan from roots --------------
_timer.start();
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
ParMarkRefsIntoAndScanClosure par_mrias_cl(_collector,
_collector->_span, _collector->ref_processor(),
&(_collector->_markBitMap),
@@ -4407,12 +4408,12 @@
// ---------- remaining roots --------------
_timer.reset();
_timer.start();
- gch->cms_process_roots(_strong_roots_scope,
- false, // yg was scanned above
- GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
- _collector->should_unload_classes(),
- &par_mrias_cl,
- NULL); // The dirty klasses will be handled below
+ heap->cms_process_roots(_strong_roots_scope,
+ false, // yg was scanned above
+ GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+ _collector->should_unload_classes(),
+ &par_mrias_cl,
+ NULL); // The dirty klasses will be handled below
assert(_collector->should_unload_classes()
|| (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
@@ -4839,8 +4840,8 @@
// Parallel version of remark
void CMSCollector::do_remark_parallel() {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- WorkGang* workers = gch->workers();
+ CMSHeap* heap = CMSHeap::heap();
+ WorkGang* workers = heap->workers();
assert(workers != NULL, "Need parallel worker threads.");
// Choose to use the number of GC workers most recently set
// into "active_workers".
@@ -4856,7 +4857,7 @@
// the younger_gen cards, so we shouldn't call the following else
// the verification code as well as subsequent younger_refs_iterate
// code would get confused. XXX
- // gch->rem_set()->prepare_for_younger_refs_iterate(true); // parallel
+ // heap->rem_set()->prepare_for_younger_refs_iterate(true); // parallel
// The young gen rescan work will not be done as part of
// process_roots (which currently doesn't know how to
@@ -4898,7 +4899,7 @@
void CMSCollector::do_remark_non_parallel() {
ResourceMark rm;
HandleMark hm;
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);
MarkRefsIntoAndScanClosure
@@ -4939,7 +4940,7 @@
}
}
if (VerifyDuringGC &&
- GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
+ CMSHeap::heap()->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
Universe::verify();
}
@@ -4948,15 +4949,15 @@
verify_work_stacks_empty();
- gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
+ heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
StrongRootsScope srs(1);
- gch->cms_process_roots(&srs,
- true, // young gen as roots
- GenCollectedHeap::ScanningOption(roots_scanning_options()),
- should_unload_classes(),
- &mrias_cl,
- NULL); // The dirty klasses will be handled below
+ heap->cms_process_roots(&srs,
+ true, // young gen as roots
+ GenCollectedHeap::ScanningOption(roots_scanning_options()),
+ should_unload_classes(),
+ &mrias_cl,
+ NULL); // The dirty klasses will be handled below
assert(should_unload_classes()
|| (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
@@ -5148,8 +5149,8 @@
void CMSRefProcTaskExecutor::execute(ProcessTask& task)
{
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- WorkGang* workers = gch->workers();
+ CMSHeap* heap = CMSHeap::heap();
+ WorkGang* workers = heap->workers();
assert(workers != NULL, "Need parallel worker threads.");
CMSRefProcTaskProxy rp_task(task, &_collector,
_collector.ref_processor()->span(),
@@ -5161,8 +5162,8 @@
void CMSRefProcTaskExecutor::execute(EnqueueTask& task)
{
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- WorkGang* workers = gch->workers();
+ CMSHeap* heap = CMSHeap::heap();
+ WorkGang* workers = heap->workers();
assert(workers != NULL, "Need parallel worker threads.");
CMSRefEnqueueTaskProxy enq_task(task);
workers->run_task(&enq_task);
@@ -5195,9 +5196,9 @@
// and a different number of discovered lists may have Ref objects.
// That is OK as long as the Reference lists are balanced (see
// balance_all_queues() and balance_queues()).
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
uint active_workers = ParallelGCThreads;
- WorkGang* workers = gch->workers();
+ WorkGang* workers = heap->workers();
if (workers != NULL) {
active_workers = workers->active_workers();
// The expectation is that active_workers will have already
@@ -5305,7 +5306,7 @@
verify_work_stacks_empty();
verify_overflow_empty();
increment_sweep_count();
- TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
+ TraceCMSMemoryManagerStats tms(_collectorState, CMSHeap::heap()->gc_cause());
_inter_sweep_timer.stop();
_inter_sweep_estimate.sample(_inter_sweep_timer.seconds());
@@ -5378,9 +5379,9 @@
// this generation. If such a promotion may still fail,
// the flag will be set again when a young collection is
// attempted.
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- gch->clear_incremental_collection_failed(); // Worth retrying as fresh space may have been freed up
- gch->update_full_collections_completed(_collection_count_start);
+ CMSHeap* heap = CMSHeap::heap();
+ heap->clear_incremental_collection_failed(); // Worth retrying as fresh space may have been freed up
+ heap->update_full_collections_completed(_collection_count_start);
}
// FIX ME!!! Looks like this belongs in CFLSpace, with
@@ -5415,7 +5416,7 @@
bool full) {
// If the young generation has been collected, gather any statistics
// that are of interest at this point.
- bool current_is_young = GenCollectedHeap::heap()->is_young_gen(current_generation);
+ bool current_is_young = CMSHeap::heap()->is_young_gen(current_generation);
if (!full && current_is_young) {
// Gather statistics on the young generation collection.
collector()->stats().record_gc0_end(used());
@@ -6188,7 +6189,7 @@
do_yield_check();
}
unsigned int after_count =
- GenCollectedHeap::heap()->total_collections();
+ CMSHeap::heap()->total_collections();
bool abort = (_before_count != after_count) ||
_collector->should_abort_preclean();
return abort ? 0 : size;
@@ -7852,7 +7853,7 @@
return false;
}
// Grab the entire list; we'll put back a suffix
- oop prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list));
+ oop prefix = cast_to_oop(Atomic::xchg((oopDesc*)BUSY, &_overflow_list));
Thread* tid = Thread::current();
// Before "no_of_gc_threads" was introduced CMSOverflowSpinCount was
// set to ParallelGCThreads.
@@ -7867,7 +7868,7 @@
return false;
} else if (_overflow_list != BUSY) {
// Try and grab the prefix
- prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list));
+ prefix = cast_to_oop(Atomic::xchg((oopDesc*)BUSY, &_overflow_list));
}
}
// If the list was found to be empty, or we spun long
@@ -7880,7 +7881,7 @@
if (prefix == NULL) {
// Write back the NULL in case we overwrote it with BUSY above
// and it is still the same value.
- (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
+ Atomic::cmpxchg((oopDesc*)NULL, &_overflow_list, (oopDesc*)BUSY);
}
return false;
}
@@ -7895,7 +7896,7 @@
// Write back the NULL in lieu of the BUSY we wrote
// above, if it is still the same value.
if (_overflow_list == BUSY) {
- (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
+ Atomic::cmpxchg((oopDesc*)NULL, &_overflow_list, (oopDesc*)BUSY);
}
} else {
// Chop off the suffix and return it to the global list.
@@ -7911,7 +7912,7 @@
bool attached = false;
while (observed_overflow_list == BUSY || observed_overflow_list == NULL) {
observed_overflow_list =
- (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)suffix_head, &_overflow_list, (oopDesc*)cur_overflow_list);
if (cur_overflow_list == observed_overflow_list) {
attached = true;
break;
@@ -7936,7 +7937,7 @@
}
// ... and try to place spliced list back on overflow_list ...
observed_overflow_list =
- (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)suffix_head, &_overflow_list, (oopDesc*)cur_overflow_list);
} while (cur_overflow_list != observed_overflow_list);
// ... until we have succeeded in doing so.
}
@@ -7957,7 +7958,7 @@
}
#ifndef PRODUCT
assert(_num_par_pushes >= n, "Too many pops?");
- Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes);
+ Atomic::sub(n, &_num_par_pushes);
#endif
return true;
}
@@ -7986,7 +7987,7 @@
p->set_mark(NULL);
}
observed_overflow_list =
- (oop) Atomic::cmpxchg_ptr(p, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)p, &_overflow_list, (oopDesc*)cur_overflow_list);
} while (cur_overflow_list != observed_overflow_list);
}
#undef BUSY
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -25,13 +25,13 @@
#ifndef SHARE_VM_GC_CMS_CONCURRENTMARKSWEEPGENERATION_INLINE_HPP
#define SHARE_VM_GC_CMS_CONCURRENTMARKSWEEPGENERATION_INLINE_HPP
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/cmsLockVerifier.hpp"
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.hpp"
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/cms/parNewGeneration.hpp"
#include "gc/shared/gcUtil.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "utilities/align.hpp"
#include "utilities/bitMap.inline.hpp"
@@ -256,7 +256,7 @@
// scavenge is done or foreground GC wants to take over collection
return _collectorState == AbortablePreclean &&
(_abort_preclean || _foregroundGCIsActive ||
- GenCollectedHeap::heap()->incremental_collection_will_fail(true /* consult_young */));
+ CMSHeap::heap()->incremental_collection_will_fail(true /* consult_young */));
}
inline size_t CMSCollector::get_eden_used() const {
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,10 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/shared/gcId.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -225,7 +225,7 @@
// Wait time in millis or 0 value representing infinite wait for a scavenge
assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
double start_time_secs = os::elapsedTime();
double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS));
@@ -233,7 +233,7 @@
unsigned int before_count;
{
MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
- before_count = gch->total_collections();
+ before_count = heap->total_collections();
}
unsigned int loop_count = 0;
@@ -279,7 +279,7 @@
unsigned int after_count;
{
MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
- after_count = gch->total_collections();
+ after_count = heap->total_collections();
}
if(before_count != after_count) {
--- a/src/hotspot/share/gc/cms/parCardTableModRefBS.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/parCardTableModRefBS.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,10 +23,10 @@
*/
#include "precompiled.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/shared/cardTableModRefBS.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/space.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/virtualspace.hpp"
@@ -394,7 +394,7 @@
// Do a dirty read here. If we pass the conditional then take the rare
// event lock and do the read again in case some other thread had already
// succeeded and done the resize.
- int cur_collection = GenCollectedHeap::heap()->total_collections();
+ int cur_collection = CMSHeap::heap()->total_collections();
// Updated _last_LNC_resizing_collection[i] must not be visible before
// _lowest_non_clean and friends are visible. Therefore use acquire/release
// to guarantee this on non TSO architecures.
--- a/src/hotspot/share/gc/cms/parNewGeneration.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/compactibleFreeListSpace.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.hpp"
#include "gc/cms/parNewGeneration.inline.hpp"
@@ -124,7 +125,7 @@
void ParScanThreadState::scan_partial_array_and_push_remainder(oop old) {
assert(old->is_objArray(), "must be obj array");
assert(old->is_forwarded(), "must be forwarded");
- assert(GenCollectedHeap::heap()->is_in_reserved(old), "must be in heap.");
+ assert(CMSHeap::heap()->is_in_reserved(old), "must be in heap.");
assert(!old_gen()->is_in(old), "must be in young generation.");
objArrayOop obj = objArrayOop(old->forwardee());
@@ -205,9 +206,9 @@
for (size_t i = 0; i != num_take_elems; i++) {
oop cur = of_stack->pop();
oop obj_to_push = cur->forwardee();
- assert(GenCollectedHeap::heap()->is_in_reserved(cur), "Should be in heap");
+ assert(CMSHeap::heap()->is_in_reserved(cur), "Should be in heap");
assert(!old_gen()->is_in_reserved(cur), "Should be in young gen");
- assert(GenCollectedHeap::heap()->is_in_reserved(obj_to_push), "Should be in heap");
+ assert(CMSHeap::heap()->is_in_reserved(obj_to_push), "Should be in heap");
if (should_be_partially_scanned(obj_to_push, cur)) {
assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
obj_to_push = cur;
@@ -590,7 +591,7 @@
{}
void ParNewGenTask::work(uint worker_id) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
// Since this is being done in a separate thread, need new resource
// and handle marks.
ResourceMark rm;
@@ -602,10 +603,10 @@
par_scan_state.set_young_old_boundary(_young_old_boundary);
CLDScanClosure cld_scan_closure(&par_scan_state.to_space_root_closure(),
- gch->rem_set()->cld_rem_set()->accumulate_modified_oops());
+ heap->rem_set()->cld_rem_set()->accumulate_modified_oops());
par_scan_state.start_strong_roots();
- gch->young_process_roots(_strong_roots_scope,
+ heap->young_process_roots(_strong_roots_scope,
&par_scan_state.to_space_root_closure(),
&par_scan_state.older_gen_closure(),
&cld_scan_closure);
@@ -687,7 +688,7 @@
_par_cl->do_oop_nv(p);
- if (GenCollectedHeap::heap()->is_in_reserved(p)) {
+ if (CMSHeap::heap()->is_in_reserved(p)) {
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
_rs->write_ref_field_gc_par(p, obj);
}
@@ -714,7 +715,7 @@
_cl->do_oop_nv(p);
- if (GenCollectedHeap::heap()->is_in_reserved(p)) {
+ if (CMSHeap::heap()->is_in_reserved(p)) {
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
_rs->write_ref_field_gc_par(p, obj);
}
@@ -804,7 +805,7 @@
};
void ParNewRefProcTaskExecutor::execute(ProcessTask& task) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* gch = CMSHeap::heap();
WorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
_state_set.reset(workers->active_workers(), _young_gen.promotion_failed());
@@ -816,7 +817,7 @@
}
void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) {
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* gch = CMSHeap::heap();
WorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
ParNewRefEnqueueTaskProxy enq_task(task);
@@ -825,8 +826,8 @@
void ParNewRefProcTaskExecutor::set_single_threaded_mode() {
_state_set.flush();
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- gch->save_marks();
+ CMSHeap* heap = CMSHeap::heap();
+ heap->save_marks();
}
ScanClosureWithParBarrier::
@@ -835,10 +836,10 @@
{ }
EvacuateFollowersClosureGeneral::
-EvacuateFollowersClosureGeneral(GenCollectedHeap* gch,
+EvacuateFollowersClosureGeneral(CMSHeap* heap,
OopsInGenClosure* cur,
OopsInGenClosure* older) :
- _gch(gch),
+ _heap(heap),
_scan_cur_or_nonheap(cur), _scan_older(older)
{ }
@@ -846,15 +847,15 @@
do {
// Beware: this call will lead to closure applications via virtual
// calls.
- _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen,
- _scan_cur_or_nonheap,
- _scan_older);
- } while (!_gch->no_allocs_since_save_marks());
+ _heap->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen,
+ _scan_cur_or_nonheap,
+ _scan_older);
+ } while (!_heap->no_allocs_since_save_marks());
}
// A Generation that does parallel young-gen collection.
-void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set) {
+void ParNewGeneration::handle_promotion_failed(CMSHeap* gch, ParScanThreadStateSet& thread_state_set) {
assert(_promo_failure_scan_stack.is_empty(), "post condition");
_promo_failure_scan_stack.clear(true); // Clear cached segments.
@@ -883,7 +884,7 @@
bool is_tlab) {
assert(full || size > 0, "otherwise we don't want to collect");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* gch = CMSHeap::heap();
_gc_timer->register_gc_start();
@@ -1064,7 +1065,7 @@
}
size_t ParNewGeneration::desired_plab_sz() {
- return _plab_stats.desired_plab_sz(GenCollectedHeap::heap()->workers()->active_workers());
+ return _plab_stats.desired_plab_sz(CMSHeap::heap()->workers()->active_workers());
}
static int sum;
@@ -1168,7 +1169,7 @@
} else {
// Is in to-space; do copying ourselves.
Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
- assert(GenCollectedHeap::heap()->is_in_reserved(new_obj), "illegal forwarding pointer value.");
+ assert(CMSHeap::heap()->is_in_reserved(new_obj), "illegal forwarding pointer value.");
forward_ptr = old->forward_to_atomic(new_obj);
// Restore the mark word copied above.
new_obj->set_mark(m);
@@ -1296,7 +1297,7 @@
from_space_obj->set_klass_to_list_ptr(NULL);
}
observed_overflow_list =
- (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)from_space_obj, &_overflow_list, (oopDesc*)cur_overflow_list);
} while (cur_overflow_list != observed_overflow_list);
}
}
@@ -1339,7 +1340,7 @@
if (_overflow_list == NULL) return false;
// Otherwise, there was something there; try claiming the list.
- oop prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list));
+ oop prefix = cast_to_oop(Atomic::xchg((oopDesc*)BUSY, &_overflow_list));
// Trim off a prefix of at most objsFromOverflow items
Thread* tid = Thread::current();
size_t spin_count = ParallelGCThreads;
@@ -1353,7 +1354,7 @@
return false;
} else if (_overflow_list != BUSY) {
// try and grab the prefix
- prefix = cast_to_oop(Atomic::xchg_ptr(BUSY, &_overflow_list));
+ prefix = cast_to_oop(Atomic::xchg((oopDesc*)BUSY, &_overflow_list));
}
}
if (prefix == NULL || prefix == BUSY) {
@@ -1361,7 +1362,7 @@
if (prefix == NULL) {
// Write back the NULL in case we overwrote it with BUSY above
// and it is still the same value.
- (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
+ (void) Atomic::cmpxchg((oopDesc*)NULL, &_overflow_list, (oopDesc*)BUSY);
}
return false;
}
@@ -1380,7 +1381,7 @@
// Write back the NULL in lieu of the BUSY we wrote
// above and it is still the same value.
if (_overflow_list == BUSY) {
- (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY);
+ (void) Atomic::cmpxchg((oopDesc*)NULL, &_overflow_list, (oopDesc*)BUSY);
}
} else {
assert(suffix != BUSY, "Error");
@@ -1394,7 +1395,7 @@
bool attached = false;
while (observed_overflow_list == BUSY || observed_overflow_list == NULL) {
observed_overflow_list =
- (oop) Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)suffix, &_overflow_list, (oopDesc*)cur_overflow_list);
if (cur_overflow_list == observed_overflow_list) {
attached = true;
break;
@@ -1420,7 +1421,7 @@
last->set_klass_to_list_ptr(NULL);
}
observed_overflow_list =
- (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
+ Atomic::cmpxchg((oopDesc*)suffix, &_overflow_list, (oopDesc*)cur_overflow_list);
} while (cur_overflow_list != observed_overflow_list);
}
}
@@ -1452,7 +1453,7 @@
TASKQUEUE_STATS_ONLY(par_scan_state->note_overflow_refill(n));
#ifndef PRODUCT
assert(_num_par_pushes >= n, "Too many pops?");
- Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes);
+ Atomic::sub(n, &_num_par_pushes);
#endif
return true;
}
@@ -1475,3 +1476,9 @@
const char* ParNewGeneration::name() const {
return "par new generation";
}
+
+void ParNewGeneration::restore_preserved_marks() {
+ SharedRestorePreservedMarksTaskExecutor task_executor(CMSHeap::heap()->workers());
+ _preserved_marks_set.restore(&task_executor);
+}
+
--- a/src/hotspot/share/gc/cms/parNewGeneration.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
#include "memory/padded.hpp"
class ChunkArray;
+class CMSHeap;
class ParScanWithoutBarrierClosure;
class ParScanWithBarrierClosure;
class ParRootScanWithoutBarrierClosure;
@@ -259,11 +260,11 @@
class EvacuateFollowersClosureGeneral: public VoidClosure {
private:
- GenCollectedHeap* _gch;
+ CMSHeap* _heap;
OopsInGenClosure* _scan_cur_or_nonheap;
OopsInGenClosure* _scan_older;
public:
- EvacuateFollowersClosureGeneral(GenCollectedHeap* gch,
+ EvacuateFollowersClosureGeneral(CMSHeap* heap,
OopsInGenClosure* cur,
OopsInGenClosure* older);
virtual void do_void();
@@ -336,7 +337,7 @@
static oop real_forwardee_slow(oop obj);
static void waste_some_time();
- void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set);
+ void handle_promotion_failed(CMSHeap* gch, ParScanThreadStateSet& thread_state_set);
protected:
@@ -345,6 +346,8 @@
bool survivor_overflow() { return _survivor_overflow; }
void set_survivor_overflow(bool v) { _survivor_overflow = v; }
+ void restore_preserved_marks();
+
public:
ParNewGeneration(ReservedSpace rs, size_t initial_byte_size);
--- a/src/hotspot/share/gc/cms/parOopClosures.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/parOopClosures.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -25,10 +25,10 @@
#ifndef SHARE_VM_GC_CMS_PAROOPCLOSURES_INLINE_HPP
#define SHARE_VM_GC_CMS_PAROOPCLOSURES_INLINE_HPP
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/parNewGeneration.hpp"
#include "gc/cms/parOopClosures.hpp"
#include "gc/shared/cardTableRS.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
@@ -72,9 +72,9 @@
inline void ParScanClosure::do_oop_work(T* p,
bool gc_barrier,
bool root_scan) {
- assert((!GenCollectedHeap::heap()->is_in_reserved(p) ||
+ assert((!CMSHeap::heap()->is_in_reserved(p) ||
generation()->is_in_reserved(p))
- && (GenCollectedHeap::heap()->is_young_gen(generation()) || gc_barrier),
+ && (CMSHeap::heap()->is_young_gen(generation()) || gc_barrier),
"The gen must be right, and we must be doing the barrier "
"in older generations.");
T heap_oop = oopDesc::load_heap_oop(p);
@@ -85,8 +85,8 @@
if (_g->to()->is_in_reserved(obj)) {
Log(gc) log;
log.error("Scanning field (" PTR_FORMAT ") twice?", p2i(p));
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- Space* sp = gch->space_containing(p);
+ CMSHeap* heap = CMSHeap::heap();
+ Space* sp = heap->space_containing(p);
oop obj = oop(sp->block_start(p));
assert((HeapWord*)obj < (HeapWord*)p, "Error");
log.error("Object: " PTR_FORMAT, p2i((void *)obj));
@@ -96,7 +96,7 @@
log.error("-----");
log.error("Heap:");
log.error("-----");
- gch->print_on(&ls);
+ heap->print_on(&ls);
ShouldNotReachHere();
}
#endif
--- a/src/hotspot/share/gc/cms/vmCMSOperations.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/cms/vmCMSOperations.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/cms/vmCMSOperations.hpp"
@@ -39,19 +40,19 @@
//////////////////////////////////////////////////////////
void VM_CMS_Operation::verify_before_gc() {
if (VerifyBeforeGC &&
- GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
+ CMSHeap::heap()->total_collections() >= VerifyGCStartAt) {
GCTraceTime(Info, gc, phases, verify) tm("Verify Before", _collector->_gc_timer_cm);
HandleMark hm;
FreelistLocker x(_collector);
MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
- GenCollectedHeap::heap()->prepare_for_verify();
+ CMSHeap::heap()->prepare_for_verify();
Universe::verify();
}
}
void VM_CMS_Operation::verify_after_gc() {
if (VerifyAfterGC &&
- GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
+ CMSHeap::heap()->total_collections() >= VerifyGCStartAt) {
GCTraceTime(Info, gc, phases, verify) tm("Verify After", _collector->_gc_timer_cm);
HandleMark hm;
FreelistLocker x(_collector);
@@ -112,13 +113,13 @@
_collector->_gc_timer_cm->register_gc_pause_start("Initial Mark");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- GCCauseSetter gccs(gch, GCCause::_cms_initial_mark);
+ CMSHeap* heap = CMSHeap::heap();
+ GCCauseSetter gccs(heap, GCCause::_cms_initial_mark);
VM_CMS_Operation::verify_before_gc();
IsGCActiveMark x; // stop-world GC active
- _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());
+ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, heap->gc_cause());
VM_CMS_Operation::verify_after_gc();
@@ -140,13 +141,13 @@
_collector->_gc_timer_cm->register_gc_pause_start("Final Mark");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- GCCauseSetter gccs(gch, GCCause::_cms_final_remark);
+ CMSHeap* heap = CMSHeap::heap();
+ GCCauseSetter gccs(heap, GCCause::_cms_final_remark);
VM_CMS_Operation::verify_before_gc();
IsGCActiveMark x; // stop-world GC active
- _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause());
+ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, heap->gc_cause());
VM_CMS_Operation::verify_after_gc();
@@ -162,8 +163,8 @@
assert(Thread::current()->is_VM_thread(), "Should be VM thread");
assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- if (_gc_count_before == gch->total_collections()) {
+ CMSHeap* heap = CMSHeap::heap();
+ if (_gc_count_before == heap->total_collections()) {
// The "full" of do_full_collection call below "forces"
// a collection; the second arg, 0, below ensures that
// only the young gen is collected. XXX In the future,
@@ -173,21 +174,21 @@
// for the future.
assert(SafepointSynchronize::is_at_safepoint(),
"We can only be executing this arm of if at a safepoint");
- GCCauseSetter gccs(gch, _gc_cause);
- gch->do_full_collection(gch->must_clear_all_soft_refs(), GenCollectedHeap::YoungGen);
+ GCCauseSetter gccs(heap, _gc_cause);
+ heap->do_full_collection(heap->must_clear_all_soft_refs(), GenCollectedHeap::YoungGen);
} // Else no need for a foreground young gc
- assert((_gc_count_before < gch->total_collections()) ||
+ assert((_gc_count_before < heap->total_collections()) ||
(GCLocker::is_active() /* gc may have been skipped */
- && (_gc_count_before == gch->total_collections())),
+ && (_gc_count_before == heap->total_collections())),
"total_collections() should be monotonically increasing");
MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
- assert(_full_gc_count_before <= gch->total_full_collections(), "Error");
- if (gch->total_full_collections() == _full_gc_count_before) {
+ assert(_full_gc_count_before <= heap->total_full_collections(), "Error");
+ if (heap->total_full_collections() == _full_gc_count_before) {
// Nudge the CMS thread to start a concurrent collection.
CMSCollector::request_full_gc(_full_gc_count_before, _gc_cause);
} else {
- assert(_full_gc_count_before < gch->total_full_collections(), "Error");
+ assert(_full_gc_count_before < heap->total_full_collections(), "Error");
FullGCCount_lock->notify_all(); // Inform the Java thread its work is done
}
}
@@ -197,11 +198,11 @@
assert(thr != NULL, "Unexpected tid");
if (!thr->is_Java_thread()) {
assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
- if (_gc_count_before != gch->total_collections()) {
+ CMSHeap* heap = CMSHeap::heap();
+ if (_gc_count_before != heap->total_collections()) {
// No need to do a young gc, we'll just nudge the CMS thread
// in the doit() method above, to be executed soon.
- assert(_gc_count_before < gch->total_collections(),
+ assert(_gc_count_before < heap->total_collections(),
"total_collections() should be monotonically increasing");
return false; // no need for foreground young gc
}
@@ -227,9 +228,9 @@
// count overflows and wraps around. XXX fix me !!!
// e.g. at the rate of 1 full gc per ms, this could
// overflow in about 1000 years.
- GenCollectedHeap* gch = GenCollectedHeap::heap();
+ CMSHeap* heap = CMSHeap::heap();
if (_gc_cause != GCCause::_gc_locker &&
- gch->total_full_collections_completed() <= _full_gc_count_before) {
+ heap->total_full_collections_completed() <= _full_gc_count_before) {
// maybe we should change the condition to test _gc_cause ==
// GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run,
// instead of _gc_cause != GCCause::_gc_locker
@@ -245,7 +246,7 @@
MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
// Either a concurrent or a stop-world full gc is sufficient
// witness to our request.
- while (gch->total_full_collections_completed() <= _full_gc_count_before) {
+ while (heap->total_full_collections_completed() <= _full_gc_count_before) {
FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
}
}
--- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -280,13 +280,13 @@
BufferNode* nd = _cur_par_buffer_node;
while (nd != NULL) {
BufferNode* next = nd->next();
- void* actual = Atomic::cmpxchg_ptr(next, &_cur_par_buffer_node, nd);
+ BufferNode* actual = Atomic::cmpxchg(next, &_cur_par_buffer_node, nd);
if (actual == nd) {
bool b = apply_closure_to_buffer(cl, nd, false);
guarantee(b, "Should not stop early.");
nd = next;
} else {
- nd = static_cast<BufferNode*>(actual);
+ nd = actual;
}
}
}
--- a/src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -155,19 +155,19 @@
}
G1CodeRootSetTable* G1CodeRootSet::load_acquire_table() {
- return (G1CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table);
+ return OrderAccess::load_acquire(&_table);
}
void G1CodeRootSet::allocate_small_table() {
G1CodeRootSetTable* temp = new G1CodeRootSetTable(SmallSize);
- OrderAccess::release_store_ptr(&_table, temp);
+ OrderAccess::release_store(&_table, temp);
}
void G1CodeRootSetTable::purge_list_append(G1CodeRootSetTable* table) {
for (;;) {
table->_purge_next = _purge_list;
- G1CodeRootSetTable* old = (G1CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next);
+ G1CodeRootSetTable* old = Atomic::cmpxchg(table, &_purge_list, table->_purge_next);
if (old == table->_purge_next) {
break;
}
@@ -191,7 +191,7 @@
G1CodeRootSetTable::purge_list_append(_table);
- OrderAccess::release_store_ptr(&_table, temp);
+ OrderAccess::release_store(&_table, temp);
}
void G1CodeRootSet::purge() {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -141,13 +141,6 @@
reset_from_card_cache(start_idx, num_regions);
}
-// Returns true if the reference points to an object that
-// can move in an incremental collection.
-bool G1CollectedHeap::is_scavengable(const void* p) {
- HeapRegion* hr = heap_region_containing(p);
- return !hr->is_pinned();
-}
-
// Private methods.
HeapRegion*
@@ -1849,6 +1842,14 @@
}
}
+void G1CollectedHeap::safepoint_synchronize_begin() {
+ SuspendibleThreadSet::synchronize();
+}
+
+void G1CollectedHeap::safepoint_synchronize_end() {
+ SuspendibleThreadSet::desynchronize();
+}
+
size_t G1CollectedHeap::conservative_max_heap_alignment() {
return HeapRegion::max_region_size();
}
@@ -3458,10 +3459,10 @@
// Variables used to claim nmethods.
CompiledMethod* _first_nmethod;
- volatile CompiledMethod* _claimed_nmethod;
+ CompiledMethod* volatile _claimed_nmethod;
// The list of nmethods that need to be processed by the second pass.
- volatile CompiledMethod* _postponed_list;
+ CompiledMethod* volatile _postponed_list;
volatile uint _num_entered_barrier;
public:
@@ -3480,7 +3481,7 @@
if(iter.next_alive()) {
_first_nmethod = iter.method();
}
- _claimed_nmethod = (volatile CompiledMethod*)_first_nmethod;
+ _claimed_nmethod = _first_nmethod;
}
~G1CodeCacheUnloadingTask() {
@@ -3496,9 +3497,9 @@
void add_to_postponed_list(CompiledMethod* nm) {
CompiledMethod* old;
do {
- old = (CompiledMethod*)_postponed_list;
+ old = _postponed_list;
nm->set_unloading_next(old);
- } while ((CompiledMethod*)Atomic::cmpxchg_ptr(nm, &_postponed_list, old) != old);
+ } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
}
void clean_nmethod(CompiledMethod* nm) {
@@ -3527,7 +3528,7 @@
do {
*num_claimed_nmethods = 0;
- first = (CompiledMethod*)_claimed_nmethod;
+ first = _claimed_nmethod;
last = CompiledMethodIterator(first);
if (first != NULL) {
@@ -3541,7 +3542,7 @@
}
}
- } while ((CompiledMethod*)Atomic::cmpxchg_ptr(last.method(), &_claimed_nmethod, first) != first);
+ } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
}
CompiledMethod* claim_postponed_nmethod() {
@@ -3549,14 +3550,14 @@
CompiledMethod* next;
do {
- claim = (CompiledMethod*)_postponed_list;
+ claim = _postponed_list;
if (claim == NULL) {
return NULL;
}
next = claim->unloading_next();
- } while ((CompiledMethod*)Atomic::cmpxchg_ptr(next, &_postponed_list, claim) != claim);
+ } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
return claim;
}
@@ -5323,17 +5324,20 @@
void do_oop(narrowOop* p) { do_oop_work(p); }
};
+// Returns true if the reference points to an object that
+// can move in an incremental collection.
+bool G1CollectedHeap::is_scavengable(oop obj) {
+ HeapRegion* hr = heap_region_containing(obj);
+ return !hr->is_pinned();
+}
+
void G1CollectedHeap::register_nmethod(nmethod* nm) {
- CollectedHeap::register_nmethod(nm);
-
guarantee(nm != NULL, "sanity");
RegisterNMethodOopClosure reg_cl(this, nm);
nm->oops_do(®_cl);
}
void G1CollectedHeap::unregister_nmethod(nmethod* nm) {
- CollectedHeap::unregister_nmethod(nm);
-
guarantee(nm != NULL, "sanity");
UnregisterNMethodOopClosure reg_cl(this, nm);
nm->oops_do(®_cl, true);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -968,6 +968,8 @@
jint initialize();
virtual void stop();
+ virtual void safepoint_synchronize_begin();
+ virtual void safepoint_synchronize_end();
// Return the (conservative) maximum heap alignment for any G1 heap
static size_t conservative_max_heap_alignment();
@@ -1282,8 +1284,6 @@
inline bool is_in_young(const oop obj);
- virtual bool is_scavengable(const void* addr);
-
// We don't need barriers for initializing stores to objects
// in the young gen: for the SATB pre-barrier, there is no
// pre-value that needs to be remembered; for the remembered-set
@@ -1395,6 +1395,9 @@
// Optimized nmethod scanning support routines
+ // Is an oop scavengeable
+ virtual bool is_scavengable(oop obj);
+
// Register the given nmethod with the G1 heap.
virtual void register_nmethod(nmethod* nm);
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1870,7 +1870,7 @@
HeapWord* end = curr_region != NULL ? curr_region->end() : finger + HeapRegion::GrainWords;
// Is the gap between reading the finger and doing the CAS too long?
- HeapWord* res = (HeapWord*) Atomic::cmpxchg_ptr(end, &_finger, finger);
+ HeapWord* res = Atomic::cmpxchg(end, &_finger, finger);
if (res == finger && curr_region != NULL) {
// we succeeded
HeapWord* bottom = curr_region->bottom();
--- a/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,17 +29,17 @@
#include "runtime/atomic.hpp"
inline void G1EvacStats::add_direct_allocated(size_t value) {
- Atomic::add_ptr(value, &_direct_allocated);
+ Atomic::add(value, &_direct_allocated);
}
inline void G1EvacStats::add_region_end_waste(size_t value) {
- Atomic::add_ptr(value, &_region_end_waste);
- Atomic::add_ptr(1, &_regions_filled);
+ Atomic::add(value, &_region_end_waste);
+ Atomic::inc(&_regions_filled);
}
inline void G1EvacStats::add_failure_used_and_waste(size_t used, size_t waste) {
- Atomic::add_ptr(used, &_failure_used);
- Atomic::add_ptr(waste, &_failure_waste);
+ Atomic::add(used, &_failure_used);
+ Atomic::add(waste, &_failure_waste);
}
#endif // SHARE_VM_GC_G1_G1EVACSTATS_INLINE_HPP
--- a/src/hotspot/share/gc/g1/g1HotCardCache.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -74,9 +74,9 @@
// card_ptr in favor of the other option, which would be starting over. This
// should be OK since card_ptr will likely be the older card already when/if
// this ever happens.
- jbyte* previous_ptr = (jbyte*)Atomic::cmpxchg_ptr(card_ptr,
- &_hot_cache[masked_index],
- current_ptr);
+ jbyte* previous_ptr = Atomic::cmpxchg(card_ptr,
+ &_hot_cache[masked_index],
+ current_ptr);
return (previous_ptr == current_ptr) ? previous_ptr : card_ptr;
}
--- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -251,7 +251,7 @@
virtual void work(uint worker_id) {
size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
while (true) {
- char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
+ char* touch_addr = Atomic::add(actual_chunk_size, &_cur_addr) - actual_chunk_size;
if (touch_addr < _start_addr || touch_addr >= _end_addr) {
break;
}
--- a/src/hotspot/share/gc/g1/g1StringDedup.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/g1StringDedup.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -203,12 +203,12 @@
// Atomically claims the next available queue for exclusive access by
// the current thread. Returns the queue number of the claimed queue.
size_t G1StringDedupUnlinkOrOopsDoClosure::claim_queue() {
- return (size_t)Atomic::add_ptr(1, &_next_queue) - 1;
+ return Atomic::add((size_t)1, &_next_queue) - 1;
}
// Atomically claims the next available table partition for exclusive
// access by the current thread. Returns the table bucket number where
// the claimed partition starts.
size_t G1StringDedupUnlinkOrOopsDoClosure::claim_table_partition(size_t partition_size) {
- return (size_t)Atomic::add_ptr(partition_size, &_next_bucket) - partition_size;
+ return Atomic::add(partition_size, &_next_bucket) - partition_size;
}
--- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -59,7 +59,7 @@
size_t want_to_allocate = MIN2(available, desired_word_size);
if (want_to_allocate >= min_word_size) {
HeapWord* new_top = obj + want_to_allocate;
- HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj);
+ HeapWord* result = Atomic::cmpxchg(new_top, top_addr(), obj);
// result can be one of two:
// the old top value: the exchange succeeded
// otherwise: the new value of the top is returned.
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -113,9 +113,7 @@
public:
- HeapRegion* hr() const {
- return (HeapRegion*) OrderAccess::load_ptr_acquire(&_hr);
- }
+ HeapRegion* hr() const { return OrderAccess::load_acquire(&_hr); }
jint occupied() const {
// Overkill, but if we ever need it...
@@ -133,7 +131,7 @@
_bm.clear();
// Make sure that the bitmap clearing above has been finished before publishing
// this PRT to concurrent threads.
- OrderAccess::release_store_ptr(&_hr, hr);
+ OrderAccess::release_store(&_hr, hr);
}
void add_reference(OopOrNarrowOopStar from) {
@@ -182,7 +180,7 @@
while (true) {
PerRegionTable* fl = _free_list;
last->set_next(fl);
- PerRegionTable* res = (PerRegionTable*) Atomic::cmpxchg_ptr(prt, &_free_list, fl);
+ PerRegionTable* res = Atomic::cmpxchg(prt, &_free_list, fl);
if (res == fl) {
return;
}
@@ -199,9 +197,7 @@
PerRegionTable* fl = _free_list;
while (fl != NULL) {
PerRegionTable* nxt = fl->next();
- PerRegionTable* res =
- (PerRegionTable*)
- Atomic::cmpxchg_ptr(nxt, &_free_list, fl);
+ PerRegionTable* res = Atomic::cmpxchg(nxt, &_free_list, fl);
if (res == fl) {
fl->init(hr, true);
return fl;
@@ -416,7 +412,7 @@
// some mark bits may not yet seem cleared or a 'later' update
// performed by a concurrent thread could be undone when the
// zeroing becomes visible). This requires store ordering.
- OrderAccess::release_store_ptr((volatile PerRegionTable*)&_fine_grain_regions[ind], prt);
+ OrderAccess::release_store(&_fine_grain_regions[ind], prt);
_n_fine_entries++;
if (G1HRRSUseSparseTable) {
--- a/src/hotspot/share/gc/g1/sparsePRT.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/g1/sparsePRT.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -292,9 +292,7 @@
SparsePRT* hd = _head_expanded_list;
while (true) {
sprt->_next_expanded = hd;
- SparsePRT* res =
- (SparsePRT*)
- Atomic::cmpxchg_ptr(sprt, &_head_expanded_list, hd);
+ SparsePRT* res = Atomic::cmpxchg(sprt, &_head_expanded_list, hd);
if (res == hd) return;
else hd = res;
}
@@ -305,9 +303,7 @@
SparsePRT* hd = _head_expanded_list;
while (hd != NULL) {
SparsePRT* next = hd->next_expanded();
- SparsePRT* res =
- (SparsePRT*)
- Atomic::cmpxchg_ptr(next, &_head_expanded_list, hd);
+ SparsePRT* res = Atomic::cmpxchg(next, &_head_expanded_list, hd);
if (res == hd) {
hd->set_next_expanded(NULL);
return hd;
--- a/src/hotspot/share/gc/parallel/gcTaskThread.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -77,8 +77,7 @@
if (_time_stamps == NULL) {
// We allocate the _time_stamps array lazily since logging can be enabled dynamically
GCTaskTimeStamp* time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries, mtGC);
- void* old = Atomic::cmpxchg_ptr(time_stamps, &_time_stamps, NULL);
- if (old != NULL) {
+ if (Atomic::cmpxchg(time_stamps, &_time_stamps, (GCTaskTimeStamp*)NULL) != NULL) {
// Someone already setup the time stamps
FREE_C_HEAP_ARRAY(GCTaskTimeStamp, time_stamps);
}
--- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -862,7 +862,7 @@
if (p != NULL) {
HeapWord* cur_top, *cur_chunk_top = p + size;
while ((cur_top = top()) < cur_chunk_top) { // Keep _top updated.
- if (Atomic::cmpxchg_ptr(cur_chunk_top, top_addr(), cur_top) == cur_top) {
+ if (Atomic::cmpxchg(cur_chunk_top, top_addr(), cur_top) == cur_top) {
break;
}
}
--- a/src/hotspot/share/gc/parallel/mutableSpace.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -192,7 +192,7 @@
HeapWord* obj = top();
if (pointer_delta(end(), obj) >= size) {
HeapWord* new_top = obj + size;
- HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj);
+ HeapWord* result = Atomic::cmpxchg(new_top, top_addr(), obj);
// result can be one of two:
// the old top value: the exchange succeeded
// otherwise: the new value of the top is returned.
@@ -211,7 +211,7 @@
// Try to deallocate previous allocation. Returns true upon success.
bool MutableSpace::cas_deallocate(HeapWord *obj, size_t size) {
HeapWord* expected_top = obj + size;
- return (HeapWord*)Atomic::cmpxchg_ptr(obj, top_addr(), expected_top) == expected_top;
+ return Atomic::cmpxchg(obj, top_addr(), expected_top) == expected_top;
}
void MutableSpace::oop_iterate_no_header(OopClosure* cl) {
--- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -90,7 +90,7 @@
bool end_bit_ok = _end_bits.par_set_bit(end_bit);
assert(end_bit_ok, "concurrency problem");
DEBUG_ONLY(Atomic::inc(&mark_bitmap_count));
- DEBUG_ONLY(Atomic::add_ptr(size, &mark_bitmap_size));
+ DEBUG_ONLY(Atomic::add(size, &mark_bitmap_size));
return true;
}
return false;
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "code/codeCache.hpp"
#include "gc/parallel/adjoiningGenerations.hpp"
#include "gc/parallel/adjoiningVirtualSpaces.hpp"
#include "gc/parallel/cardTableExtension.hpp"
@@ -169,10 +170,6 @@
return young_gen()->is_in_reserved(p) || old_gen()->is_in_reserved(p);
}
-bool ParallelScavengeHeap::is_scavengable(const void* addr) {
- return is_in_young((oop)addr);
-}
-
// There are two levels of allocation policy here.
//
// When an allocation request fails, the requesting thread must invoke a VM
@@ -665,3 +662,15 @@
}
}
#endif
+
+bool ParallelScavengeHeap::is_scavengable(oop obj) {
+ return is_in_young(obj);
+}
+
+void ParallelScavengeHeap::register_nmethod(nmethod* nm) {
+ CodeCache::register_scavenge_root_nmethod(nm);
+}
+
+void ParallelScavengeHeap::verify_nmethod(nmethod* nm) {
+ CodeCache::verify_scavenge_root_nmethod(nm);
+}
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -134,7 +134,9 @@
// can be moved in a partial collection. For currently implemented
// generational collectors that means during a collection of
// the young gen.
- virtual bool is_scavengable(const void* addr);
+ virtual bool is_scavengable(oop obj);
+ virtual void register_nmethod(nmethod* nm);
+ virtual void verify_nmethod(nmethod* nmethod);
size_t max_capacity() const;
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -521,7 +521,7 @@
const size_t end_region = (obj_ofs + len - 1) >> Log2RegionSize;
DEBUG_ONLY(Atomic::inc(&add_obj_count);)
- DEBUG_ONLY(Atomic::add_ptr(len, &add_obj_size);)
+ DEBUG_ONLY(Atomic::add(len, &add_obj_size);)
if (beg_region == end_region) {
// All in one region.
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -586,7 +586,7 @@
#ifdef ASSERT
HeapWord* tmp = _highest_ref;
while (addr > tmp) {
- tmp = (HeapWord*)Atomic::cmpxchg_ptr(addr, &_highest_ref, tmp);
+ tmp = Atomic::cmpxchg(addr, &_highest_ref, tmp);
}
#endif // #ifdef ASSERT
}
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -734,8 +734,11 @@
RemoveForwardedPointerClosure rspc;
eden()->object_iterate(&rspc);
from()->object_iterate(&rspc);
+ restore_preserved_marks();
+}
- SharedRestorePreservedMarksTaskExecutor task_executor(GenCollectedHeap::heap()->workers());
+void DefNewGeneration::restore_preserved_marks() {
+ SharedRestorePreservedMarksTaskExecutor task_executor(NULL);
_preserved_marks_set.restore(&task_executor);
}
--- a/src/hotspot/share/gc/serial/defNewGeneration.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,8 @@
// therefore we must remove their forwarding pointers.
void remove_forwarding_pointers();
+ virtual void restore_preserved_marks();
+
// Preserved marks
PreservedMarksSet _preserved_marks_set;
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -135,14 +135,6 @@
_barrier_set->print_on(st);
}
-void CollectedHeap::register_nmethod(nmethod* nm) {
- assert_locked_or_safepoint(CodeCache_lock);
-}
-
-void CollectedHeap::unregister_nmethod(nmethod* nm) {
- assert_locked_or_safepoint(CodeCache_lock);
-}
-
void CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) {
const GCHeapSummary& heap_summary = create_heap_summary();
gc_tracer->report_gc_heap_summary(when, heap_summary);
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -83,6 +83,7 @@
// GenCollectedHeap
// G1CollectedHeap
// ParallelScavengeHeap
+// CMSHeap
//
class CollectedHeap : public CHeapObj<mtInternal> {
friend class VMStructs;
@@ -194,7 +195,8 @@
enum Name {
GenCollectedHeap,
ParallelScavengeHeap,
- G1CollectedHeap
+ G1CollectedHeap,
+ CMSHeap
};
static inline size_t filler_array_max_size() {
@@ -219,6 +221,10 @@
// Stop any onging concurrent work and prepare for exit.
virtual void stop() {}
+ // Stop and resume concurrent GC threads interfering with safepoint operations
+ virtual void safepoint_synchronize_begin() {}
+ virtual void safepoint_synchronize_end() {}
+
void initialize_reserved_region(HeapWord *start, HeapWord *end);
MemRegion reserved_region() const { return _reserved; }
address base() const { return (address)reserved_region().start(); }
@@ -287,10 +293,6 @@
return p == NULL || is_in_closed_subset(p);
}
- // An object is scavengable if its location may move during a scavenge.
- // (A scavenge is a GC which is not a full GC.)
- virtual bool is_scavengable(const void *p) = 0;
-
void set_gc_cause(GCCause::Cause v) {
if (UsePerfData) {
_gc_lastcause = _gc_cause;
@@ -568,10 +570,14 @@
void print_heap_before_gc();
void print_heap_after_gc();
+ // An object is scavengable if its location may move during a scavenge.
+ // (A scavenge is a GC which is not a full GC.)
+ virtual bool is_scavengable(oop obj) = 0;
// Registering and unregistering an nmethod (compiled code) with the heap.
// Override with specific mechanism for each specialized heap type.
- virtual void register_nmethod(nmethod* nm);
- virtual void unregister_nmethod(nmethod* nm);
+ virtual void register_nmethod(nmethod* nm) {}
+ virtual void unregister_nmethod(nmethod* nm) {}
+ virtual void verify_nmethod(nmethod* nmethod) {}
void trace_heap_before_gc(const GCTracer* gc_tracer);
void trace_heap_after_gc(const GCTracer* gc_tracer);
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -58,28 +58,6 @@
#include "utilities/macros.hpp"
#include "utilities/stack.inline.hpp"
#include "utilities/vmError.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/cms/concurrentMarkSweepThread.hpp"
-#include "gc/cms/vmCMSOperations.hpp"
-#endif // INCLUDE_ALL_GCS
-
-NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;)
-
-// The set of potentially parallel tasks in root scanning.
-enum GCH_strong_roots_tasks {
- GCH_PS_Universe_oops_do,
- GCH_PS_JNIHandles_oops_do,
- GCH_PS_ObjectSynchronizer_oops_do,
- GCH_PS_Management_oops_do,
- GCH_PS_SystemDictionary_oops_do,
- GCH_PS_ClassLoaderDataGraph_oops_do,
- GCH_PS_jvmti_oops_do,
- GCH_PS_CodeCache_oops_do,
- GCH_PS_aot_oops_do,
- GCH_PS_younger_gens,
- // Leave this one last.
- GCH_PS_NumElements
-};
GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :
CollectedHeap(),
@@ -89,15 +67,6 @@
_full_collections_completed(0)
{
assert(policy != NULL, "Sanity check");
- if (UseConcMarkSweepGC) {
- _workers = new WorkGang("GC Thread", ParallelGCThreads,
- /* are_GC_task_threads */true,
- /* are_ConcurrentGC_threads */false);
- _workers->initialize_workers();
- } else {
- // Serial GC does not use workers.
- _workers = NULL;
- }
}
jint GenCollectedHeap::initialize() {
@@ -138,15 +107,6 @@
_old_gen = gen_policy()->old_gen_spec()->init(old_rs, rem_set());
clear_incremental_collection_failed();
-#if INCLUDE_ALL_GCS
- // If we are running CMS, create the collector responsible
- // for collecting the CMS generations.
- if (collector_policy()->is_concurrent_mark_sweep_policy()) {
- bool success = create_cms_collector();
- if (!success) return JNI_ENOMEM;
- }
-#endif // INCLUDE_ALL_GCS
-
return JNI_OK;
}
@@ -183,21 +143,22 @@
void GenCollectedHeap::post_initialize() {
ref_processing_init();
- assert((_young_gen->kind() == Generation::DefNew) ||
- (_young_gen->kind() == Generation::ParNew),
- "Wrong youngest generation type");
+ check_gen_kinds();
DefNewGeneration* def_new_gen = (DefNewGeneration*)_young_gen;
- assert(_old_gen->kind() == Generation::ConcurrentMarkSweep ||
- _old_gen->kind() == Generation::MarkSweepCompact,
- "Wrong generation kind");
-
_gen_policy->initialize_size_policy(def_new_gen->eden()->capacity(),
_old_gen->capacity(),
def_new_gen->from()->capacity());
_gen_policy->initialize_gc_policy_counters();
}
+void GenCollectedHeap::check_gen_kinds() {
+ assert(young_gen()->kind() == Generation::DefNew,
+ "Wrong youngest generation type");
+ assert(old_gen()->kind() == Generation::MarkSweepCompact,
+ "Wrong generation kind");
+}
+
void GenCollectedHeap::ref_processing_init() {
_young_gen->ref_processor_init();
_old_gen->ref_processor_init();
@@ -309,19 +270,6 @@
_gc_cause == GCCause::_wb_full_gc;
}
-bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
- if (!UseConcMarkSweepGC) {
- return false;
- }
-
- switch (cause) {
- case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
- case GCCause::_java_lang_system_gc:
- case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
- default: return false;
- }
-}
-
void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,
bool is_tlab, bool run_verification, bool clear_soft_refs,
bool restore_marks_for_biased_locking) {
@@ -553,6 +501,14 @@
#endif
}
+void GenCollectedHeap::register_nmethod(nmethod* nm) {
+ CodeCache::register_scavenge_root_nmethod(nm);
+}
+
+void GenCollectedHeap::verify_nmethod(nmethod* nm) {
+ CodeCache::verify_scavenge_root_nmethod(nm);
+}
+
HeapWord* GenCollectedHeap::satisfy_failed_allocation(size_t size, bool is_tlab) {
return gen_policy()->satisfy_failed_allocation(size, is_tlab);
}
@@ -674,31 +630,6 @@
_process_strong_tasks->all_tasks_completed(scope->n_threads());
}
-void GenCollectedHeap::cms_process_roots(StrongRootsScope* scope,
- bool young_gen_as_roots,
- ScanningOption so,
- bool only_strong_roots,
- OopsInGenClosure* root_closure,
- CLDClosure* cld_closure) {
- MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations);
- OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure;
- CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
-
- process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure);
- if (!only_strong_roots) {
- process_string_table_roots(scope, root_closure);
- }
-
- if (young_gen_as_roots &&
- !_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
- root_closure->set_generation(_young_gen);
- _young_gen->oop_iterate(root_closure);
- root_closure->reset_generation();
- }
-
- _process_strong_tasks->all_tasks_completed(scope->n_threads());
-}
-
void GenCollectedHeap::full_process_roots(StrongRootsScope* scope,
bool is_adjust_phase,
ScanningOption so,
@@ -763,14 +694,7 @@
// public collection interfaces
void GenCollectedHeap::collect(GCCause::Cause cause) {
- if (should_do_concurrent_full_gc(cause)) {
-#if INCLUDE_ALL_GCS
- // Mostly concurrent full collection.
- collect_mostly_concurrent(cause);
-#else // INCLUDE_ALL_GCS
- ShouldNotReachHere();
-#endif // INCLUDE_ALL_GCS
- } else if (cause == GCCause::_wb_young_gc) {
+ if (cause == GCCause::_wb_young_gc) {
// Young collection for the WhiteBox API.
collect(cause, YoungGen);
} else {
@@ -817,44 +741,6 @@
}
}
-#if INCLUDE_ALL_GCS
-bool GenCollectedHeap::create_cms_collector() {
-
- assert(_old_gen->kind() == Generation::ConcurrentMarkSweep,
- "Unexpected generation kinds");
- // Skip two header words in the block content verification
- NOT_PRODUCT(_skip_header_HeapWords = CMSCollector::skip_header_HeapWords();)
- assert(_gen_policy->is_concurrent_mark_sweep_policy(), "Unexpected policy type");
- CMSCollector* collector =
- new CMSCollector((ConcurrentMarkSweepGeneration*)_old_gen,
- _rem_set,
- _gen_policy->as_concurrent_mark_sweep_policy());
-
- if (collector == NULL || !collector->completed_initialization()) {
- if (collector) {
- delete collector; // Be nice in embedded situation
- }
- vm_shutdown_during_initialization("Could not create CMS collector");
- return false;
- }
- return true; // success
-}
-
-void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) {
- assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock");
-
- MutexLocker ml(Heap_lock);
- // Read the GC counts while holding the Heap_lock
- unsigned int full_gc_count_before = total_full_collections();
- unsigned int gc_count_before = total_collections();
- {
- MutexUnlocker mu(Heap_lock);
- VM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause);
- VMThread::execute(&op);
- }
-}
-#endif // INCLUDE_ALL_GCS
-
void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
do_full_collection(clear_all_soft_refs, OldGen);
}
@@ -1097,8 +983,9 @@
GenCollectedHeap* GenCollectedHeap::heap() {
CollectedHeap* heap = Universe::heap();
assert(heap != NULL, "Uninitialized access to GenCollectedHeap::heap()");
- assert(heap->kind() == CollectedHeap::GenCollectedHeap, "Not a GenCollectedHeap");
- return (GenCollectedHeap*)heap;
+ assert(heap->kind() == CollectedHeap::GenCollectedHeap ||
+ heap->kind() == CollectedHeap::CMSHeap, "Not a GenCollectedHeap");
+ return (GenCollectedHeap*) heap;
}
void GenCollectedHeap::prepare_for_compaction() {
@@ -1126,34 +1013,9 @@
}
void GenCollectedHeap::gc_threads_do(ThreadClosure* tc) const {
- if (workers() != NULL) {
- workers()->threads_do(tc);
- }
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC) {
- ConcurrentMarkSweepThread::threads_do(tc);
- }
-#endif // INCLUDE_ALL_GCS
}
void GenCollectedHeap::print_gc_threads_on(outputStream* st) const {
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC) {
- workers()->print_worker_threads_on(st);
- ConcurrentMarkSweepThread::print_all_on(st);
- }
-#endif // INCLUDE_ALL_GCS
-}
-
-void GenCollectedHeap::print_on_error(outputStream* st) const {
- this->CollectedHeap::print_on_error(st);
-
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC) {
- st->cr();
- CMSCollector::print_on_error(st);
- }
-#endif // INCLUDE_ALL_GCS
}
void GenCollectedHeap::print_tracing_info() const {
@@ -1184,7 +1046,6 @@
void GenCollectedHeap::gc_prologue(bool full) {
assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
- always_do_update_barrier = false;
// Fill TLAB's and such
CollectedHeap::accumulate_statistics_all_tlabs();
ensure_parsability(true); // retire TLABs
@@ -1222,8 +1083,6 @@
MetaspaceCounters::update_performance_counters();
CompressedClassSpaceCounters::update_performance_counters();
-
- always_do_update_barrier = UseConcMarkSweepGC;
};
#ifndef PRODUCT
@@ -1304,11 +1163,3 @@
}
return retVal;
}
-
-void GenCollectedHeap::stop() {
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC) {
- ConcurrentMarkSweepThread::cmst()->stop();
- }
-#endif
-}
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -78,21 +78,34 @@
// In support of ExplicitGCInvokesConcurrent functionality
unsigned int _full_collections_completed;
- // Data structure for claiming the (potentially) parallel tasks in
- // (gen-specific) roots processing.
- SubTasksDone* _process_strong_tasks;
-
// Collects the given generation.
void collect_generation(Generation* gen, bool full, size_t size, bool is_tlab,
bool run_verification, bool clear_soft_refs,
bool restore_marks_for_biased_locking);
- // In block contents verification, the number of header words to skip
- NOT_PRODUCT(static size_t _skip_header_HeapWords;)
+protected:
- WorkGang* _workers;
+ // The set of potentially parallel tasks in root scanning.
+ enum GCH_strong_roots_tasks {
+ GCH_PS_Universe_oops_do,
+ GCH_PS_JNIHandles_oops_do,
+ GCH_PS_ObjectSynchronizer_oops_do,
+ GCH_PS_FlatProfiler_oops_do,
+ GCH_PS_Management_oops_do,
+ GCH_PS_SystemDictionary_oops_do,
+ GCH_PS_ClassLoaderDataGraph_oops_do,
+ GCH_PS_jvmti_oops_do,
+ GCH_PS_CodeCache_oops_do,
+ GCH_PS_aot_oops_do,
+ GCH_PS_younger_gens,
+ // Leave this one last.
+ GCH_PS_NumElements
+ };
-protected:
+ // Data structure for claiming the (potentially) parallel tasks in
+ // (gen-specific) roots processing.
+ SubTasksDone* _process_strong_tasks;
+
// Helper functions for allocation
HeapWord* attempt_allocation(size_t size,
bool is_tlab,
@@ -124,8 +137,6 @@
public:
GenCollectedHeap(GenCollectorPolicy *policy);
- WorkGang* workers() const { return _workers; }
-
// Returns JNI_OK on success
virtual jint initialize();
@@ -135,6 +146,8 @@
// Does operations required after initialization has been done.
void post_initialize();
+ virtual void check_gen_kinds();
+
// Initialize ("weak") refs processing support
virtual void ref_processing_init();
@@ -143,11 +156,7 @@
}
virtual const char* name() const {
- if (UseConcMarkSweepGC) {
- return "Concurrent Mark Sweep";
- } else {
- return "Serial";
- }
+ return "Serial";
}
Generation* young_gen() const { return _young_gen; }
@@ -190,7 +199,7 @@
// Perform a full collection of the heap; intended for use in implementing
// "System.gc". This implies as full a collection as the CollectedHeap
// supports. Caller does not hold the Heap_lock on entry.
- void collect(GCCause::Cause cause);
+ virtual void collect(GCCause::Cause cause);
// The same as above but assume that the caller holds the Heap_lock.
void collect_locked(GCCause::Cause cause);
@@ -207,12 +216,8 @@
bool is_in(const void* p) const;
// override
- bool is_in_closed_subset(const void* p) const {
- if (UseConcMarkSweepGC) {
- return is_in_reserved(p);
- } else {
- return is_in(p);
- }
+ virtual bool is_in_closed_subset(const void* p) const {
+ return is_in(p);
}
// Returns true if the reference is to an object in the reserved space
@@ -224,10 +229,14 @@
bool is_in_partial_collection(const void* p);
#endif
- virtual bool is_scavengable(const void* addr) {
- return is_in_young((oop)addr);
+ virtual bool is_scavengable(oop obj) {
+ return is_in_young(obj);
}
+ // Optimized nmethod scanning support routines
+ virtual void register_nmethod(nmethod* nm);
+ virtual void verify_nmethod(nmethod* nmethod);
+
// Iteration functions.
void oop_iterate_no_header(OopClosure* cl);
void oop_iterate(ExtendedOopClosure* cl);
@@ -278,7 +287,7 @@
}
virtual bool card_mark_must_follow_store() const {
- return UseConcMarkSweepGC;
+ return false;
}
// We don't need barriers for stores to objects in the
@@ -344,7 +353,6 @@
virtual void print_gc_threads_on(outputStream* st) const;
virtual void gc_threads_do(ThreadClosure* tc) const;
virtual void print_tracing_info() const;
- virtual void print_on_error(outputStream* st) const;
void print_heap_change(size_t young_prev_used, size_t old_prev_used) const;
@@ -383,7 +391,7 @@
SO_ScavengeCodeCache = 0x10
};
- private:
+ protected:
void process_roots(StrongRootsScope* scope,
ScanningOption so,
OopClosure* strong_roots,
@@ -395,24 +403,20 @@
void process_string_table_roots(StrongRootsScope* scope,
OopClosure* root_closure);
+ // Accessor for memory state verification support
+ NOT_PRODUCT(
+ virtual size_t skip_header_HeapWords() { return 0; }
+ )
+
+ virtual void gc_prologue(bool full);
+ virtual void gc_epilogue(bool full);
+
public:
void young_process_roots(StrongRootsScope* scope,
OopsInGenClosure* root_closure,
OopsInGenClosure* old_gen_closure,
CLDClosure* cld_closure);
- // If "young_gen_as_roots" is false, younger generations are
- // not scanned as roots; in this case, the caller must be arranging to
- // scan the younger generations itself. (For example, a generation might
- // explicitly mark reachable objects in younger generations, to avoid
- // excess storage retention.)
- void cms_process_roots(StrongRootsScope* scope,
- bool young_gen_as_roots,
- ScanningOption so,
- bool only_strong_roots,
- OopsInGenClosure* root_closure,
- CLDClosure* cld_closure);
-
void full_process_roots(StrongRootsScope* scope,
bool is_adjust_phase,
ScanningOption so,
@@ -479,12 +483,8 @@
oop obj,
size_t obj_size);
+
private:
- // Accessor for memory state verification support
- NOT_PRODUCT(
- static size_t skip_header_HeapWords() { return _skip_header_HeapWords; }
- )
-
// Override
void check_for_non_bad_heap_word_value(HeapWord* addr,
size_t size) PRODUCT_RETURN;
@@ -499,22 +499,8 @@
// collect() and collect_locked(). Caller holds the Heap_lock on entry.
void collect_locked(GCCause::Cause cause, GenerationType max_generation);
- // Returns success or failure.
- bool create_cms_collector();
-
- // In support of ExplicitGCInvokesConcurrent functionality
- bool should_do_concurrent_full_gc(GCCause::Cause cause);
- void collect_mostly_concurrent(GCCause::Cause cause);
-
// Save the tops of the spaces in all generations
void record_gen_tops_before_GC() PRODUCT_RETURN;
-
-protected:
- void gc_prologue(bool full);
- void gc_epilogue(bool full);
-
-public:
- void stop();
};
#endif // SHARE_VM_GC_SHARED_GENCOLLECTEDHEAP_HPP
--- a/src/hotspot/share/gc/shared/plab.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/plab.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,19 +43,19 @@
}
void PLABStats::add_allocated(size_t v) {
- Atomic::add_ptr(v, &_allocated);
+ Atomic::add(v, &_allocated);
}
void PLABStats::add_unused(size_t v) {
- Atomic::add_ptr(v, &_unused);
+ Atomic::add(v, &_unused);
}
void PLABStats::add_wasted(size_t v) {
- Atomic::add_ptr(v, &_wasted);
+ Atomic::add(v, &_wasted);
}
void PLABStats::add_undo_wasted(size_t v) {
- Atomic::add_ptr(v, &_undo_wasted);
+ Atomic::add(v, &_undo_wasted);
}
#endif // SHARE_VM_GC_SHARED_PLAB_INLINE_HPP
--- a/src/hotspot/share/gc/shared/space.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/space.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -631,7 +631,7 @@
HeapWord* obj = top();
if (pointer_delta(end(), obj) >= size) {
HeapWord* new_top = obj + size;
- HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj);
+ HeapWord* result = Atomic::cmpxchg(new_top, top_addr(), obj);
// result can be one of two:
// the old top value: the exchange succeeded
// otherwise: the new value of the top is returned.
--- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -259,9 +259,7 @@
template <unsigned int N, MEMFLAGS F>
inline typename TaskQueueSuper<N, F>::Age TaskQueueSuper<N, F>::Age::cmpxchg(const Age new_age, const Age old_age) volatile {
- return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
- (volatile intptr_t *)&_data,
- (intptr_t)old_age._data);
+ return Atomic::cmpxchg(new_age._data, &_data, old_age._data);
}
template<class E, MEMFLAGS F, unsigned int N>
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -705,7 +705,7 @@
if (hash != markOopDesc::no_hash) {
header = header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(header, rcvr->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics)
(*BiasedLocking::revoked_lock_entry_count_addr())++;
}
@@ -715,7 +715,7 @@
if (hash != markOopDesc::no_hash) {
new_header = new_header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(new_header, rcvr->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics) {
(* BiasedLocking::rebiased_lock_entry_count_addr())++;
}
@@ -734,7 +734,7 @@
markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
// Debugging hint.
DEBUG_ONLY(mon->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
- if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), header) == header) {
+ if (Atomic::cmpxchg(new_header, rcvr->mark_addr(), header) == header) {
if (PrintBiasedLockingStatistics) {
(* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
}
@@ -750,7 +750,7 @@
markOop displaced = rcvr->mark()->set_unlocked();
mon->lock()->set_displaced_header(displaced);
bool call_vm = UseHeavyMonitors;
- if (call_vm || Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) {
+ if (call_vm || Atomic::cmpxchg((markOop)mon, rcvr->mark_addr(), displaced) != displaced) {
// Is it simple recursive case?
if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
mon->lock()->set_displaced_header(NULL);
@@ -903,7 +903,7 @@
if (hash != markOopDesc::no_hash) {
header = header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(header, lockee->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics) {
(*BiasedLocking::revoked_lock_entry_count_addr())++;
}
@@ -914,7 +914,7 @@
if (hash != markOopDesc::no_hash) {
new_header = new_header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(new_header, lockee->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics) {
(* BiasedLocking::rebiased_lock_entry_count_addr())++;
}
@@ -932,7 +932,7 @@
markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
// debugging hint
DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
- if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) {
+ if (Atomic::cmpxchg(new_header, lockee->mark_addr(), header) == header) {
if (PrintBiasedLockingStatistics) {
(* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
}
@@ -948,7 +948,7 @@
markOop displaced = lockee->mark()->set_unlocked();
entry->lock()->set_displaced_header(displaced);
bool call_vm = UseHeavyMonitors;
- if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) {
+ if (call_vm || Atomic::cmpxchg((markOop)entry, lockee->mark_addr(), displaced) != displaced) {
// Is it simple recursive case?
if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
entry->lock()->set_displaced_header(NULL);
@@ -1844,7 +1844,7 @@
if (hash != markOopDesc::no_hash) {
header = header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(header, lockee->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics)
(*BiasedLocking::revoked_lock_entry_count_addr())++;
}
@@ -1855,7 +1855,7 @@
if (hash != markOopDesc::no_hash) {
new_header = new_header->copy_set_hash(hash);
}
- if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) {
+ if (Atomic::cmpxchg(new_header, lockee->mark_addr(), mark) == mark) {
if (PrintBiasedLockingStatistics)
(* BiasedLocking::rebiased_lock_entry_count_addr())++;
}
@@ -1875,7 +1875,7 @@
markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
// debugging hint
DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
- if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) {
+ if (Atomic::cmpxchg(new_header, lockee->mark_addr(), header) == header) {
if (PrintBiasedLockingStatistics)
(* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
}
@@ -1891,7 +1891,7 @@
markOop displaced = lockee->mark()->set_unlocked();
entry->lock()->set_displaced_header(displaced);
bool call_vm = UseHeavyMonitors;
- if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) {
+ if (call_vm || Atomic::cmpxchg((markOop)entry, lockee->mark_addr(), displaced) != displaced) {
// Is it simple recursive case?
if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
entry->lock()->set_displaced_header(NULL);
@@ -1923,7 +1923,8 @@
bool call_vm = UseHeavyMonitors;
// If it isn't recursive we either must swap old header or call the runtime
if (header != NULL || call_vm) {
- if (call_vm || Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) {
+ markOop old_header = markOopDesc::encode(lock);
+ if (call_vm || lockee->cas_set_mark(header, old_header) != old_header) {
// restore object for the slow case
most_recent->set_obj(lockee);
CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception);
@@ -2189,7 +2190,7 @@
HeapWord* compare_to = *Universe::heap()->top_addr();
HeapWord* new_top = compare_to + obj_size;
if (new_top <= *Universe::heap()->end_addr()) {
- if (Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) {
+ if (Atomic::cmpxchg(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) {
goto retry;
}
result = (oop) compare_to;
@@ -2975,7 +2976,8 @@
if (!lockee->mark()->has_bias_pattern()) {
// If it isn't recursive we either must swap old header or call the runtime
if (header != NULL) {
- if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) {
+ markOop old_header = markOopDesc::encode(lock);
+ if (lockee->cas_set_mark(header, old_header) != old_header) {
// restore object for the slow case
end->set_obj(lockee);
{
@@ -3050,7 +3052,8 @@
base->set_obj(NULL);
// If it isn't recursive we either must swap old header or call the runtime
if (header != NULL) {
- if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) {
+ markOop old_header = markOopDesc::encode(lock);
+ if (rcvr->cas_set_mark(header, old_header) != old_header) {
// restore object for the slow case
base->set_obj(rcvr);
{
--- a/src/hotspot/share/interpreter/oopMapCache.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/interpreter/oopMapCache.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -448,11 +448,11 @@
}
OopMapCacheEntry* OopMapCache::entry_at(int i) const {
- return (OopMapCacheEntry*)OrderAccess::load_ptr_acquire(&(_array[i % _size]));
+ return OrderAccess::load_acquire(&(_array[i % _size]));
}
bool OopMapCache::put_at(int i, OopMapCacheEntry* entry, OopMapCacheEntry* old) {
- return Atomic::cmpxchg_ptr (entry, &_array[i % _size], old) == old;
+ return Atomic::cmpxchg(entry, &_array[i % _size], old) == old;
}
void OopMapCache::flush() {
@@ -564,7 +564,7 @@
do {
head = _old_entries;
entry->_next = head;
- success = Atomic::cmpxchg_ptr (entry, &_old_entries, head) == head;
+ success = Atomic::cmpxchg(entry, &_old_entries, head) == head;
} while (!success);
if (log_is_enabled(Debug, interpreter, oopmap)) {
--- a/src/hotspot/share/memory/metaspace.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/memory/metaspace.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1499,7 +1499,7 @@
}
size_t MetaspaceGC::capacity_until_GC() {
- size_t value = (size_t)OrderAccess::load_ptr_acquire(&_capacity_until_GC);
+ size_t value = OrderAccess::load_acquire(&_capacity_until_GC);
assert(value >= MetaspaceSize, "Not initialized properly?");
return value;
}
@@ -1507,16 +1507,16 @@
bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) {
assert_is_aligned(v, Metaspace::commit_alignment());
- size_t capacity_until_GC = (size_t) _capacity_until_GC;
- size_t new_value = capacity_until_GC + v;
+ intptr_t capacity_until_GC = _capacity_until_GC;
+ intptr_t new_value = capacity_until_GC + v;
if (new_value < capacity_until_GC) {
// The addition wrapped around, set new_value to aligned max value.
new_value = align_down(max_uintx, Metaspace::commit_alignment());
}
- intptr_t expected = (intptr_t) capacity_until_GC;
- intptr_t actual = Atomic::cmpxchg_ptr((intptr_t) new_value, &_capacity_until_GC, expected);
+ intptr_t expected = _capacity_until_GC;
+ intptr_t actual = Atomic::cmpxchg(new_value, &_capacity_until_GC, expected);
if (expected != actual) {
return false;
@@ -1534,7 +1534,7 @@
size_t MetaspaceGC::dec_capacity_until_GC(size_t v) {
assert_is_aligned(v, Metaspace::commit_alignment());
- return (size_t)Atomic::add_ptr(-(intptr_t)v, &_capacity_until_GC);
+ return (size_t)Atomic::sub((intptr_t)v, &_capacity_until_GC);
}
void MetaspaceGC::initialize() {
@@ -2398,7 +2398,7 @@
void SpaceManager::inc_used_metrics(size_t words) {
// Add to the per SpaceManager total
- Atomic::add_ptr(words, &_allocated_blocks_words);
+ Atomic::add(words, &_allocated_blocks_words);
// Add to the global total
MetaspaceAux::inc_used(mdtype(), words);
}
@@ -2753,8 +2753,7 @@
// sweep which is a concurrent phase. Protection by the expand_lock()
// is not enough since allocation is on a per Metaspace basis
// and protected by the Metaspace lock.
- jlong minus_words = (jlong) - (jlong) words;
- Atomic::add_ptr(minus_words, &_used_words[mdtype]);
+ Atomic::sub(words, &_used_words[mdtype]);
}
void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
@@ -2762,7 +2761,7 @@
// each piece of metadata. Those allocations are
// generally done concurrently by different application
// threads so must be done atomically.
- Atomic::add_ptr(words, &_used_words[mdtype]);
+ Atomic::add(words, &_used_words[mdtype]);
}
size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) {
--- a/src/hotspot/share/memory/universe.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/memory/universe.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -84,6 +84,7 @@
#include "utilities/preserveException.hpp"
#if INCLUDE_ALL_GCS
#include "gc/cms/cmsCollectorPolicy.hpp"
+#include "gc/cms/cmsHeap.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/parallel/parallelScavengeHeap.hpp"
@@ -536,7 +537,7 @@
oop Universe::swap_reference_pending_list(oop list) {
assert_pll_locked(is_locked);
- return (oop)Atomic::xchg_ptr(list, &_reference_pending_list);
+ return Atomic::xchg(list, &_reference_pending_list);
}
#undef assert_pll_locked
@@ -758,7 +759,7 @@
} else if (UseG1GC) {
return Universe::create_heap_with_policy<G1CollectedHeap, G1CollectorPolicy>();
} else if (UseConcMarkSweepGC) {
- return Universe::create_heap_with_policy<GenCollectedHeap, ConcurrentMarkSweepPolicy>();
+ return Universe::create_heap_with_policy<CMSHeap, ConcurrentMarkSweepPolicy>();
#endif
} else if (UseSerialGC) {
return Universe::create_heap_with_policy<GenCollectedHeap, MarkSweepPolicy>();
--- a/src/hotspot/share/metaprogramming/integralConstant.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/metaprogramming/integralConstant.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -44,7 +44,7 @@
// T is an integral type, and is the value_type.
// v is an integral constant, and is the value.
template<typename T, T v>
-struct IntegralConstant : AllStatic {
+struct IntegralConstant VALUE_OBJ_CLASS_SPEC {
typedef T value_type;
static const value_type value = v;
typedef IntegralConstant<T, v> type;
--- a/src/hotspot/share/oops/arrayKlass.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/arrayKlass.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,11 +29,11 @@
#include "oops/arrayKlass.hpp"
inline Klass* ArrayKlass::higher_dimension_acquire() const {
- return (Klass*) OrderAccess::load_ptr_acquire(&_higher_dimension);
+ return OrderAccess::load_acquire(&_higher_dimension);
}
inline void ArrayKlass::release_set_higher_dimension(Klass* k) {
- OrderAccess::release_store_ptr(&_higher_dimension, k);
+ OrderAccess::release_store(&_higher_dimension, k);
}
#endif // SHARE_VM_OOPS_ARRAYKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/constantPool.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/constantPool.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -226,7 +226,7 @@
symbol_at_put(name_index, name);
name->increment_refcount();
Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
- OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+ OrderAccess::release_store(adr, k);
// The interpreter assumes when the tag is stored, the klass is resolved
// and the Klass* non-NULL, so we need hardware store ordering here.
@@ -243,7 +243,7 @@
CPKlassSlot kslot = klass_slot_at(class_index);
int resolved_klass_index = kslot.resolved_klass_index();
Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
- OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+ OrderAccess::release_store(adr, k);
// The interpreter assumes when the tag is stored, the klass is resolved
// and the Klass* non-NULL, so we need hardware store ordering here.
@@ -511,7 +511,7 @@
trace_class_resolution(this_cp, k);
}
Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index);
- OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+ OrderAccess::release_store(adr, k);
// The interpreter assumes when the tag is stored, the klass is resolved
// and the Klass* stored in _resolved_klasses is non-NULL, so we need
// hardware store ordering here.
--- a/src/hotspot/share/oops/constantPool.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/constantPool.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -145,7 +145,7 @@
assert(is_within_bounds(which), "index out of bounds");
assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool");
// Uses volatile because the klass slot changes without a lock.
- volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
+ intptr_t adr = OrderAccess::load_acquire(obj_at_addr_raw(which));
assert(adr != 0 || which == 0, "cp entry for klass should not be zero");
return CPSlot(adr);
}
@@ -407,7 +407,7 @@
assert(tag_at(kslot.name_index()).is_symbol(), "sanity");
Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index());
- return (Klass*)OrderAccess::load_ptr_acquire(adr);
+ return OrderAccess::load_acquire(adr);
}
// RedefineClasses() API support:
--- a/src/hotspot/share/oops/cpCache.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/cpCache.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -91,7 +91,7 @@
assert(c == 0 || c == code || code == 0, "update must be consistent");
#endif
// Need to flush pending stores here before bytecode is written.
- OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << bytecode_1_shift));
+ OrderAccess::release_store(&_indices, _indices | ((u_char)code << bytecode_1_shift));
}
void ConstantPoolCacheEntry::set_bytecode_2(Bytecodes::Code code) {
@@ -101,19 +101,13 @@
assert(c == 0 || c == code || code == 0, "update must be consistent");
#endif
// Need to flush pending stores here before bytecode is written.
- OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << bytecode_2_shift));
+ OrderAccess::release_store(&_indices, _indices | ((u_char)code << bytecode_2_shift));
}
// Sets f1, ordering with previous writes.
void ConstantPoolCacheEntry::release_set_f1(Metadata* f1) {
assert(f1 != NULL, "");
- OrderAccess::release_store_ptr((HeapWord*) &_f1, f1);
-}
-
-// Sets flags, but only if the value was previously zero.
-bool ConstantPoolCacheEntry::init_flags_atomic(intptr_t flags) {
- intptr_t result = Atomic::cmpxchg_ptr(flags, &_flags, 0);
- return (result == 0);
+ OrderAccess::release_store(&_f1, f1);
}
// Note that concurrent update of both bytecodes can leave one of them
@@ -154,7 +148,8 @@
// bother trying to update it once it's nonzero but always make
// sure that the final parameter size agrees with what was passed.
if (_flags == 0) {
- Atomic::cmpxchg_ptr((value & parameter_size_mask), &_flags, 0);
+ intx newflags = (value & parameter_size_mask);
+ Atomic::cmpxchg(newflags, &_flags, (intx)0);
}
guarantee(parameter_size() == value,
"size must not change: parameter_size=%d, value=%d", parameter_size(), value);
--- a/src/hotspot/share/oops/cpCache.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/cpCache.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -136,7 +136,7 @@
private:
volatile intx _indices; // constant pool index & rewrite bytecodes
- volatile Metadata* _f1; // entry specific metadata field
+ Metadata* volatile _f1; // entry specific metadata field
volatile intx _f2; // entry specific int/metadata field
volatile intx _flags; // flags
@@ -144,7 +144,7 @@
void set_bytecode_1(Bytecodes::Code code);
void set_bytecode_2(Bytecodes::Code code);
void set_f1(Metadata* f1) {
- Metadata* existing_f1 = (Metadata*)_f1; // read once
+ Metadata* existing_f1 = _f1; // read once
assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change");
_f1 = f1;
}
@@ -160,7 +160,6 @@
}
int make_flags(TosState state, int option_bits, int field_index_or_method_params);
void set_flags(intx flags) { _flags = flags; }
- bool init_flags_atomic(intx flags);
void set_field_flags(TosState field_type, int option_bits, int field_index) {
assert((field_index & field_index_mask) == field_index, "field_index in range");
set_flags(make_flags(field_type, option_bits | (1 << is_field_entry_shift), field_index));
@@ -169,10 +168,6 @@
assert((method_params & parameter_size_mask) == method_params, "method_params in range");
set_flags(make_flags(return_type, option_bits, method_params));
}
- bool init_method_flags_atomic(TosState return_type, int option_bits, int method_params) {
- assert((method_params & parameter_size_mask) == method_params, "method_params in range");
- return init_flags_atomic(make_flags(return_type, option_bits, method_params));
- }
public:
// specific bit definitions for the flags field:
@@ -332,11 +327,11 @@
// Accessors
int indices() const { return _indices; }
- int indices_ord() const { return (intx)OrderAccess::load_ptr_acquire(&_indices); }
+ int indices_ord() const { return OrderAccess::load_acquire(&_indices); }
int constant_pool_index() const { return (indices() & cp_index_mask); }
Bytecodes::Code bytecode_1() const { return Bytecodes::cast((indices_ord() >> bytecode_1_shift) & bytecode_1_mask); }
Bytecodes::Code bytecode_2() const { return Bytecodes::cast((indices_ord() >> bytecode_2_shift) & bytecode_2_mask); }
- Metadata* f1_ord() const { return (Metadata *)OrderAccess::load_ptr_acquire(&_f1); }
+ Metadata* f1_ord() const { return (Metadata *)OrderAccess::load_acquire(&_f1); }
Method* f1_as_method() const { Metadata* f1 = f1_ord(); assert(f1 == NULL || f1->is_method(), ""); return (Method*)f1; }
Klass* f1_as_klass() const { Metadata* f1 = f1_ord(); assert(f1 == NULL || f1->is_klass(), ""); return (Klass*)f1; }
// Use the accessor f1() to acquire _f1's value. This is needed for
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1109,16 +1109,15 @@
void InstanceKlass::mask_for(const methodHandle& method, int bci,
InterpreterOopMap* entry_for) {
// Lazily create the _oop_map_cache at first request
- // Lock-free access requires load_ptr_acquire.
- OopMapCache* oop_map_cache =
- static_cast<OopMapCache*>(OrderAccess::load_ptr_acquire(&_oop_map_cache));
+ // Lock-free access requires load_acquire.
+ OopMapCache* oop_map_cache = OrderAccess::load_acquire(&_oop_map_cache);
if (oop_map_cache == NULL) {
MutexLocker x(OopMapCacheAlloc_lock);
// Check if _oop_map_cache was allocated while we were waiting for this lock
if ((oop_map_cache = _oop_map_cache) == NULL) {
oop_map_cache = new OopMapCache();
// Ensure _oop_map_cache is stable, since it is examined without a lock
- OrderAccess::release_store_ptr(&_oop_map_cache, oop_map_cache);
+ OrderAccess::release_store(&_oop_map_cache, oop_map_cache);
}
}
// _oop_map_cache is constant after init; lookup below does its own locking.
@@ -1672,7 +1671,7 @@
// transitions from NULL to non-NULL which is safe because we use
// release_set_methods_jmethod_ids() to advertise the new cache.
// A partially constructed cache should never be seen by a racing
- // thread. We also use release_store_ptr() to save a new jmethodID
+ // thread. We also use release_store() to save a new jmethodID
// in the cache so a partially constructed jmethodID should never be
// seen either. Cache reads of existing jmethodIDs proceed without a
// lock, but cache writes of a new jmethodID requires uniqueness and
@@ -1831,7 +1830,7 @@
// The jmethodID cache can be read while unlocked so we have to
// make sure the new jmethodID is complete before installing it
// in the cache.
- OrderAccess::release_store_ptr(&jmeths[idnum+1], id);
+ OrderAccess::release_store(&jmeths[idnum+1], id);
} else {
*to_dealloc_id_p = new_id; // save new id for later delete
}
--- a/src/hotspot/share/oops/instanceKlass.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/instanceKlass.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,19 +35,19 @@
#include "utilities/macros.hpp"
inline Klass* InstanceKlass::array_klasses_acquire() const {
- return (Klass*) OrderAccess::load_ptr_acquire(&_array_klasses);
+ return OrderAccess::load_acquire(&_array_klasses);
}
inline void InstanceKlass::release_set_array_klasses(Klass* k) {
- OrderAccess::release_store_ptr(&_array_klasses, k);
+ OrderAccess::release_store(&_array_klasses, k);
}
inline jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const {
- return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids);
+ return OrderAccess::load_acquire(&_methods_jmethod_ids);
}
inline void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) {
- OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths);
+ OrderAccess::release_store(&_methods_jmethod_ids, jmeths);
}
// The iteration over the oops in objects is a hot path in the GC code.
--- a/src/hotspot/share/oops/method.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/method.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -444,6 +444,11 @@
return mh->method_counters();
}
+bool Method::init_method_counters(MethodCounters* counters) {
+ // Try to install a pointer to MethodCounters, return true on success.
+ return Atomic::cmpxchg(counters, &_method_counters, (MethodCounters*)NULL) == NULL;
+}
+
void Method::cleanup_inline_caches() {
// The current system doesn't use inline caches in the interpreter
// => nothing to do (keep this method around for future use)
@@ -1108,8 +1113,8 @@
}
}
-volatile address Method::from_compiled_entry_no_trampoline() const {
- nmethod *code = (nmethod *)OrderAccess::load_ptr_acquire(&_code);
+address Method::from_compiled_entry_no_trampoline() const {
+ CompiledMethod *code = OrderAccess::load_acquire(&_code);
if (code) {
return code->verified_entry_point();
} else {
@@ -1135,7 +1140,7 @@
// Not inline to avoid circular ref.
bool Method::check_code() const {
// cached in a register or local. There's a race on the value of the field.
- CompiledMethod *code = (CompiledMethod *)OrderAccess::load_ptr_acquire(&_code);
+ CompiledMethod *code = OrderAccess::load_acquire(&_code);
return code == NULL || (code->method() == NULL) || (code->method() == (Method*)this && !code->is_osr_method());
}
--- a/src/hotspot/share/oops/method.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/method.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -136,9 +136,9 @@
static address make_adapters(const methodHandle& mh, TRAPS);
- volatile address from_compiled_entry() const { return (address)OrderAccess::load_ptr_acquire(&_from_compiled_entry); }
- volatile address from_compiled_entry_no_trampoline() const;
- volatile address from_interpreted_entry() const{ return (address)OrderAccess::load_ptr_acquire(&_from_interpreted_entry); }
+ address from_compiled_entry() const { return OrderAccess::load_acquire(&_from_compiled_entry); }
+ address from_compiled_entry_no_trampoline() const;
+ address from_interpreted_entry() const{ return OrderAccess::load_acquire(&_from_interpreted_entry); }
// access flag
AccessFlags access_flags() const { return _access_flags; }
@@ -337,7 +337,7 @@
// The store into method must be released. On platforms without
// total store order (TSO) the reference may become visible before
// the initialization of data otherwise.
- OrderAccess::release_store_ptr((volatile void *)&_method_data, data);
+ OrderAccess::release_store(&_method_data, data);
}
MethodCounters* method_counters() const {
@@ -348,10 +348,7 @@
_method_counters = NULL;
}
- bool init_method_counters(MethodCounters* counters) {
- // Try to install a pointer to MethodCounters, return true on success.
- return Atomic::cmpxchg_ptr(counters, (volatile void*)&_method_counters, NULL) == NULL;
- }
+ bool init_method_counters(MethodCounters* counters);
#ifdef TIERED
// We are reusing interpreter_invocation_count as a holder for the previous event count!
@@ -452,7 +449,7 @@
// nmethod/verified compiler entry
address verified_code_entry();
bool check_code() const; // Not inline to avoid circular ref
- CompiledMethod* volatile code() const { assert( check_code(), "" ); return (CompiledMethod *)OrderAccess::load_ptr_acquire(&_code); }
+ CompiledMethod* volatile code() const { assert( check_code(), "" ); return OrderAccess::load_acquire(&_code); }
void clear_code(bool acquire_lock = true); // Clear out any compiled code
static void set_code(const methodHandle& mh, CompiledMethod* code);
void set_adapter_entry(AdapterHandlerEntry* adapter) {
--- a/src/hotspot/share/oops/methodData.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/methodData.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -202,7 +202,7 @@
_cells[index] = value;
}
void release_set_cell_at(int index, intptr_t value) {
- OrderAccess::release_store_ptr(&_cells[index], value);
+ OrderAccess::release_store(&_cells[index], value);
}
intptr_t cell_at(int index) const {
return _cells[index];
--- a/src/hotspot/share/oops/oop.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/oops/oop.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -66,7 +66,7 @@
template <class T> void oop_store(volatile T* p, oop v) {
update_barrier_set_pre((T*)p, v); // cast away volatile
- // Used by release_obj_field_put, so use release_store_ptr.
+ // Used by release_obj_field_put, so use release_store.
oopDesc::release_encode_store_heap_oop(p, v);
// When using CMS we must mark the card corresponding to p as dirty
// with release sematics to prevent that CMS sees the dirty card but
@@ -90,7 +90,7 @@
// We need a separate file to avoid circular references
void oopDesc::release_set_mark(markOop m) {
- OrderAccess::release_store_ptr(&_mark, m);
+ OrderAccess::release_store(&_mark, m);
}
markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) {
@@ -124,7 +124,7 @@
volatile narrowKlass* xaddr = const_cast<volatile narrowKlass*>(addr);
return Klass::decode_klass(OrderAccess::load_acquire(xaddr));
} else {
- return (Klass*)OrderAccess::load_ptr_acquire(&_metadata._klass);
+ return OrderAccess::load_acquire(&_metadata._klass);
}
}
@@ -161,7 +161,7 @@
OrderAccess::release_store(compressed_klass_addr(),
Klass::encode_klass_not_null(k));
} else {
- OrderAccess::release_store_ptr(klass_addr(), k);
+ OrderAccess::release_store(klass_addr(), k);
}
}
@@ -361,7 +361,7 @@
// Store heap oop as is for volatile fields.
void oopDesc::release_store_heap_oop(volatile oop* p, oop v) {
- OrderAccess::release_store_ptr(p, v);
+ OrderAccess::release_store(p, v);
}
void oopDesc::release_store_heap_oop(volatile narrowOop* p, narrowOop v) {
OrderAccess::release_store(p, v);
@@ -372,11 +372,11 @@
OrderAccess::release_store(p, encode_heap_oop_not_null(v));
}
void oopDesc::release_encode_store_heap_oop_not_null(volatile oop* p, oop v) {
- OrderAccess::release_store_ptr(p, v);
+ OrderAccess::release_store(p, v);
}
void oopDesc::release_encode_store_heap_oop(volatile oop* p, oop v) {
- OrderAccess::release_store_ptr(p, v);
+ OrderAccess::release_store(p, v);
}
void oopDesc::release_encode_store_heap_oop(volatile narrowOop* p, oop v) {
OrderAccess::release_store(p, encode_heap_oop(v));
@@ -388,11 +388,11 @@
if (UseCompressedOops) {
// encode exchange value from oop to T
narrowOop val = encode_heap_oop(exchange_value);
- narrowOop old = (narrowOop)Atomic::xchg(val, (narrowOop*)dest);
+ narrowOop old = Atomic::xchg(val, (narrowOop*)dest);
// decode old from T to oop
return decode_heap_oop(old);
} else {
- return (oop)Atomic::xchg_ptr(exchange_value, (oop*)dest);
+ return Atomic::xchg(exchange_value, (oop*)dest);
}
}
@@ -447,11 +447,11 @@
void oopDesc::metadata_field_put(int offset, Metadata* value) { *metadata_field_addr(offset) = value; }
Metadata* oopDesc::metadata_field_acquire(int offset) const {
- return (Metadata*)OrderAccess::load_ptr_acquire(metadata_field_addr(offset));
+ return OrderAccess::load_acquire(metadata_field_addr(offset));
}
void oopDesc::release_metadata_field_put(int offset, Metadata* value) {
- OrderAccess::release_store_ptr(metadata_field_addr(offset), value);
+ OrderAccess::release_store(metadata_field_addr(offset), value);
}
jbyte oopDesc::byte_field(int offset) const { return (jbyte) *byte_field_addr(offset); }
@@ -485,8 +485,8 @@
return UseCompressedOops ?
decode_heap_oop((narrowOop)
OrderAccess::load_acquire(obj_field_addr<narrowOop>(offset)))
- : decode_heap_oop((oop)
- OrderAccess::load_ptr_acquire(obj_field_addr<oop>(offset)));
+ : decode_heap_oop(
+ OrderAccess::load_acquire(obj_field_addr<oop>(offset)));
}
void oopDesc::release_obj_field_put(int offset, oop value) {
UseCompressedOops ?
@@ -518,8 +518,8 @@
jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); }
void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); }
-address oopDesc::address_field_acquire(int offset) const { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); }
-void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store_ptr(address_field_addr(offset), contents); }
+address oopDesc::address_field_acquire(int offset) const { return OrderAccess::load_acquire(address_field_addr(offset)); }
+void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store(address_field_addr(offset), contents); }
bool oopDesc::is_locked() const {
return mark()->is_locked();
@@ -539,7 +539,7 @@
}
bool oopDesc::is_scavengable() const {
- return Universe::heap()->is_scavengable(this);
+ return Universe::heap()->is_scavengable(oop(const_cast<oopDesc*>(this)));
}
// Used by scavengers
--- a/src/hotspot/share/opto/c2_globals.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/opto/c2_globals.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -192,7 +192,7 @@
"of rounds of unroll,optimize,..") \
range(0, max_jint) \
\
- product(bool, UseSubwordForMaxVector, false, \
+ product(bool, UseSubwordForMaxVector, true, \
"Use Subword Analysis to set maximum vector size") \
\
develop(intx, UnrollLimitForProfileCheck, 1, \
--- a/src/hotspot/share/opto/loopopts.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/opto/loopopts.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -826,45 +826,26 @@
}
}
if (mem_ok) {
- // Move the Store out of the loop creating clones along
- // all paths out of the loop that observe the stored value
+ // Move the store out of the loop if the LCA of all
+ // users (except for the phi) is outside the loop.
+ Node* hook = new Node(1);
_igvn.rehash_node_delayed(phi);
- int count = phi->replace_edge(n, n->in(MemNode::Memory));
+ int count = phi->replace_edge(n, hook);
assert(count > 0, "inconsistent phi");
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node* u = n->fast_out(i);
- Node* c = get_ctrl(u);
- if (u->is_Phi()) {
- c = u->in(0)->in(u->find_edge(n));
- }
- IdealLoopTree *u_loop = get_loop(c);
- assert (!n_loop->is_member(u_loop), "only the phi should have been a use in the loop");
- while(true) {
- Node* next_c = find_non_split_ctrl(idom(c));
- if (n_loop->is_member(get_loop(next_c))) {
- break;
- }
- c = next_c;
- }
-
- Node* st = n->clone();
- st->set_req(0, c);
- _igvn.register_new_node_with_optimizer(st);
-
- set_ctrl(st, c);
- IdealLoopTree* new_loop = get_loop(c);
- assert(new_loop != n_loop, "should be moved out of loop");
- if (new_loop->_child == NULL) new_loop->_body.push(st);
-
- _igvn.replace_input_of(u, u->find_edge(n), st);
- --imax;
- --i;
+ // Compute latest point this store can go
+ Node* lca = get_late_ctrl(n, get_ctrl(n));
+ if (n_loop->is_member(get_loop(lca))) {
+ // LCA is in the loop - bail out
+ _igvn.replace_node(hook, n);
+ return;
}
+ // Move store out of the loop
+ _igvn.replace_node(hook, n->in(MemNode::Memory));
+ _igvn.replace_input_of(n, 0, lca);
+ set_ctrl_and_loop(n, lca);
- assert(n->outcnt() == 0, "all uses should be gone");
- _igvn.replace_input_of(n, MemNode::Memory, C->top());
// Disconnect the phi now. An empty phi can confuse other
// optimizations in this pass of loop opts..
if (phi->in(LoopNode::LoopBackControl) == phi) {
--- a/src/hotspot/share/opto/runtime.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/opto/runtime.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1658,7 +1658,7 @@
c->set_next(NULL);
head = _named_counters;
c->set_next(head);
- } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head);
+ } while (Atomic::cmpxchg(c, &_named_counters, head) != head);
return c;
}
--- a/src/hotspot/share/precompiled/precompiled.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/precompiled/precompiled.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -71,7 +71,6 @@
# include "code/debugInfoRec.hpp"
# include "code/dependencies.hpp"
# include "code/exceptionHandlerTable.hpp"
-# include "code/jvmticmlr.h"
# include "code/location.hpp"
# include "code/nativeInst.hpp"
# include "code/nmethod.hpp"
--- a/src/hotspot/share/prims/jni.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/prims/jni.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -3777,7 +3777,7 @@
intptr_t *a = (intptr_t *) jni_functions();
intptr_t *b = (intptr_t *) new_jni_NativeInterface;
for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
- Atomic::store_ptr(*b++, a++);
+ Atomic::store(*b++, a++);
}
}
@@ -3898,11 +3898,11 @@
#if defined(ZERO) && defined(ASSERT)
{
jint a = 0xcafebabe;
- jint b = Atomic::xchg(0xdeadbeef, &a);
+ jint b = Atomic::xchg((jint) 0xdeadbeef, &a);
void *c = &a;
- void *d = Atomic::xchg_ptr(&b, &c);
+ void *d = Atomic::xchg(&b, &c);
assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");
- assert(c == &b && d == &a, "Atomic::xchg_ptr() works");
+ assert(c == &b && d == &a, "Atomic::xchg() works");
}
#endif // ZERO && ASSERT
--- a/src/hotspot/share/prims/jvmtiExport.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/prims/jvmtiExport.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -37,7 +37,7 @@
#include "utilities/macros.hpp"
// Must be included after jvmti.h.
-#include "code/jvmticmlr.h"
+#include "jvmticmlr.h"
// Forward declarations
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -127,7 +127,7 @@
int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
for (;;) {
- if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+ if (Atomic::cmpxchg(Self, &_owner, (void*)NULL) == NULL) {
return OS_OK ;
}
@@ -139,7 +139,7 @@
Node._next = _EntryList ;
_EntryList = &Node ;
OrderAccess::fence() ;
- if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+ if (_owner == NULL && Atomic::cmpxchg(Self, &_owner, (void*)NULL) == NULL) {
_EntryList = Node._next ;
RawMonitor_lock->unlock() ;
return OS_OK ;
@@ -153,7 +153,7 @@
int JvmtiRawMonitor::SimpleExit (Thread * Self) {
guarantee (_owner == Self, "invariant") ;
- OrderAccess::release_store_ptr (&_owner, NULL) ;
+ OrderAccess::release_store(&_owner, (void*)NULL) ;
OrderAccess::fence() ;
if (_EntryList == NULL) return OS_OK ;
ObjectWaiter * w ;
@@ -277,10 +277,10 @@
jt->SR_lock()->lock_without_safepoint_check();
}
// guarded by SR_lock to avoid racing with new external suspend requests.
- Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
+ Contended = Atomic::cmpxchg(THREAD, &_owner, (void*)NULL);
jt->SR_lock()->unlock();
} else {
- Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
+ Contended = Atomic::cmpxchg(THREAD, &_owner, (void*)NULL);
}
if (Contended == THREAD) {
--- a/src/hotspot/share/runtime/atomic.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/atomic.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -70,14 +70,6 @@
template<typename T, typename D>
inline static void store(T store_value, volatile D* dest);
- inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest) {
- Atomic::store(store_value, dest);
- }
-
- inline static void store_ptr(void* store_value, volatile void* dest) {
- Atomic::store(store_value, reinterpret_cast<void* volatile*>(dest));
- }
-
// Atomically load from a location
// The type T must be either a pointer type, an integral/enum type,
// or a type that is primitive convertible using PrimitiveConversions.
@@ -90,13 +82,8 @@
template<typename I, typename D>
inline static D add(I add_value, D volatile* dest);
- inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest) {
- return add(add_value, dest);
- }
-
- inline static void* add_ptr(intptr_t add_value, volatile void* dest) {
- return add(add_value, reinterpret_cast<char* volatile*>(dest));
- }
+ template<typename I, typename D>
+ inline static D sub(I sub_value, D volatile* dest);
// Atomically increment location. inc() provide:
// <fence> increment-dest <membar StoreLoad|StoreStore>
@@ -123,14 +110,6 @@
template<typename T, typename D>
inline static D xchg(T exchange_value, volatile D* dest);
- inline static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
- return xchg(exchange_value, dest);
- }
-
- inline static void* xchg_ptr(void* exchange_value, volatile void* dest) {
- return xchg(exchange_value, reinterpret_cast<void* volatile*>(dest));
- }
-
// Performs atomic compare of *dest and compare_value, and exchanges
// *dest with exchange_value if the comparison succeeded. Returns prior
// value of *dest. cmpxchg*() provide:
@@ -151,23 +130,6 @@
inline static bool replace_if_null(T* value, D* volatile* dest,
cmpxchg_memory_order order = memory_order_conservative);
- inline static intptr_t cmpxchg_ptr(intptr_t exchange_value,
- volatile intptr_t* dest,
- intptr_t compare_value,
- cmpxchg_memory_order order = memory_order_conservative) {
- return cmpxchg(exchange_value, dest, compare_value, order);
- }
-
- inline static void* cmpxchg_ptr(void* exchange_value,
- volatile void* dest,
- void* compare_value,
- cmpxchg_memory_order order = memory_order_conservative) {
- return cmpxchg(exchange_value,
- reinterpret_cast<void* volatile*>(dest),
- compare_value,
- order);
- }
-
private:
// Test whether From is implicitly convertible to To.
// From and To must be pointer types.
@@ -555,6 +517,23 @@
Atomic::add(I(-1), dest);
}
+template<typename I, typename D>
+inline D Atomic::sub(I sub_value, D volatile* dest) {
+ STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
+ STATIC_ASSERT(IsIntegral<I>::value);
+ // If D is a pointer type, use [u]intptr_t as the addend type,
+ // matching signedness of I. Otherwise, use D as the addend type.
+ typedef typename Conditional<IsSigned<I>::value, intptr_t, uintptr_t>::type PI;
+ typedef typename Conditional<IsPointer<D>::value, PI, D>::type AddendType;
+ // Only allow conversions that can't change the value.
+ STATIC_ASSERT(IsSigned<I>::value == IsSigned<AddendType>::value);
+ STATIC_ASSERT(sizeof(I) <= sizeof(AddendType));
+ AddendType addend = sub_value;
+ // Assumes two's complement integer representation.
+ #pragma warning(suppress: 4146) // In case AddendType is not signed.
+ return Atomic::add(-addend, dest);
+}
+
// Define the class before including platform file, which may specialize
// the operator definition. No generic definition of specializations
// of the operator template are provided, nor are there any generic
--- a/src/hotspot/share/runtime/biasedLocking.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/biasedLocking.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -35,6 +35,7 @@
#include "runtime/vframe.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
+#include "trace/tracing.hpp"
static bool _biased_locking_enabled = false;
BiasedLockingCounters BiasedLocking::_counters;
@@ -643,23 +644,43 @@
// stale epoch.
ResourceMark rm;
log_info(biasedlocking)("Revoking bias by walking my own stack:");
+ EventBiasedLockSelfRevocation event;
BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
assert(cond == BIAS_REVOKED, "why not?");
+ if (event.should_commit()) {
+ event.set_lockClass(k);
+ event.commit();
+ }
return cond;
} else {
+ EventBiasedLockRevocation event;
VM_RevokeBias revoke(&obj, (JavaThread*) THREAD);
VMThread::execute(&revoke);
+ if (event.should_commit() && (revoke.status_code() != NOT_BIASED)) {
+ event.set_lockClass(k);
+ // Subtract 1 to match the id of events committed inside the safepoint
+ event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
+ event.commit();
+ }
return revoke.status_code();
}
}
assert((heuristics == HR_BULK_REVOKE) ||
(heuristics == HR_BULK_REBIAS), "?");
+ EventBiasedLockClassRevocation event;
VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD,
(heuristics == HR_BULK_REBIAS),
attempt_rebias);
VMThread::execute(&bulk_revoke);
+ if (event.should_commit()) {
+ event.set_revokedClass(obj->klass());
+ event.set_disableBiasing((heuristics != HR_BULK_REBIAS));
+ // Subtract 1 to match the id of events committed inside the safepoint
+ event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
+ event.commit();
+ }
return bulk_revoke.status_code();
}
--- a/src/hotspot/share/runtime/mutex.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/mutex.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -251,12 +251,6 @@
//
// o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
-
-// CASPTR() uses the canonical argument order that dominates in the literature.
-// Our internal cmpxchg_ptr() uses a bastardized ordering to accommodate Sun .il templates.
-
-#define CASPTR(a, c, s) \
- intptr_t(Atomic::cmpxchg_ptr((void *)(s), (void *)(a), (void *)(c)))
#define UNS(x) (uintptr_t(x))
#define TRACE(m) \
{ \
@@ -268,6 +262,15 @@
} \
}
+const intptr_t _LBIT = 1;
+
+// Endian-ness ... index of least-significant byte in SplitWord.Bytes[]
+#ifdef VM_LITTLE_ENDIAN
+ #define _LSBINDEX 0
+#else
+ #define _LSBINDEX (sizeof(intptr_t)-1)
+#endif
+
// Simplistic low-quality Marsaglia SHIFT-XOR RNG.
// Bijective except for the trailing mask operation.
// Useful for spin loops as the compiler can't optimize it away.
@@ -297,7 +300,7 @@
intptr_t v = _LockWord.FullWord;
for (;;) {
if ((v & _LBIT) != 0) return 0;
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (v == u) return 1;
v = u;
}
@@ -307,12 +310,12 @@
// Optimistic fast-path form ...
// Fast-path attempt for the common uncontended case.
// Avoid RTS->RTO $ coherence upgrade on typical SMP systems.
- intptr_t v = CASPTR(&_LockWord, 0, _LBIT); // agro ...
+ intptr_t v = Atomic::cmpxchg(_LBIT, &_LockWord.FullWord, (intptr_t)0); // agro ...
if (v == 0) return 1;
for (;;) {
if ((v & _LBIT) != 0) return 0;
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (v == u) return 1;
v = u;
}
@@ -350,7 +353,7 @@
for (;;) {
intptr_t v = _LockWord.FullWord;
if ((v & _LBIT) == 0) {
- if (CASPTR (&_LockWord, v, v|_LBIT) == v) {
+ if (Atomic::cmpxchg (v|_LBIT, &_LockWord.FullWord, v) == v) {
return 1;
}
continue;
@@ -419,13 +422,13 @@
intptr_t v = _LockWord.FullWord;
for (;;) {
if ((v & _LBIT) == 0) {
- const intptr_t u = CASPTR(&_LockWord, v, v|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(v|_LBIT, &_LockWord.FullWord, v);
if (u == v) return 1; // indicate acquired
v = u;
} else {
// Anticipate success ...
ESelf->ListNext = (ParkEvent *)(v & ~_LBIT);
- const intptr_t u = CASPTR(&_LockWord, v, intptr_t(ESelf)|_LBIT);
+ const intptr_t u = Atomic::cmpxchg(intptr_t(ESelf)|_LBIT, &_LockWord.FullWord, v);
if (u == v) return 0; // indicate pushed onto cxq
v = u;
}
@@ -463,7 +466,7 @@
OrderAccess::fence();
// Optional optimization ... try barging on the inner lock
- if ((NativeMonitorFlags & 32) && CASPTR (&_OnDeck, NULL, UNS(ESelf)) == 0) {
+ if ((NativeMonitorFlags & 32) && Atomic::cmpxchg(ESelf, &_OnDeck, (ParkEvent*)NULL) == NULL) {
goto OnDeck_LOOP;
}
@@ -474,7 +477,7 @@
// Only the OnDeck thread can try to acquire -- contend for -- the lock.
// CONSIDER: use Self->OnDeck instead of m->OnDeck.
// Deschedule Self so that others may run.
- while (OrderAccess::load_ptr_acquire(&_OnDeck) != ESelf) {
+ while (OrderAccess::load_acquire(&_OnDeck) != ESelf) {
ParkCommon(ESelf, 0);
}
@@ -570,7 +573,7 @@
// Unlike a normal lock, however, the exiting thread "locks" OnDeck,
// picks a successor and marks that thread as OnDeck. That successor
// thread will then clear OnDeck once it eventually acquires the outer lock.
- if (CASPTR (&_OnDeck, NULL, _LBIT) != UNS(NULL)) {
+ if (Atomic::cmpxchg((ParkEvent*)_LBIT, &_OnDeck, (ParkEvent*)NULL) != NULL) {
return;
}
@@ -585,14 +588,14 @@
assert(RelaxAssert || w != Thread::current()->_MutexEvent, "invariant");
_EntryList = w->ListNext;
// as a diagnostic measure consider setting w->_ListNext = BAD
- assert(UNS(_OnDeck) == _LBIT, "invariant");
+ assert(intptr_t(_OnDeck) == _LBIT, "invariant");
// Pass OnDeck role to w, ensuring that _EntryList has been set first.
// w will clear _OnDeck once it acquires the outer lock.
// Note that once we set _OnDeck that thread can acquire the mutex, proceed
// with its critical section and then enter this code to unlock the mutex. So
// you can have multiple threads active in IUnlock at the same time.
- OrderAccess::release_store_ptr(&_OnDeck, w);
+ OrderAccess::release_store(&_OnDeck, w);
// Another optional optimization ...
// For heavily contended locks it's not uncommon that some other
@@ -616,7 +619,7 @@
for (;;) {
// optional optimization - if locked, the owner is responsible for succession
if (cxq & _LBIT) goto Punt;
- const intptr_t vfy = CASPTR(&_LockWord, cxq, cxq & _LBIT);
+ const intptr_t vfy = Atomic::cmpxchg(cxq & _LBIT, &_LockWord.FullWord, cxq);
if (vfy == cxq) break;
cxq = vfy;
// Interference - LockWord changed - Just retry
@@ -652,7 +655,7 @@
// A thread could have added itself to cxq since this thread previously checked.
// Detect and recover by refetching cxq.
Punt:
- assert(UNS(_OnDeck) == _LBIT, "invariant");
+ assert(intptr_t(_OnDeck) == _LBIT, "invariant");
_OnDeck = NULL; // Release inner lock.
OrderAccess::storeload(); // Dekker duality - pivot point
@@ -693,7 +696,7 @@
const intptr_t v = _LockWord.FullWord;
assert((v & 0xFF) == _LBIT, "invariant");
nfy->ListNext = (ParkEvent *)(v & ~_LBIT);
- if (CASPTR (&_LockWord, v, UNS(nfy)|_LBIT) == v) break;
+ if (Atomic::cmpxchg(intptr_t(nfy)|_LBIT, &_LockWord.FullWord, v) == v) break;
// interference - _LockWord changed -- just retry
}
// Note that setting Notified before pushing nfy onto the cxq is
@@ -840,7 +843,7 @@
// ESelf is now on the cxq, EntryList or at the OnDeck position.
// The following fragment is extracted from Monitor::ILock()
for (;;) {
- if (OrderAccess::load_ptr_acquire(&_OnDeck) == ESelf && TrySpin(Self)) break;
+ if (OrderAccess::load_acquire(&_OnDeck) == ESelf && TrySpin(Self)) break;
ParkCommon(ESelf, 0);
}
assert(_OnDeck == ESelf, "invariant");
@@ -1058,7 +1061,7 @@
// Only the OnDeck thread can try to acquire -- contend for -- the lock.
// CONSIDER: use Self->OnDeck instead of m->OnDeck.
for (;;) {
- if (OrderAccess::load_ptr_acquire(&_OnDeck) == ESelf && TrySpin(NULL)) break;
+ if (OrderAccess::load_acquire(&_OnDeck) == ESelf && TrySpin(NULL)) break;
ParkCommon(ESelf, 0);
}
--- a/src/hotspot/share/runtime/mutex.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/mutex.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -67,13 +67,6 @@
volatile jbyte Bytes [sizeof(intptr_t)] ;
} ;
-// Endian-ness ... index of least-significant byte in SplitWord.Bytes[]
-#ifdef VM_LITTLE_ENDIAN
- #define _LSBINDEX 0
-#else
- #define _LSBINDEX (sizeof(intptr_t)-1)
-#endif
-
class ParkEvent ;
// See orderAccess.hpp. We assume throughout the VM that mutex lock and
@@ -128,7 +121,6 @@
protected: // Monitor-Mutex metadata
SplitWord _LockWord ; // Contention queue (cxq) colocated with Lock-byte
- enum LockWordBits { _LBIT=1 } ;
Thread * volatile _owner; // The owner of the lock
// Consider sequestering _owner on its own $line
// to aid future synchronization mechanisms.
--- a/src/hotspot/share/runtime/objectMonitor.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -249,7 +249,7 @@
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
Thread * const Self = THREAD;
- void * cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL);
+ void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL);
if (cur == NULL) {
// Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
assert(_recursions == 0, "invariant");
@@ -406,7 +406,7 @@
int ObjectMonitor::TryLock(Thread * Self) {
void * own = _owner;
if (own != NULL) return 0;
- if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+ if (Atomic::cmpxchg(Self, &_owner, (void*)NULL) == NULL) {
// Either guarantee _recursions == 0 or set _recursions = 0.
assert(_recursions == 0, "invariant");
assert(_owner == Self, "invariant");
@@ -476,7 +476,7 @@
ObjectWaiter * nxt;
for (;;) {
node._next = nxt = _cxq;
- if (Atomic::cmpxchg_ptr(&node, &_cxq, nxt) == nxt) break;
+ if (Atomic::cmpxchg(&node, &_cxq, nxt) == nxt) break;
// Interference - the CAS failed because _cxq changed. Just retry.
// As an optional optimization we retry the lock.
@@ -514,7 +514,7 @@
if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
// Try to assume the role of responsible thread for the monitor.
// CONSIDER: ST vs CAS vs { if (Responsible==null) Responsible=Self }
- Atomic::cmpxchg_ptr(Self, &_Responsible, NULL);
+ Atomic::cmpxchg(Self, &_Responsible, (Thread*)NULL);
}
// The lock might have been released while this thread was occupied queueing
@@ -538,7 +538,7 @@
assert(_owner != Self, "invariant");
if ((SyncFlags & 2) && _Responsible == NULL) {
- Atomic::cmpxchg_ptr(Self, &_Responsible, NULL);
+ Atomic::cmpxchg(Self, &_Responsible, (Thread*)NULL);
}
// park self
@@ -795,7 +795,7 @@
ObjectWaiter * v = _cxq;
assert(v != NULL, "invariant");
- if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
+ if (v != SelfNode || Atomic::cmpxchg(SelfNode->_next, &_cxq, v) != v) {
// The CAS above can fail from interference IFF a "RAT" arrived.
// In that case Self must be in the interior and can no longer be
// at the head of cxq.
@@ -947,7 +947,7 @@
// in massive wasteful coherency traffic on classic SMP systems.
// Instead, I use release_store(), which is implemented as just a simple
// ST on x64, x86 and SPARC.
- OrderAccess::release_store_ptr(&_owner, NULL); // drop the lock
+ OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock
OrderAccess::storeload(); // See if we need to wake a successor
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
TEVENT(Inflated exit - simple egress);
@@ -992,13 +992,13 @@
// to reacquire the lock the responsibility for ensuring succession
// falls to the new owner.
//
- if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
+ if (Atomic::cmpxchg(THREAD, &_owner, (void*)NULL) != NULL) {
return;
}
TEVENT(Exit - Reacquired);
} else {
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
- OrderAccess::release_store_ptr(&_owner, NULL); // drop the lock
+ OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock
OrderAccess::storeload();
// Ratify the previously observed values.
if (_cxq == NULL || _succ != NULL) {
@@ -1017,7 +1017,7 @@
// B. If the elements forming the EntryList|cxq are TSM
// we could simply unpark() the lead thread and return
// without having set _succ.
- if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
+ if (Atomic::cmpxchg(THREAD, &_owner, (void*)NULL) != NULL) {
TEVENT(Inflated exit - reacquired succeeded);
return;
}
@@ -1052,7 +1052,7 @@
w = _cxq;
for (;;) {
assert(w != NULL, "Invariant");
- ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr(NULL, &_cxq, w);
+ ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w);
if (u == w) break;
w = u;
}
@@ -1093,7 +1093,7 @@
w = _cxq;
for (;;) {
assert(w != NULL, "Invariant");
- ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr(NULL, &_cxq, w);
+ ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w);
if (u == w) break;
w = u;
}
@@ -1146,7 +1146,7 @@
// The following loop is tantamount to: w = swap(&cxq, NULL)
for (;;) {
assert(w != NULL, "Invariant");
- ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr(NULL, &_cxq, w);
+ ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w);
if (u == w) break;
w = u;
}
@@ -1279,7 +1279,7 @@
Wakee = NULL;
// Drop the lock
- OrderAccess::release_store_ptr(&_owner, NULL);
+ OrderAccess::release_store(&_owner, (void*)NULL);
OrderAccess::fence(); // ST _owner vs LD in unpark()
if (SafepointSynchronize::do_call_back()) {
@@ -1688,7 +1688,7 @@
for (;;) {
ObjectWaiter * front = _cxq;
iterator->_next = front;
- if (Atomic::cmpxchg_ptr(iterator, &_cxq, front) == front) {
+ if (Atomic::cmpxchg(iterator, &_cxq, front) == front) {
break;
}
}
@@ -1699,7 +1699,7 @@
ObjectWaiter * tail = _cxq;
if (tail == NULL) {
iterator->_next = NULL;
- if (Atomic::cmpxchg_ptr(iterator, &_cxq, NULL) == NULL) {
+ if (Atomic::cmpxchg(iterator, &_cxq, (ObjectWaiter*)NULL) == NULL) {
break;
}
} else {
@@ -1980,7 +1980,7 @@
Thread * ox = (Thread *) _owner;
if (ox == NULL) {
- ox = (Thread *) Atomic::cmpxchg_ptr(Self, &_owner, NULL);
+ ox = (Thread*)Atomic::cmpxchg(Self, &_owner, (void*)NULL);
if (ox == NULL) {
// The CAS succeeded -- this thread acquired ownership
// Take care of some bookkeeping to exit spin state.
--- a/src/hotspot/share/runtime/objectMonitor.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -143,7 +143,7 @@
volatile markOop _header; // displaced object header word - mark
void* volatile _object; // backward object pointer - strong root
public:
- ObjectMonitor * FreeNext; // Free list linkage
+ ObjectMonitor* FreeNext; // Free list linkage
private:
DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE,
sizeof(volatile markOop) + sizeof(void * volatile) +
@@ -251,6 +251,7 @@
((ObjectMonitor::f ## _offset_in_bytes()) - markOopDesc::monitor_value)
markOop header() const;
+ volatile markOop* header_addr();
void set_header(markOop hdr);
intptr_t is_busy() const {
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,11 @@
return _header;
}
+inline volatile markOop* ObjectMonitor::header_addr() {
+ assert((intptr_t)this == (intptr_t)&_header, "sync code expects this");
+ return &_header;
+}
+
inline void ObjectMonitor::set_header(markOop hdr) {
_header = hdr;
}
--- a/src/hotspot/share/runtime/orderAccess.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/orderAccess.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -268,21 +268,12 @@
template <typename T>
static T load_acquire(const volatile T* p);
- static intptr_t load_ptr_acquire(const volatile intptr_t* p);
- static void* load_ptr_acquire(const volatile void* p);
-
template <typename T, typename D>
static void release_store(volatile D* p, T v);
- static void release_store_ptr(volatile intptr_t* p, intptr_t v);
- static void release_store_ptr(volatile void* p, void* v);
-
template <typename T, typename D>
static void release_store_fence(volatile D* p, T v);
- static void release_store_ptr_fence(volatile intptr_t* p, intptr_t v);
- static void release_store_ptr_fence(volatile void* p, void* v);
-
private:
// This is a helper that invokes the StubRoutines::fence_entry()
// routine if it exists, It should only be used by platforms that
--- a/src/hotspot/share/runtime/orderAccess.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/orderAccess.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -54,28 +54,13 @@
return LoadImpl<T, PlatformOrderedLoad<sizeof(T), X_ACQUIRE> >()(p);
}
-inline intptr_t OrderAccess::load_ptr_acquire(const volatile intptr_t* p) {
- return load_acquire(p);
-}
-
-inline void* OrderAccess::load_ptr_acquire(const volatile void* p) {
- return load_acquire(static_cast<void* const volatile *>(p));
-}
-
template <typename T, typename D>
inline void OrderAccess::release_store(volatile D* p, T v) {
StoreImpl<T, D, PlatformOrderedStore<sizeof(D), RELEASE_X> >()(v, p);
}
-inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release_store(p, v); }
-inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { release_store(static_cast<void* volatile*>(p), v); }
-
template <typename T, typename D>
inline void OrderAccess::release_store_fence(volatile D* p, T v) {
StoreImpl<T, D, PlatformOrderedStore<sizeof(D), RELEASE_X_FENCE> >()(v, p);
}
-
-inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_fence(p, v); }
-inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_fence(static_cast<void* volatile*>(p), v); }
-
#endif // SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP
--- a/src/hotspot/share/runtime/safepoint.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/safepoint.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -63,10 +63,6 @@
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/cms/concurrentMarkSweepThread.hpp"
-#include "gc/g1/suspendibleThreadSet.hpp"
-#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
#endif
@@ -94,15 +90,7 @@
_ts_of_current_safepoint = tty->time_stamp().seconds();
}
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC) {
- // In the future we should investigate whether CMS can use the
- // more-general mechanism below. DLD (01/05).
- ConcurrentMarkSweepThread::synchronize(false);
- } else if (UseG1GC) {
- SuspendibleThreadSet::synchronize();
- }
-#endif // INCLUDE_ALL_GCS
+ Universe::heap()->safepoint_synchronize_begin();
// By getting the Threads_lock, we assure that no threads are about to start or
// exit. It is released again in SafepointSynchronize::end().
@@ -333,7 +321,8 @@
}
if (sync_event.should_commit()) {
- sync_event.set_safepointId(safepoint_counter());
+ // Group this event together with the ones committed after the counter is increased
+ sync_event.set_safepointId(safepoint_counter() + 1);
sync_event.set_initialThreadCount(initial_running);
sync_event.set_runningThreadCount(_waiting_to_block);
sync_event.set_iterations(iterations);
@@ -511,14 +500,7 @@
Threads_lock->unlock();
}
-#if INCLUDE_ALL_GCS
- // If there are any concurrent GC threads resume them.
- if (UseConcMarkSweepGC) {
- ConcurrentMarkSweepThread::desynchronize(false);
- } else if (UseG1GC) {
- SuspendibleThreadSet::desynchronize();
- }
-#endif // INCLUDE_ALL_GCS
+ Universe::heap()->safepoint_synchronize_end();
// record this time so VMThread can keep track how much time has elapsed
// since last safepoint.
_end_of_last_safepoint = os::javaTimeMillis();
@@ -581,7 +563,7 @@
void work(uint worker_id) {
// All threads deflate monitors and mark nmethods (if necessary).
- Threads::parallel_java_threads_do(&_cleanup_threads_cl);
+ Threads::possibly_parallel_threads_do(true, &_cleanup_threads_cl);
if (!_subtasks.is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_DEFLATE_MONITORS)) {
const char* name = "deflating idle monitors";
--- a/src/hotspot/share/runtime/stubRoutines.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/stubRoutines.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -59,11 +59,10 @@
jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_verify_oop_subroutine_entry = NULL;
address StubRoutines::_atomic_xchg_entry = NULL;
-address StubRoutines::_atomic_xchg_ptr_entry = NULL;
+address StubRoutines::_atomic_xchg_long_entry = NULL;
address StubRoutines::_atomic_store_entry = NULL;
address StubRoutines::_atomic_store_ptr_entry = NULL;
address StubRoutines::_atomic_cmpxchg_entry = NULL;
-address StubRoutines::_atomic_cmpxchg_ptr_entry = NULL;
address StubRoutines::_atomic_cmpxchg_byte_entry = NULL;
address StubRoutines::_atomic_cmpxchg_long_entry = NULL;
address StubRoutines::_atomic_add_entry = NULL;
--- a/src/hotspot/share/runtime/stubRoutines.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/stubRoutines.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -101,11 +101,10 @@
static address _throw_delayed_StackOverflowError_entry;
static address _atomic_xchg_entry;
- static address _atomic_xchg_ptr_entry;
+ static address _atomic_xchg_long_entry;
static address _atomic_store_entry;
static address _atomic_store_ptr_entry;
static address _atomic_cmpxchg_entry;
- static address _atomic_cmpxchg_ptr_entry;
static address _atomic_cmpxchg_byte_entry;
static address _atomic_cmpxchg_long_entry;
static address _atomic_add_entry;
@@ -276,11 +275,10 @@
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; }
static address atomic_xchg_entry() { return _atomic_xchg_entry; }
- static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
+ static address atomic_xchg_long_entry() { return _atomic_xchg_long_entry; }
static address atomic_store_entry() { return _atomic_store_entry; }
static address atomic_store_ptr_entry() { return _atomic_store_ptr_entry; }
static address atomic_cmpxchg_entry() { return _atomic_cmpxchg_entry; }
- static address atomic_cmpxchg_ptr_entry() { return _atomic_cmpxchg_ptr_entry; }
static address atomic_cmpxchg_byte_entry() { return _atomic_cmpxchg_byte_entry; }
static address atomic_cmpxchg_long_entry() { return _atomic_cmpxchg_long_entry; }
static address atomic_add_entry() { return _atomic_add_entry; }
--- a/src/hotspot/share/runtime/synchronizer.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/synchronizer.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -111,9 +111,7 @@
static volatile intptr_t gInflationLocks[NINFLATIONLOCKS];
// global list of blocks of monitors
-// gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't
-// want to expose the PaddedEnd template more than necessary.
-ObjectMonitor * volatile ObjectSynchronizer::gBlockList = NULL;
+PaddedEnd<ObjectMonitor> * volatile ObjectSynchronizer::gBlockList = NULL;
// global monitor free list
ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL;
// global monitor in-use list, for moribund threads,
@@ -241,7 +239,7 @@
lock->set_displaced_header(markOopDesc::unused_mark());
if (owner == NULL &&
- Atomic::cmpxchg_ptr(Self, &(m->_owner), NULL) == NULL) {
+ Atomic::cmpxchg(Self, &(m->_owner), (void*)NULL) == NULL) {
assert(m->_recursions == 0, "invariant");
assert(m->_owner == Self, "invariant");
return true;
@@ -802,7 +800,7 @@
hash = get_next_hash(Self, obj);
temp = mark->copy_set_hash(hash); // merge hash code into header
assert(temp->is_neutral(), "invariant");
- test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
+ test = Atomic::cmpxchg(temp, monitor->header_addr(), mark);
if (test != mark) {
// The only update to the header in the monitor (outside GC)
// is install the hash code. If someone add new usage of
@@ -939,8 +937,7 @@
// Visitors ...
void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
- PaddedEnd<ObjectMonitor> * block =
- (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+ PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header");
for (int i = _BLOCKSIZE - 1; i > 0; i--) {
@@ -955,9 +952,9 @@
}
// Get the next block in the block list.
-static inline ObjectMonitor* next(ObjectMonitor* block) {
+static inline PaddedEnd<ObjectMonitor>* next(PaddedEnd<ObjectMonitor>* block) {
assert(block->object() == CHAINMARKER, "must be a block header");
- block = block->FreeNext;
+ block = (PaddedEnd<ObjectMonitor>*) block->FreeNext;
assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
return block;
}
@@ -991,9 +988,8 @@
void ObjectSynchronizer::global_oops_do(OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- PaddedEnd<ObjectMonitor> * block =
- (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
- for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
+ PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
+ for (; block != NULL; block = next(block)) {
assert(block->object() == CHAINMARKER, "must be a block header");
for (int i = 1; i < _BLOCKSIZE; i++) {
ObjectMonitor* mid = (ObjectMonitor *)&block[i];
@@ -1232,7 +1228,7 @@
temp[0].FreeNext = gBlockList;
// There are lock-free uses of gBlockList so make sure that
// the previous stores happen before we update gBlockList.
- OrderAccess::release_store_ptr(&gBlockList, temp);
+ OrderAccess::release_store(&gBlockList, temp);
// Add the new string of objectMonitors to the global free list
temp[_BLOCKSIZE - 1].FreeNext = gFreeList;
@@ -1734,9 +1730,8 @@
}
} else {
- PaddedEnd<ObjectMonitor> * block =
- (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
- for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
+ PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
+ for (; block != NULL; block = next(block)) {
// Iterate over all extant monitors - Scavenge all idle monitors.
assert(block->object() == CHAINMARKER, "must be a block header");
counters->nInCirculation += _BLOCKSIZE;
@@ -1969,12 +1964,10 @@
// the list of extant blocks without taking a lock.
int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
- PaddedEnd<ObjectMonitor> * block =
- (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+ PaddedEnd<ObjectMonitor> * block = OrderAccess::load_acquire(&gBlockList);
while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header");
- if (monitor > (ObjectMonitor *)&block[0] &&
- monitor < (ObjectMonitor *)&block[_BLOCKSIZE]) {
+ if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) {
address mon = (address)monitor;
address blk = (address)block;
size_t diff = mon - blk;
--- a/src/hotspot/share/runtime/synchronizer.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/synchronizer.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_RUNTIME_SYNCHRONIZER_HPP
#define SHARE_VM_RUNTIME_SYNCHRONIZER_HPP
+#include "memory/padded.hpp"
#include "oops/markOop.hpp"
#include "runtime/basicLock.hpp"
#include "runtime/handles.hpp"
@@ -159,9 +160,7 @@
private:
enum { _BLOCKSIZE = 128 };
// global list of blocks of monitors
- // gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't
- // want to expose the PaddedEnd template more than necessary.
- static ObjectMonitor * volatile gBlockList;
+ static PaddedEnd<ObjectMonitor> * volatile gBlockList;
// global monitor free list
static ObjectMonitor * volatile gFreeList;
// global monitor in-use list, for moribund threads,
--- a/src/hotspot/share/runtime/thread.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/thread.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -3349,20 +3349,17 @@
// If CompilerThreads ever become non-JavaThreads, add them here
}
-void Threads::parallel_java_threads_do(ThreadClosure* tc) {
+void Threads::possibly_parallel_threads_do(bool is_par, ThreadClosure* tc) {
int cp = Threads::thread_claim_parity();
ALL_JAVA_THREADS(p) {
- if (p->claim_oops_do(true, cp)) {
+ if (p->claim_oops_do(is_par, cp)) {
tc->do_thread(p);
}
}
- // Thread claiming protocol requires us to claim the same interesting
- // threads on all paths. Notably, Threads::possibly_parallel_threads_do
- // claims all Java threads *and* the VMThread. To avoid breaking the
- // claiming protocol, we have to claim VMThread on this path too, even
- // if we do not apply the closure to the VMThread.
VMThread* vmt = VMThread::vm_thread();
- (void)vmt->claim_oops_do(true, cp);
+ if (vmt->claim_oops_do(is_par, cp)) {
+ tc->do_thread(vmt);
+ }
}
// The system initialization in the library has three phases.
@@ -4324,17 +4321,20 @@
}
#endif // ASSERT
+class ParallelOopsDoThreadClosure : public ThreadClosure {
+private:
+ OopClosure* _f;
+ CodeBlobClosure* _cf;
+public:
+ ParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf) : _f(f), _cf(cf) {}
+ void do_thread(Thread* t) {
+ t->oops_do(_f, _cf);
+ }
+};
+
void Threads::possibly_parallel_oops_do(bool is_par, OopClosure* f, CodeBlobClosure* cf) {
- int cp = Threads::thread_claim_parity();
- ALL_JAVA_THREADS(p) {
- if (p->claim_oops_do(is_par, cp)) {
- p->oops_do(f, cf);
- }
- }
- VMThread* vmt = VMThread::vm_thread();
- if (vmt->claim_oops_do(is_par, cp)) {
- vmt->oops_do(f, cf);
- }
+ ParallelOopsDoThreadClosure tc(f, cf);
+ possibly_parallel_threads_do(is_par, &tc);
}
#if INCLUDE_ALL_GCS
@@ -4701,13 +4701,12 @@
//
-typedef volatile intptr_t MutexT; // Mux Lock-word
-enum MuxBits { LOCKBIT = 1 };
+const intptr_t LOCKBIT = 1;
void Thread::muxAcquire(volatile intptr_t * Lock, const char * LockName) {
- intptr_t w = Atomic::cmpxchg_ptr(LOCKBIT, Lock, 0);
+ intptr_t w = Atomic::cmpxchg(LOCKBIT, Lock, (intptr_t)0);
if (w == 0) return;
- if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
return;
}
@@ -4720,7 +4719,7 @@
// Optional spin phase: spin-then-park strategy
while (--its >= 0) {
w = *Lock;
- if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
return;
}
}
@@ -4733,7 +4732,7 @@
for (;;) {
w = *Lock;
if ((w & LOCKBIT) == 0) {
- if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if (Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
Self->OnList = 0; // hygiene - allows stronger asserts
return;
}
@@ -4741,7 +4740,7 @@
}
assert(w & LOCKBIT, "invariant");
Self->ListNext = (ParkEvent *) (w & ~LOCKBIT);
- if (Atomic::cmpxchg_ptr(intptr_t(Self)|LOCKBIT, Lock, w) == w) break;
+ if (Atomic::cmpxchg(intptr_t(Self)|LOCKBIT, Lock, w) == w) break;
}
while (Self->OnList != 0) {
@@ -4751,9 +4750,9 @@
}
void Thread::muxAcquireW(volatile intptr_t * Lock, ParkEvent * ev) {
- intptr_t w = Atomic::cmpxchg_ptr(LOCKBIT, Lock, 0);
+ intptr_t w = Atomic::cmpxchg(LOCKBIT, Lock, (intptr_t)0);
if (w == 0) return;
- if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
return;
}
@@ -4770,7 +4769,7 @@
// Optional spin phase: spin-then-park strategy
while (--its >= 0) {
w = *Lock;
- if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if ((w & LOCKBIT) == 0 && Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
if (ReleaseAfter != NULL) {
ParkEvent::Release(ReleaseAfter);
}
@@ -4786,7 +4785,7 @@
for (;;) {
w = *Lock;
if ((w & LOCKBIT) == 0) {
- if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+ if (Atomic::cmpxchg(w|LOCKBIT, Lock, w) == w) {
ev->OnList = 0;
// We call ::Release while holding the outer lock, thus
// artificially lengthening the critical section.
@@ -4801,7 +4800,7 @@
}
assert(w & LOCKBIT, "invariant");
ev->ListNext = (ParkEvent *) (w & ~LOCKBIT);
- if (Atomic::cmpxchg_ptr(intptr_t(ev)|LOCKBIT, Lock, w) == w) break;
+ if (Atomic::cmpxchg(intptr_t(ev)|LOCKBIT, Lock, w) == w) break;
}
while (ev->OnList != 0) {
@@ -4837,7 +4836,7 @@
// store (CAS) to the lock-word that releases the lock becomes globally visible.
void Thread::muxRelease(volatile intptr_t * Lock) {
for (;;) {
- const intptr_t w = Atomic::cmpxchg_ptr(0, Lock, LOCKBIT);
+ const intptr_t w = Atomic::cmpxchg((intptr_t)0, Lock, LOCKBIT);
assert(w & LOCKBIT, "invariant");
if (w == LOCKBIT) return;
ParkEvent * const List = (ParkEvent *) (w & ~LOCKBIT);
@@ -4848,7 +4847,7 @@
// The following CAS() releases the lock and pops the head element.
// The CAS() also ratifies the previously fetched lock-word value.
- if (Atomic::cmpxchg_ptr (intptr_t(nxt), Lock, w) != w) {
+ if (Atomic::cmpxchg(intptr_t(nxt), Lock, w) != w) {
continue;
}
List->OnList = 0;
--- a/src/hotspot/share/runtime/thread.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/thread.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -2052,7 +2052,7 @@
static bool includes(JavaThread* p);
static JavaThread* first() { return _thread_list; }
static void threads_do(ThreadClosure* tc);
- static void parallel_java_threads_do(ThreadClosure* tc);
+ static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc);
// Initializes the vm and creates the vm thread
static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain);
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -61,6 +61,7 @@
#include "memory/allocation.inline.hpp"
#include "memory/heap.hpp"
#include "memory/metachunk.hpp"
+#include "memory/padded.hpp"
#include "memory/referenceType.hpp"
#include "memory/universe.hpp"
#include "memory/virtualspace.hpp"
@@ -198,6 +199,8 @@
typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
+typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
+
//--------------------------------------------------------------------------------
// VM_STRUCTS
//
@@ -359,7 +362,7 @@
/***********************/ \
\
volatile_nonstatic_field(ConstantPoolCacheEntry, _indices, intx) \
- nonstatic_field(ConstantPoolCacheEntry, _f1, volatile Metadata*) \
+ volatile_nonstatic_field(ConstantPoolCacheEntry, _f1, Metadata*) \
volatile_nonstatic_field(ConstantPoolCacheEntry, _f2, intx) \
volatile_nonstatic_field(ConstantPoolCacheEntry, _flags, intx) \
\
@@ -1052,7 +1055,7 @@
volatile_nonstatic_field(BasicLock, _displaced_header, markOop) \
nonstatic_field(BasicObjectLock, _lock, BasicLock) \
nonstatic_field(BasicObjectLock, _obj, oop) \
- static_ptr_volatile_field(ObjectSynchronizer, gBlockList, ObjectMonitor*) \
+ static_ptr_volatile_field(ObjectSynchronizer, gBlockList, PaddedObjectMonitor*) \
\
/*********************/ \
/* Matcher (C2 only) */ \
@@ -1680,6 +1683,7 @@
/************/ \
\
declare_toplevel_type(ObjectMonitor) \
+ declare_toplevel_type(PaddedObjectMonitor) \
declare_toplevel_type(ObjectSynchronizer) \
declare_toplevel_type(BasicLock) \
declare_toplevel_type(BasicObjectLock) \
@@ -2154,6 +2158,7 @@
declare_toplevel_type(nmethod*) \
COMPILER2_PRESENT(declare_unsigned_integer_type(node_idx_t)) \
declare_toplevel_type(ObjectMonitor*) \
+ declare_toplevel_type(PaddedObjectMonitor*) \
declare_toplevel_type(oop*) \
declare_toplevel_type(OopMap**) \
declare_toplevel_type(OopMapCache*) \
--- a/src/hotspot/share/services/mallocSiteTable.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/mallocSiteTable.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -147,7 +147,7 @@
if (entry == NULL) return NULL;
// swap in the head
- if (Atomic::cmpxchg_ptr((void*)entry, (volatile void *)&_table[index], NULL) == NULL) {
+ if (Atomic::cmpxchg(entry, &_table[index], (MallocSiteHashtableEntry*)NULL) == NULL) {
return entry->data();
}
@@ -257,3 +257,7 @@
}
_lock_state = ExclusiveLock;
}
+
+bool MallocSiteHashtableEntry::atomic_insert(MallocSiteHashtableEntry* entry) {
+ return Atomic::cmpxchg(entry, &_next, (MallocSiteHashtableEntry*)NULL) == NULL;
+}
--- a/src/hotspot/share/services/mallocSiteTable.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/mallocSiteTable.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -61,8 +61,8 @@
// Malloc site hashtable entry
class MallocSiteHashtableEntry : public CHeapObj<mtNMT> {
private:
- MallocSite _malloc_site;
- MallocSiteHashtableEntry* _next;
+ MallocSite _malloc_site;
+ MallocSiteHashtableEntry* volatile _next;
public:
MallocSiteHashtableEntry() : _next(NULL) { }
@@ -79,10 +79,7 @@
// Insert an entry atomically.
// Return true if the entry is inserted successfully.
// The operation can be failed due to contention from other thread.
- bool atomic_insert(const MallocSiteHashtableEntry* entry) {
- return (Atomic::cmpxchg_ptr((void*)entry, (volatile void*)&_next,
- NULL) == NULL);
- }
+ bool atomic_insert(MallocSiteHashtableEntry* entry);
void set_callsite(const MallocSite& site) {
_malloc_site = site;
--- a/src/hotspot/share/services/mallocTracker.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/mallocTracker.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -68,7 +68,7 @@
if (sz > 0) {
// unary minus operator applied to unsigned type, result still unsigned
#pragma warning(suppress: 4146)
- Atomic::add(-sz, &_size);
+ Atomic::sub(sz, &_size);
}
}
--- a/src/hotspot/share/services/memoryManager.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/memoryManager.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -94,7 +94,7 @@
instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
// Must do an acquire so as to force ordering of subsequent
// loads from anything _memory_mgr_obj points to or implies.
- instanceOop mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);
+ instanceOop mgr_obj = OrderAccess::load_acquire(&_memory_mgr_obj);
if (mgr_obj == NULL) {
// It's ok for more than one thread to execute the code up to the locked region.
// Extra manager instances will just be gc'ed.
@@ -147,7 +147,7 @@
//
// The lock has done an acquire, so the load can't float above it, but
// we need to do a load_acquire as above.
- mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);
+ mgr_obj = OrderAccess::load_acquire(&_memory_mgr_obj);
if (mgr_obj != NULL) {
return mgr_obj;
}
@@ -159,7 +159,7 @@
// with creating the management object are visible before publishing
// its address. The unlock will publish the store to _memory_mgr_obj
// because it does a release first.
- OrderAccess::release_store_ptr(&_memory_mgr_obj, mgr_obj);
+ OrderAccess::release_store(&_memory_mgr_obj, mgr_obj);
}
}
--- a/src/hotspot/share/services/memoryPool.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/memoryPool.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -82,7 +82,7 @@
instanceOop MemoryPool::get_memory_pool_instance(TRAPS) {
// Must do an acquire so as to force ordering of subsequent
// loads from anything _memory_pool_obj points to or implies.
- instanceOop pool_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_pool_obj);
+ instanceOop pool_obj = OrderAccess::load_acquire(&_memory_pool_obj);
if (pool_obj == NULL) {
// It's ok for more than one thread to execute the code up to the locked region.
// Extra pool instances will just be gc'ed.
@@ -123,7 +123,7 @@
//
// The lock has done an acquire, so the load can't float above it,
// but we need to do a load_acquire as above.
- pool_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_pool_obj);
+ pool_obj = OrderAccess::load_acquire(&_memory_pool_obj);
if (pool_obj != NULL) {
return pool_obj;
}
@@ -135,7 +135,7 @@
// with creating the pool are visible before publishing its address.
// The unlock will publish the store to _memory_pool_obj because
// it does a release first.
- OrderAccess::release_store_ptr(&_memory_pool_obj, pool_obj);
+ OrderAccess::release_store(&_memory_pool_obj, pool_obj);
}
}
--- a/src/hotspot/share/services/memoryService.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/services/memoryService.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -86,7 +86,8 @@
void MemoryService::set_universe_heap(CollectedHeap* heap) {
CollectedHeap::Name kind = heap->kind();
switch (kind) {
- case CollectedHeap::GenCollectedHeap : {
+ case CollectedHeap::GenCollectedHeap :
+ case CollectedHeap::CMSHeap : {
add_gen_collected_heap_info(GenCollectedHeap::heap());
break;
}
--- a/src/hotspot/share/trace/trace.dtd Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/trace/trace.dtd Wed Oct 18 21:05:09 2017 +0000
@@ -65,7 +65,8 @@
is_instant CDATA "false"
is_constant CDATA "false"
is_requestable CDATA "false"
- experimental CDATA "false">
+ experimental CDATA "false"
+ cutoff CDATA "false">
<!ATTLIST struct id CDATA #REQUIRED>
<!ATTLIST value type CDATA #REQUIRED
field CDATA #REQUIRED
--- a/src/hotspot/share/trace/traceevents.xml Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/trace/traceevents.xml Wed Oct 18 21:05:09 2017 +0000
@@ -104,6 +104,24 @@
<value type="INFLATECAUSE" field="cause" label="Monitor Inflation Cause" description="Cause of inflation"/>
</event>
+ <event id="BiasedLockRevocation" path="java/biased_lock_revocation" label="Biased Lock Revocation"
+ description="Revoked bias of object" has_thread="true" has_stacktrace="true" is_instant="false">
+ <value type="CLASS" field="lockClass" label="Lock Class" description="Class of object whose biased lock was revoked"/>
+ <value type="INTEGER" field="safepointId" label="Safepoint Identifier" relation="SafepointId"/>
+ </event>
+
+ <event id="BiasedLockSelfRevocation" path="java/biased_lock_self_revocation" label="Biased Lock Self Revocation"
+ description="Revoked bias of object biased towards own thread" has_thread="true" has_stacktrace="true" is_instant="false">
+ <value type="CLASS" field="lockClass" label="Lock Class" description="Class of object whose biased lock was revoked"/>
+ </event>
+
+ <event id="BiasedLockClassRevocation" path="java/biased_lock_class_revocation" label="Biased Lock Class Revocation"
+ description="Revoked biases for all instances of a class" has_thread="true" has_stacktrace="true" is_instant="false">
+ <value type="CLASS" field="revokedClass" label="Revoked Class" description="Class whose biased locks were revoked"/>
+ <value type="BOOLEAN" field="disableBiasing" label="Disable Further Biasing" description="Whether further biasing for instances of this class will be allowed"/>
+ <value type="INTEGER" field="safepointId" label="Safepoint Identifier" relation="SafepointId"/>
+ </event>
+
<event id="ReservedStackActivation" path="vm/runtime/reserved_stack_activation" label="Reserved Stack Activation"
description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack"
has_thread="true" has_stacktrace="true" is_instant="true">
--- a/src/hotspot/share/utilities/bitMap.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/utilities/bitMap.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -628,7 +628,7 @@
table[i] = num_set_bits(i);
}
- if (!Atomic::replace_if_null(table, &_pop_count_table)) {
+ if (Atomic::cmpxchg(table, &_pop_count_table, (BitMap::idx_t*)NULL) != NULL) {
guarantee(_pop_count_table != NULL, "invariant");
FREE_C_HEAP_ARRAY(idx_t, table);
}
--- a/src/hotspot/share/utilities/hashtable.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/utilities/hashtable.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -190,7 +190,7 @@
BasicHashtableEntry<F>* current = _free_list;
while (true) {
context->_removed_tail->set_next(current);
- BasicHashtableEntry<F>* old = (BasicHashtableEntry<F>*)Atomic::cmpxchg_ptr(context->_removed_head, &_free_list, current);
+ BasicHashtableEntry<F>* old = Atomic::cmpxchg(context->_removed_head, &_free_list, current);
if (old == current) {
break;
}
--- a/src/hotspot/share/utilities/hashtable.inline.hpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/utilities/hashtable.inline.hpp Wed Oct 18 21:05:09 2017 +0000
@@ -78,7 +78,7 @@
// SystemDictionary are read without locks. The new entry must be
// complete before other threads can be allowed to see it
// via a store to _buckets[index].
- OrderAccess::release_store_ptr(&_entry, l);
+ OrderAccess::release_store(&_entry, l);
}
@@ -87,7 +87,7 @@
// SystemDictionary are read without locks. The new entry must be
// complete before other threads can be allowed to see it
// via a store to _buckets[index].
- return (BasicHashtableEntry<F>*) OrderAccess::load_ptr_acquire(&_entry);
+ return OrderAccess::load_acquire(&_entry);
}
--- a/src/hotspot/share/utilities/vmError.cpp Wed Oct 18 13:52:32 2017 -0700
+++ b/src/hotspot/share/utilities/vmError.cpp Wed Oct 18 21:05:09 2017 +0000
@@ -1269,7 +1269,7 @@
}
intptr_t mytid = os::current_thread_id();
if (first_error_tid == -1 &&
- Atomic::cmpxchg_ptr(mytid, &first_error_tid, -1) == -1) {
+ Atomic::cmpxchg(mytid, &first_error_tid, (intptr_t)-1) == -1) {
// Initialize time stamps to use the same base.
out.time_stamp().update_to(1);
--- a/src/java.base/share/classes/java/lang/Object.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/lang/Object.java Wed Oct 18 21:05:09 2017 +0000
@@ -307,18 +307,67 @@
public final native void notifyAll();
/**
- * Causes the current thread to wait until either another thread invokes the
- * {@link java.lang.Object#notify()} method or the
- * {@link java.lang.Object#notifyAll()} method for this object, or a
- * specified amount of time has elapsed.
+ * Causes the current thread to wait until it is awakened, typically
+ * by being <em>notified</em> or <em>interrupted</em>.
+ * <p>
+ * In all respects, this method behaves as if {@code wait(0L, 0)}
+ * had been called. See the specification of the {@link #wait(long, int)} method
+ * for details.
+ *
+ * @throws IllegalMonitorStateException if the current thread is not
+ * the owner of the object's monitor
+ * @throws InterruptedException if any thread interrupted the current thread before or
+ * while the current thread was waiting. The <em>interrupted status</em> of the
+ * current thread is cleared when this exception is thrown.
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait(long)
+ * @see #wait(long, int)
+ */
+ public final void wait() throws InterruptedException {
+ wait(0L);
+ }
+
+ /**
+ * Causes the current thread to wait until it is awakened, typically
+ * by being <em>notified</em> or <em>interrupted</em>, or until a
+ * certain amount of real time has elapsed.
* <p>
- * The current thread must own this object's monitor.
+ * In all respects, this method behaves as if {@code wait(timeout, 0)}
+ * had been called. See the specification of the {@link #wait(long, int)} method
+ * for details.
+ *
+ * @param timeout the maximum time to wait, in milliseconds
+ * @throws IllegalArgumentException if the value of {@code timeout} is negative
+ * @throws IllegalMonitorStateException if the current thread is not
+ * the owner of the object's monitor
+ * @throws InterruptedException if any thread interrupted the current thread before or
+ * while the current thread was waiting. The <em>interrupted status</em> of the
+ * current thread is cleared when this exception is thrown.
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait()
+ * @see #wait(long, int)
+ */
+ public final native void wait(long timeout) throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is awakened, typically
+ * by being <em>notified</em> or <em>interrupted</em>, or until a
+ * certain amount of real time has elapsed.
* <p>
- * This method causes the current thread (call it <var>T</var>) to
- * place itself in the wait set for this object and then to relinquish
- * any and all synchronization claims on this object. Thread <var>T</var>
- * becomes disabled for thread scheduling purposes and lies dormant
- * until one of four things happens:
+ * The current thread must own this object's monitor lock. See the
+ * {@link #notify notify} method for a description of the ways in which
+ * a thread can become the owner of a monitor lock.
+ * <p>
+ * This method causes the current thread (referred to here as <var>T</var>) to
+ * place itself in the wait set for this object and then to relinquish any
+ * and all synchronization claims on this object. Note that only the locks
+ * on this object are relinquished; any other objects on which the current
+ * thread may be synchronized remain locked while the thread waits.
+ * <p>
+ * Thread <var>T</var> then becomes disabled for thread scheduling purposes
+ * and lies dormant until one of the following occurs:
* <ul>
* <li>Some other thread invokes the {@code notify} method for this
* object and thread <var>T</var> happens to be arbitrarily chosen as
@@ -327,14 +376,18 @@
* object.
* <li>Some other thread {@linkplain Thread#interrupt() interrupts}
* thread <var>T</var>.
- * <li>The specified amount of real time has elapsed, more or less. If
- * {@code timeout} is zero, however, then real time is not taken into
- * consideration and the thread simply waits until notified.
+ * <li>The specified amount of real time has elapsed, more or less.
+ * The amount of real time, in nanoseconds, is given by the expression
+ * {@code 1000000 * timeout + nanos}. If {@code timeout} and {@code nanos}
+ * are both zero, then real time is not taken into consideration and the
+ * thread waits until awakened by one of the other causes.
+ * <li>Thread <var>T</var> is awakened spuriously. (See below.)
* </ul>
+ * <p>
* The thread <var>T</var> is then removed from the wait set for this
- * object and re-enabled for thread scheduling. It then competes in the
+ * object and re-enabled for thread scheduling. It competes in the
* usual manner with other threads for the right to synchronize on the
- * object; once it has gained control of the object, all its
+ * object; once it has regained control of the object, all its
* synchronization claims on the object are restored to the status quo
* ante - that is, to the situation as of the time that the {@code wait}
* method was invoked. Thread <var>T</var> then returns from the
@@ -343,119 +396,54 @@
* thread {@code T} is exactly as it was when the {@code wait} method
* was invoked.
* <p>
- * A thread can also wake up without being notified, interrupted, or
- * timing out, a so-called <i>spurious wakeup</i>. While this will rarely
- * occur in practice, applications must guard against it by testing for
- * the condition that should have caused the thread to be awakened, and
- * continuing to wait if the condition is not satisfied. In other words,
- * waits should always occur in loops, like this one:
- * <pre>
- * synchronized (obj) {
- * while (<condition does not hold>)
- * obj.wait(timeout);
- * ... // Perform action appropriate to condition
- * }
- * </pre>
+ * A thread can wake up without being notified, interrupted, or timing out, a
+ * so-called <em>spurious wakeup</em>. While this will rarely occur in practice,
+ * applications must guard against it by testing for the condition that should
+ * have caused the thread to be awakened, and continuing to wait if the condition
+ * is not satisfied. See the example below.
+ * <p>
+ * For more information on this topic, see section 14.2,
+ * "Condition Queues," in Brian Goetz and others' <em>Java Concurrency
+ * in Practice</em> (Addison-Wesley, 2006) or Item 69 in Joshua
+ * Bloch's <em>Effective Java, Second Edition</em> (Addison-Wesley,
+ * 2008).
+ * <p>
+ * If the current thread is {@linkplain java.lang.Thread#interrupt() interrupted}
+ * by any thread before or while it is waiting, then an {@code InterruptedException}
+ * is thrown. The <em>interrupted status</em> of the current thread is cleared when
+ * this exception is thrown. This exception is not thrown until the lock status of
+ * this object has been restored as described above.
*
- * (For more information on this topic, see section 14.2,
- * Condition Queues, in Brian Goetz and others' "Java Concurrency
- * in Practice" (Addison-Wesley, 2006) or Item 69 in Joshua
- * Bloch's "Effective Java (Second Edition)" (Addison-Wesley,
- * 2008).
- *
- * <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
- * interrupted} by any thread before or while it is waiting, then an
- * {@code InterruptedException} is thrown. This exception is not
- * thrown until the lock status of this object has been restored as
- * described above.
- *
- * <p>
- * Note that the {@code wait} method, as it places the current thread
- * into the wait set for this object, unlocks only this object; any
- * other objects on which the current thread may be synchronized remain
- * locked while the thread waits.
- * <p>
- * This method should only be called by a thread that is the owner
- * of this object's monitor. See the {@code notify} method for a
- * description of the ways in which a thread can become the owner of
- * a monitor.
+ * @apiNote
+ * The recommended approach to waiting is to check the condition being awaited in
+ * a {@code while} loop around the call to {@code wait}, as shown in the example
+ * below. Among other things, this approach avoids problems that can be caused
+ * by spurious wakeups.
*
- * @param timeout the maximum time to wait in milliseconds.
- * @throws IllegalArgumentException if the value of timeout is
- * negative.
- * @throws IllegalMonitorStateException if the current thread is not
- * the owner of the object's monitor.
- * @throws InterruptedException if any thread interrupted the
- * current thread before or while the current thread
- * was waiting for a notification. The <i>interrupted
- * status</i> of the current thread is cleared when
- * this exception is thrown.
- * @see java.lang.Object#notify()
- * @see java.lang.Object#notifyAll()
- */
- public final native void wait(long timeout) throws InterruptedException;
-
- /**
- * Causes the current thread to wait until another thread invokes the
- * {@link java.lang.Object#notify()} method or the
- * {@link java.lang.Object#notifyAll()} method for this object, or
- * some other thread interrupts the current thread, or a certain
- * amount of real time has elapsed.
- * <p>
- * This method is similar to the {@code wait} method of one
- * argument, but it allows finer control over the amount of time to
- * wait for a notification before giving up. The amount of real time,
- * measured in nanoseconds, is given by:
- * <blockquote>
- * <pre>
- * 1000000*timeout+nanos</pre></blockquote>
- * <p>
- * In all other respects, this method does the same thing as the
- * method {@link #wait(long)} of one argument. In particular,
- * {@code wait(0, 0)} means the same thing as {@code wait(0)}.
- * <p>
- * The current thread must own this object's monitor. The thread
- * releases ownership of this monitor and waits until either of the
- * following two conditions has occurred:
- * <ul>
- * <li>Another thread notifies threads waiting on this object's monitor
- * to wake up either through a call to the {@code notify} method
- * or the {@code notifyAll} method.
- * <li>The timeout period, specified by {@code timeout}
- * milliseconds plus {@code nanos} nanoseconds arguments, has
- * elapsed.
- * </ul>
- * <p>
- * The thread then waits until it can re-obtain ownership of the
- * monitor and resumes execution.
- * <p>
- * As in the one argument version, interrupts and spurious wakeups are
- * possible, and this method should always be used in a loop:
- * <pre>
+ * <pre>{@code
* synchronized (obj) {
- * while (<condition does not hold>)
+ * while (<condition does not hold> and <timeout not exceeded>) {
+ * long timeout = ... ; // recompute timeout values
+ * int nanos = ... ;
* obj.wait(timeout, nanos);
- * ... // Perform action appropriate to condition
+ * }
+ * ... // Perform action appropriate to condition or timeout
* }
- * </pre>
- * This method should only be called by a thread that is the owner
- * of this object's monitor. See the {@code notify} method for a
- * description of the ways in which a thread can become the owner of
- * a monitor.
+ * }</pre>
*
- * @param timeout the maximum time to wait in milliseconds.
- * @param nanos additional time, in nanoseconds range
- * 0-999999.
- * @throws IllegalArgumentException if the value of timeout is
- * negative or the value of nanos is
- * not in the range 0-999999.
- * @throws IllegalMonitorStateException if the current thread is not
- * the owner of this object's monitor.
- * @throws InterruptedException if any thread interrupted the
- * current thread before or while the current thread
- * was waiting for a notification. The <i>interrupted
- * status</i> of the current thread is cleared when
- * this exception is thrown.
+ * @param timeout the maximum time to wait, in milliseconds
+ * @param nanos additional time, in nanoseconds, in the range range 0-999999 inclusive
+ * @throws IllegalArgumentException if the value of {@code timeout} is negative,
+ * or if the value of {@code nanos} is out of range
+ * @throws IllegalMonitorStateException if the current thread is not
+ * the owner of the object's monitor
+ * @throws InterruptedException if any thread interrupted the current thread before or
+ * while the current thread was waiting. The <em>interrupted status</em> of the
+ * current thread is cleared when this exception is thrown.
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait()
+ * @see #wait(long)
*/
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
@@ -475,48 +463,6 @@
}
/**
- * Causes the current thread to wait until another thread invokes the
- * {@link java.lang.Object#notify()} method or the
- * {@link java.lang.Object#notifyAll()} method for this object.
- * In other words, this method behaves exactly as if it simply
- * performs the call {@code wait(0)}.
- * <p>
- * The current thread must own this object's monitor. The thread
- * releases ownership of this monitor and waits until another thread
- * notifies threads waiting on this object's monitor to wake up
- * either through a call to the {@code notify} method or the
- * {@code notifyAll} method. The thread then waits until it can
- * re-obtain ownership of the monitor and resumes execution.
- * <p>
- * As in the one argument version, interrupts and spurious wakeups are
- * possible, and this method should always be used in a loop:
- * <pre>
- * synchronized (obj) {
- * while (<condition does not hold>)
- * obj.wait();
- * ... // Perform action appropriate to condition
- * }
- * </pre>
- * This method should only be called by a thread that is the owner
- * of this object's monitor. See the {@code notify} method for a
- * description of the ways in which a thread can become the owner of
- * a monitor.
- *
- * @throws IllegalMonitorStateException if the current thread is not
- * the owner of the object's monitor.
- * @throws InterruptedException if any thread interrupted the
- * current thread before or while the current thread
- * was waiting for a notification. The <i>interrupted
- * status</i> of the current thread is cleared when
- * this exception is thrown.
- * @see java.lang.Object#notify()
- * @see java.lang.Object#notifyAll()
- */
- public final void wait() throws InterruptedException {
- wait(0);
- }
-
- /**
* Called by the garbage collector on an object when garbage collection
* determines that there are no more references to the object.
* A subclass overrides the {@code finalize} method to dispose of
--- a/src/java.base/share/classes/java/util/ServiceLoader.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java Wed Oct 18 21:05:09 2017 +0000
@@ -747,8 +747,10 @@
// invoke factory method with permissions restricted by acc
try {
result = AccessController.doPrivileged(pa, acc);
- } catch (PrivilegedActionException pae) {
- exc = pae.getCause();
+ } catch (Throwable x) {
+ if (x instanceof PrivilegedActionException)
+ x = x.getCause();
+ exc = x;
}
}
if (exc != null) {
@@ -788,8 +790,10 @@
// invoke constructor with permissions restricted by acc
try {
p = AccessController.doPrivileged(pa, acc);
- } catch (PrivilegedActionException pae) {
- exc = pae.getCause();
+ } catch (Throwable x) {
+ if (x instanceof PrivilegedActionException)
+ x = x.getCause();
+ exc = x;
}
}
if (exc != null) {
@@ -852,8 +856,9 @@
PrivilegedExceptionAction<Class<?>> pa = () -> Class.forName(module, cn);
try {
clazz = AccessController.doPrivileged(pa);
- } catch (PrivilegedActionException pae) {
- Throwable x = pae.getCause();
+ } catch (Throwable x) {
+ if (x instanceof PrivilegedActionException)
+ x = x.getCause();
fail(service, "Unable to load " + cn, x);
return null;
}
@@ -1477,6 +1482,8 @@
next = (Provider<T>) loadedProviders.get(index++);
} else if (iterator.hasNext()) {
next = iterator.next();
+ loadedProviders.add((Provider<S>)next);
+ index++;
} else {
loadedAllProviders = true;
}
--- a/src/java.base/share/classes/java/util/SplittableRandom.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java Wed Oct 18 21:05:09 2017 +0000
@@ -399,6 +399,26 @@
}
/**
+ * Fills a user-supplied byte array with generated pseudorandom bytes.
+ *
+ * @param bytes the byte array to fill with pseudorandom bytes
+ * @throws NullPointerException if bytes is null
+ * @since 10
+ */
+ public void nextBytes(byte[] bytes) {
+ int i = 0;
+ int len = bytes.length;
+ for (int words = len >> 3; words--> 0; ) {
+ long rnd = nextLong();
+ for (int n = 8; n--> 0; rnd >>>= Byte.SIZE)
+ bytes[i++] = (byte)rnd;
+ }
+ if (i < len)
+ for (long rnd = nextLong(); i < len; rnd >>>= Byte.SIZE)
+ bytes[i++] = (byte)rnd;
+ }
+
+ /**
* Returns a pseudorandom {@code int} value.
*
* @return a pseudorandom {@code int} value
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Wed Oct 18 21:05:09 2017 +0000
@@ -231,15 +231,16 @@
*
* The implementation is completely directionally symmetrical,
* except that most public methods that iterate through the list
- * follow next pointers ("forward" direction).
+ * follow next pointers, in the "forward" direction.
*
- * We believe (without full proof) that all single-element deque
- * operations (e.g., addFirst, peekLast, pollLast) are linearizable
- * (see Herlihy and Shavit's book). However, some combinations of
+ * We believe (without full proof) that all single-element Deque
+ * operations that operate directly at the two ends of the Deque
+ * (e.g., addFirst, peekLast, pollLast) are linearizable (see
+ * Herlihy and Shavit's book). However, some combinations of
* operations are known not to be linearizable. In particular,
- * when an addFirst(A) is racing with pollFirst() removing B, it is
- * possible for an observer iterating over the elements to observe
- * A B C and subsequently observe A C, even though no interior
+ * when an addFirst(A) is racing with pollFirst() removing B, it
+ * is possible for an observer iterating over the elements to
+ * observe first [A B C] and then [A C], even though no interior
* removes are ever performed. Nevertheless, iterators behave
* reasonably, providing the "weakly consistent" guarantees.
*
@@ -865,21 +866,33 @@
}
public E peekFirst() {
- for (Node<E> p = first(); p != null; p = succ(p)) {
- final E item;
- if ((item = p.item) != null)
- return item;
+ restart: for (;;) {
+ for (Node<E> first = first(), p = first;;) {
+ final E item;
+ if ((item = p.item) != null) {
+ // recheck for linearizability
+ if (first.prev != null) continue restart;
+ return item;
+ }
+ if ((p = succ(p)) == null)
+ return null;
+ }
}
- return null;
}
public E peekLast() {
- for (Node<E> p = last(); p != null; p = pred(p)) {
- final E item;
- if ((item = p.item) != null)
- return item;
+ restart: for (;;) {
+ for (Node<E> last = last(), p = last;;) {
+ final E item;
+ if ((item = p.item) != null) {
+ // recheck for linearizability
+ if (last.next != null) continue restart;
+ return item;
+ }
+ if ((p = pred(p)) == null)
+ return null;
+ }
}
- return null;
}
/**
@@ -897,27 +910,39 @@
}
public E pollFirst() {
- for (Node<E> p = first(); p != null; p = succ(p)) {
- final E item;
- if ((item = p.item) != null
- && ITEM.compareAndSet(p, item, null)) {
- unlink(p);
- return item;
+ restart: for (;;) {
+ for (Node<E> first = first(), p = first;;) {
+ final E item;
+ if ((item = p.item) != null) {
+ // recheck for linearizability
+ if (first.prev != null) continue restart;
+ if (ITEM.compareAndSet(p, item, null)) {
+ unlink(p);
+ return item;
+ }
+ }
+ if ((p = succ(p)) == null)
+ return null;
}
}
- return null;
}
public E pollLast() {
- for (Node<E> p = last(); p != null; p = pred(p)) {
- final E item;
- if ((item = p.item) != null
- && ITEM.compareAndSet(p, item, null)) {
- unlink(p);
- return item;
+ restart: for (;;) {
+ for (Node<E> last = last(), p = last;;) {
+ final E item;
+ if ((item = p.item) != null) {
+ // recheck for linearizability
+ if (last.next != null) continue restart;
+ if (ITEM.compareAndSet(p, item, null)) {
+ unlink(p);
+ return item;
+ }
+ }
+ if ((p = pred(p)) == null)
+ return null;
}
}
- return null;
}
/**
@@ -1079,14 +1104,14 @@
* @return the number of elements in this deque
*/
public int size() {
- restartFromHead: for (;;) {
+ restart: for (;;) {
int count = 0;
for (Node<E> p = first(); p != null;) {
if (p.item != null)
if (++count == Integer.MAX_VALUE)
break; // @see Collection.size()
if (p == (p = p.next))
- continue restartFromHead;
+ continue restart;
}
return count;
}
@@ -1183,7 +1208,7 @@
public String toString() {
String[] a = null;
- restartFromHead: for (;;) {
+ restart: for (;;) {
int charLength = 0;
int size = 0;
for (Node<E> p = first(); p != null;) {
@@ -1198,7 +1223,7 @@
charLength += s.length();
}
if (p == (p = p.next))
- continue restartFromHead;
+ continue restart;
}
if (size == 0)
@@ -1210,7 +1235,7 @@
private Object[] toArrayInternal(Object[] a) {
Object[] x = a;
- restartFromHead: for (;;) {
+ restart: for (;;) {
int size = 0;
for (Node<E> p = first(); p != null;) {
final E item;
@@ -1222,7 +1247,7 @@
x[size++] = item;
}
if (p == (p = p.next))
- continue restartFromHead;
+ continue restart;
}
if (x == null)
return new Object[0];
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed Oct 18 21:05:09 2017 +0000
@@ -1039,7 +1039,10 @@
*/
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
- // Constants from SplittableRandom
+ /**
+ * The least non-zero value returned by nextDouble(). This value
+ * is scaled by a random value of 53 bits to produce a result.
+ */
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Oct 18 21:05:09 2017 +0000
@@ -140,7 +140,8 @@
* private double x, y;
* private final StampedLock sl = new StampedLock();
*
- * void move(double deltaX, double deltaY) { // an exclusively locked method
+ * // an exclusively locked method
+ * void move(double deltaX, double deltaY) {
* long stamp = sl.writeLock();
* try {
* x += deltaX;
@@ -150,25 +151,57 @@
* }
* }
*
- * double distanceFromOrigin() { // A read-only method
- * double currentX, currentY;
+ * // a read-only method
+ * // upgrade from optimistic read to read lock
+ * double distanceFromOrigin() {
* long stamp = sl.tryOptimisticRead();
- * do {
- * if (stamp == 0L)
- * stamp = sl.readLock();
- * try {
+ * try {
+ * retryHoldingLock: for (;; stamp = sl.readLock()) {
+ * if (stamp == 0L)
+ * continue retryHoldingLock;
* // possibly racy reads
- * currentX = x;
- * currentY = y;
- * } finally {
- * stamp = sl.tryConvertToOptimisticRead(stamp);
+ * double currentX = x;
+ * double currentY = y;
+ * if (!sl.validate(stamp))
+ * continue retryHoldingLock;
+ * return Math.hypot(currentX, currentY);
* }
- * } while (stamp == 0);
- * return Math.hypot(currentX, currentY);
+ * } finally {
+ * if (StampedLock.isReadLockStamp(stamp))
+ * sl.unlockRead(stamp);
+ * }
* }
*
- * void moveIfAtOrigin(double newX, double newY) { // upgrade
- * // Could instead start with optimistic, not read mode
+ * // upgrade from optimistic read to write lock
+ * void moveIfAtOrigin(double newX, double newY) {
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * retryHoldingLock: for (;; stamp = sl.writeLock()) {
+ * if (stamp == 0L)
+ * continue retryHoldingLock;
+ * // possibly racy reads
+ * double currentX = x;
+ * double currentY = y;
+ * if (!sl.validate(stamp))
+ * continue retryHoldingLock;
+ * if (currentX != 0.0 || currentY != 0.0)
+ * break;
+ * stamp = sl.tryConvertToWriteLock(stamp);
+ * if (stamp == 0L)
+ * continue retryHoldingLock;
+ * // exclusive access
+ * x = newX;
+ * y = newY;
+ * return;
+ * }
+ * } finally {
+ * if (StampedLock.isWriteLockStamp(stamp))
+ * sl.unlockWrite(stamp);
+ * }
+ * }
+ *
+ * // Upgrade read lock to write lock
+ * void moveIfAtOrigin(double newX, double newY) {
* long stamp = sl.readLock();
* try {
* while (x == 0.0 && y == 0.0) {
@@ -882,6 +915,92 @@
}
/**
+ * Tells whether a stamp represents holding a lock exclusively.
+ * This method may be useful in conjunction with
+ * {@link #tryConvertToWriteLock}, for example: <pre> {@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToWriteLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isWriteLockStamp(stamp))
+ * sl.unlockWrite(stamp);
+ * }}</pre>
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * write-lock operation
+ * @since 10
+ */
+ public static boolean isWriteLockStamp(long stamp) {
+ return (stamp & ABITS) == WBIT;
+ }
+
+ /**
+ * Tells whether a stamp represents holding a lock non-exclusively.
+ * This method may be useful in conjunction with
+ * {@link #tryConvertToReadLock}, for example: <pre> {@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToReadLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isReadLockStamp(stamp))
+ * sl.unlockRead(stamp);
+ * }}</pre>
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * read-lock operation
+ * @since 10
+ */
+ public static boolean isReadLockStamp(long stamp) {
+ return (stamp & RBITS) != 0L;
+ }
+
+ /**
+ * Tells whether a stamp represents holding a lock.
+ * This method may be useful in conjunction with
+ * {@link #tryConvertToReadLock} and {@link #tryConvertToWriteLock},
+ * for example: <pre> {@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToReadLock(stamp);
+ * ...
+ * stamp = sl.tryConvertToWriteLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isLockStamp(stamp))
+ * sl.unlock(stamp);
+ * }}</pre>
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * read-lock or write-lock operation
+ * @since 10
+ */
+ public static boolean isLockStamp(long stamp) {
+ return (stamp & ABITS) != 0L;
+ }
+
+ /**
+ * Tells whether a stamp represents a successful optimistic read.
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * optimistic read operation, that is, a non-zero return from
+ * {@link #tryOptimisticRead()} or
+ * {@link #tryConvertToOptimisticRead(long)}
+ * @since 10
+ */
+ public static boolean isOptimisticReadStamp(long stamp) {
+ return (stamp & ABITS) == 0L && stamp != 0L;
+ }
+
+ /**
* Queries the number of read locks held for this lock. This
* method is designed for use in monitoring system state, not for
* synchronization control.
--- a/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Oct 18 21:05:09 2017 +0000
@@ -28,9 +28,11 @@
import java.nio.file.attribute.FileTime;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
+import java.util.Date;
import java.util.concurrent.TimeUnit;
import static java.util.zip.ZipConstants.ENDHDR;
@@ -78,31 +80,39 @@
}
/**
+ /*
* Converts DOS time to Java time (number of milliseconds since epoch).
*/
public static long dosToJavaTime(long dtime) {
- int year;
- int month;
- int day;
+ int year = (int) (((dtime >> 25) & 0x7f) + 1980);
+ int month = (int) ((dtime >> 21) & 0x0f);
+ int day = (int) ((dtime >> 16) & 0x1f);
int hour = (int) ((dtime >> 11) & 0x1f);
int minute = (int) ((dtime >> 5) & 0x3f);
int second = (int) ((dtime << 1) & 0x3e);
- if ((dtime >> 16) == 0) {
- // Interpret the 0 DOS date as 1979-11-30 for compatibility with
- // other implementations.
- year = 1979;
- month = 11;
- day = 30;
- } else {
- year = (int) (((dtime >> 25) & 0x7f) + 1980);
- month = (int) ((dtime >> 21) & 0x0f);
- day = (int) ((dtime >> 16) & 0x1f);
+
+ if (month > 0 && month < 13 && day > 0 && hour < 24 && minute < 60 && second < 60) {
+ try {
+ LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
+ return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
+ ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
+ } catch (DateTimeException dte) {
+ // ignore
+ }
}
- LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
- return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
- ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
+ return overflowDosToJavaTime(year, month, day, hour, minute, second);
}
+ /*
+ * Deal with corner cases where an arguably mal-formed DOS time is used
+ */
+ @SuppressWarnings("deprecation") // Use of Date constructor
+ private static long overflowDosToJavaTime(int year, int month, int day,
+ int hour, int minute, int second) {
+ return new Date(year - 1900, month - 1, day, hour, minute, second).getTime();
+ }
+
+
/**
* Converts extended DOS time to Java time, where up to 1999 milliseconds
* might be encoded into the upper half of the returned long.
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Wed Oct 18 21:05:09 2017 +0000
@@ -27,6 +27,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.lang.ref.Cleaner.Cleanable;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.ClosedByInterruptException;
@@ -47,6 +48,7 @@
import jdk.internal.misc.JavaNioAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.ref.Cleaner;
+import jdk.internal.ref.CleanerFactory;
import sun.security.action.GetPropertyAction;
public class FileChannelImpl
@@ -55,7 +57,7 @@
// Memory allocation size for mapping buffers
private static final long allocationGranularity;
- // Access to FileDispatcher internals
+ // Access to FileDescriptor internals
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
@@ -85,6 +87,21 @@
// Positional-read is not interruptible
private volatile boolean uninterruptible;
+ // Cleanable with an action which closes this channel's file descriptor
+ private final Cleanable closer;
+
+ private static class Closer implements Runnable {
+ private final FileDescriptor fd;
+
+ Closer(FileDescriptor fd) {
+ this.fd = fd;
+ }
+
+ public void run() {
+ fdAccess.close(fd);
+ }
+ }
+
private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
boolean writable, Object parent)
{
@@ -94,6 +111,12 @@
this.parent = parent;
this.path = path;
this.nd = new FileDispatcherImpl();
+ // Register a cleaning action if and only if there is no parent
+ // as the parent will take care of closing the file descriptor.
+ // FileChannel is used by the LambdaMetaFactory so a lambda cannot
+ // be used here hence we use a nested class instead.
+ this.closer = parent != null ? null :
+ CleanerFactory.cleaner().register(this, new Closer(fd));
}
// Used by FileInputStream.getChannel(), FileOutputStream.getChannel
@@ -143,6 +166,10 @@
// that method will prevent this method from being reinvoked.
//
((java.io.Closeable)parent).close();
+ } else if (closer != null) {
+ // Perform the cleaning action so it is not redone when
+ // this channel becomes phantom reachable.
+ closer.clean();
} else {
fdAccess.close(fd);
}
@@ -1237,5 +1264,4 @@
IOUtil.load();
allocationGranularity = initIDs();
}
-
}
--- a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Wed Oct 18 21:05:09 2017 +0000
@@ -26,6 +26,7 @@
package sun.util.cldr;
import java.security.AccessController;
+import java.security.AccessControlException;
import java.security.PrivilegedExceptionAction;
import java.text.spi.BreakIteratorProvider;
import java.text.spi.CollatorProvider;
@@ -37,6 +38,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
+import java.util.ServiceConfigurationError;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
@@ -81,8 +83,11 @@
return null;
}
});
- } catch (Exception e) {
+ } catch (Exception e) {
// Catch any exception, and continue as if only CLDR's base locales exist.
+ } catch (ServiceConfigurationError sce) {
+ Throwable cause = sce.getCause();
+ if (!(cause instanceof AccessControlException)) throw sce;
}
nonBaseMetaInfo = nbmi;
--- a/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Oct 18 21:05:09 2017 +0000
@@ -26,6 +26,7 @@
package sun.util.locale.provider;
import java.security.AccessController;
+import java.security.AccessControlException;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.text.spi.BreakIteratorProvider;
@@ -40,6 +41,7 @@
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.ServiceLoader;
+import java.util.ServiceConfigurationError;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
@@ -476,8 +478,11 @@
if (nonBaseTags != null) {
supportedLocaleString += " " + nonBaseTags;
}
- } catch (Exception e) {
+ } catch (Exception e) {
// catch any exception, and ignore them as if non-EN locales do not exist.
+ } catch (ServiceConfigurationError sce) {
+ Throwable cause = sce.getCause();
+ if (!(cause instanceof AccessControlException)) throw sce;
}
return supportedLocaleString;
--- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Wed Oct 18 13:52:32 2017 -0700
+++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,6 +79,7 @@
strlen("IP Helper Library GetAdaptersAddresses function failed"
" with error == ") + 10;
int _ret = 0;
+ int try;
adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);
@@ -94,7 +95,7 @@
flags |= GAA_FLAG_INCLUDE_PREFIX;
ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
- for (int try = 0; ret == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {
+ for (try = 0; ret == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {
IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;
if (len < (ULONG_MAX - BUFF_SIZE)) {
len += BUFF_SIZE;
@@ -160,6 +161,7 @@
size_t error_msg_buf_size =
strlen("IP Helper Library GetAdaptersAddresses function failed with error == ") + 10;
int _ret = 0;
+ int try;
adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);
if (adapterInfo == NULL) {
JNU_ThrowByName(env, "java/lang/OutOfMemoryError",
@@ -171,7 +173,7 @@
flags |= GAA_FLAG_SKIP_MULTICAST;
flags |= GAA_FLAG_INCLUDE_PREFIX;
val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
- for (int try = 0; val == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {
+ for (try = 0; val == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {
IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;
if (len < (ULONG_MAX - BUFF_SIZE)) {
len += BUFF_SIZE;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Oct 18 21:05:09 2017 +0000
@@ -1174,6 +1174,9 @@
v.type = chk.checkLocalVarType(tree, tree.init.type.baseType(), tree.name);
}
}
+ if (tree.isImplicitlyTyped()) {
+ setSyntheticVariableType(tree, v.type);
+ }
}
result = tree.type = v.type;
}
@@ -1348,11 +1351,7 @@
}
if (tree.var.isImplicitlyTyped()) {
Type inferredType = chk.checkLocalVarType(tree.var, elemtype, tree.var.name);
- if (inferredType.isErroneous()) {
- tree.var.vartype = make.at(tree.var.vartype).Erroneous();
- } else {
- tree.var.vartype = make.at(tree.var.vartype).Type(inferredType);
- }
+ setSyntheticVariableType(tree.var, inferredType);
}
attribStat(tree.var, loopEnv);
chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
@@ -2559,7 +2558,7 @@
Type argType = arityMismatch ?
syms.errType :
actuals.head;
- params.head.vartype = make.at(params.head).Type(argType);
+ setSyntheticVariableType(params.head, argType);
params.head.sym = null;
actuals = actuals.isEmpty() ?
actuals :
@@ -4831,6 +4830,14 @@
return types.capture(type);
}
+ private void setSyntheticVariableType(JCVariableDecl tree, Type type) {
+ if (type.isErroneous()) {
+ tree.vartype = make.at(Position.NOPOS).Erroneous();
+ } else {
+ tree.vartype = make.at(Position.NOPOS).Type(type);
+ }
+ }
+
public void validateTypeAnnotations(JCTree tree, boolean sigOnly) {
tree.accept(new TypeAnnotationsValidator(sigOnly));
}
@@ -5152,7 +5159,7 @@
that.sym.adr = 0;
}
if (that.vartype == null) {
- that.vartype = make.Erroneous();
+ that.vartype = make.at(Position.NOPOS).Erroneous();
}
super.visitVarDef(that);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Oct 18 21:05:09 2017 +0000
@@ -56,6 +56,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -2096,9 +2097,12 @@
}
break;
case CAPTURED_OUTER_THIS:
- if (lambdaIdent.sym.owner.kind == TYP && m.containsKey(lambdaIdent.sym.owner)) {
+ Optional<Symbol> proxy = m.keySet().stream()
+ .filter(out -> lambdaIdent.sym.isMemberOf(out.type.tsym, types))
+ .reduce((a, b) -> a.isEnclosedBy((ClassSymbol)b) ? a : b);
+ if (proxy.isPresent()) {
// Transform outer instance variable references anchoring them to the captured synthetic.
- Symbol tSym = m.get(lambdaIdent.sym.owner);
+ Symbol tSym = m.get(proxy.get());
JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type);
t = make.Select(t, lambdaIdent.name);
t.setType(lambdaIdent.type);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Oct 18 21:05:09 2017 +0000
@@ -308,8 +308,8 @@
void visitSymbol(Symbol _sym) {
Symbol sym = _sym;
if (sym.kind == VAR || sym.kind == MTH) {
- while (sym != null && sym.owner != owner)
- sym = proxies.findFirst(proxyName(sym.name));
+ if (sym != null && sym.owner != owner)
+ sym = proxies.get(sym);
if (sym != null && sym.owner == owner) {
VarSymbol v = (VarSymbol)sym;
if (v.getConstValue() == null) {
@@ -1084,7 +1084,7 @@
return makeLit(sym.type, cv);
}
// Otherwise replace the variable by its proxy.
- sym = proxies.findFirst(proxyName(sym.name));
+ sym = proxies.get(sym);
Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
tree = make.at(tree.pos).Ident(sym);
}
@@ -1359,14 +1359,12 @@
* Free variables proxies and this$n
*************************************************************************/
- /** A scope containing all free variable proxies for currently translated
- * class, as well as its this$n symbol (if needed).
- * Proxy scopes are nested in the same way classes are.
- * Inside a constructor, proxies and any this$n symbol are duplicated
- * in an additional innermost scope, where they represent the constructor
- * parameters.
+ /** A map which allows to retrieve the translated proxy variable for any given symbol of an
+ * enclosing scope that is accessed (the accessed symbol could be the synthetic 'this$n' symbol).
+ * Inside a constructor, the map temporarily overrides entries corresponding to proxies and any
+ * 'this$n' symbols, where they represent the constructor parameters.
*/
- WriteableScope proxies;
+ Map<Symbol, Symbol> proxies;
/** A scope containing all unnamed resource variables/saved
* exception variables for translated TWR blocks
@@ -1383,8 +1381,12 @@
/** The name of a free variable proxy.
*/
- Name proxyName(Name name) {
- return names.fromString("val" + target.syntheticNameChar() + name);
+ Name proxyName(Name name, int index) {
+ Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
+ if (index > 0) {
+ proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
+ }
+ return proxyName;
}
/** Proxy definitions for all free variables in given list, in reverse order.
@@ -1400,11 +1402,17 @@
long additionalFlags) {
long flags = FINAL | SYNTHETIC | additionalFlags;
List<JCVariableDecl> defs = List.nil();
+ Set<Name> proxyNames = new HashSet<>();
for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
VarSymbol v = l.head;
+ int index = 0;
+ Name proxyName;
+ do {
+ proxyName = proxyName(v.name, index++);
+ } while (!proxyNames.add(proxyName));
VarSymbol proxy = new VarSymbol(
- flags, proxyName(v.name), v.erasure(types), owner);
- proxies.enter(proxy);
+ flags, proxyName, v.erasure(types), owner);
+ proxies.put(v, proxy);
JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
vd.vartype = access(vd.vartype);
defs = defs.prepend(vd);
@@ -1843,11 +1851,8 @@
/** Return tree simulating the assignment {@code this.name = name}, where
* name is the name of a free variable.
*/
- JCStatement initField(int pos, Name name) {
- Iterator<Symbol> it = proxies.getSymbolsByName(name).iterator();
- Symbol rhs = it.next();
+ JCStatement initField(int pos, Symbol rhs, Symbol lhs) {
Assert.check(rhs.owner.kind == MTH);
- Symbol lhs = it.next();
Assert.check(rhs.owner.owner == lhs.owner);
make.at(pos);
return
@@ -2207,7 +2212,8 @@
classdefs.put(currentClass, tree);
- proxies = proxies.dup(currentClass);
+ Map<Symbol, Symbol> prevProxies = proxies;
+ proxies = new HashMap<>(proxies);
List<VarSymbol> prevOuterThisStack = outerThisStack;
// If this is an enum definition
@@ -2270,7 +2276,7 @@
enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
}
- proxies = proxies.leave();
+ proxies = prevProxies;
outerThisStack = prevOuterThisStack;
// Append translated tree to `translated' queue.
@@ -2488,7 +2494,8 @@
// Push a new proxy scope for constructor parameters.
// and create definitions for any this$n and proxy parameters.
- proxies = proxies.dup(m);
+ Map<Symbol, Symbol> prevProxies = proxies;
+ proxies = new HashMap<>(proxies);
List<VarSymbol> prevOuterThisStack = outerThisStack;
List<VarSymbol> fvs = freevars(currentClass);
JCVariableDecl otdef = null;
@@ -2523,13 +2530,12 @@
if (fvs.nonEmpty()) {
List<Type> addedargtypes = List.nil();
for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
- final Name pName = proxyName(l.head.name);
m.capturedLocals =
m.capturedLocals.prepend((VarSymbol)
- (proxies.findFirst(pName)));
+ (proxies.get(l.head)));
if (TreeInfo.isInitialConstructor(tree)) {
added = added.prepend(
- initField(tree.body.pos, pName));
+ initField(tree.body.pos, proxies.get(l.head), prevProxies.get(l.head)));
}
addedargtypes = addedargtypes.prepend(l.head.erasure(types));
}
@@ -2547,7 +2553,7 @@
}
// pop local variables from proxy stack
- proxies = proxies.leave();
+ proxies = prevProxies;
// recursively translate following local statements and
// combine with this- or super-call
@@ -3714,7 +3720,7 @@
classdefs = new HashMap<>();
actualSymbols = new HashMap<>();
freevarCache = new HashMap<>();
- proxies = WriteableScope.create(syms.noSymbol);
+ proxies = new HashMap<>();
twrVars = WriteableScope.create(syms.noSymbol);
outerThisStack = List.nil();
accessNums = new HashMap<>();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Oct 18 21:05:09 2017 +0000
@@ -3063,6 +3063,7 @@
}
else if (reqInit) syntaxError(token.pos, "expected", EQ);
JCTree elemType = TreeInfo.innermostType(type, true);
+ int startPos = Position.NOPOS;
if (allowLocalVariableTypeInference && elemType.hasTag(IDENT)) {
Name typeName = ((JCIdent)elemType).name;
if (isRestrictedLocalVarTypeName(typeName)) {
@@ -3070,6 +3071,9 @@
//error - 'var' and arrays
reportSyntaxError(pos, "var.not.allowed.array");
} else {
+ startPos = TreeInfo.getStartPos(mods);
+ if (startPos == Position.NOPOS)
+ startPos = TreeInfo.getStartPos(type);
//implicit type
type = null;
}
@@ -3078,6 +3082,7 @@
JCVariableDecl result =
toP(F.at(pos).VarDef(mods, name, type, init));
attach(result, dc);
+ result.startPos = startPos;
return result;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Oct 18 21:05:09 2017 +0000
@@ -920,6 +920,8 @@
public JCExpression init;
/** symbol */
public VarSymbol sym;
+ /** explicit start pos */
+ public int startPos = Position.NOPOS;
protected JCVariableDecl(JCModifiers mods,
Name name,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Oct 18 21:05:09 2017 +0000
@@ -457,9 +457,11 @@
}
case VARDEF: {
JCVariableDecl node = (JCVariableDecl)tree;
- if (node.mods.pos != Position.NOPOS) {
+ if (node.startPos != Position.NOPOS) {
+ return node.startPos;
+ } else if (node.mods.pos != Position.NOPOS) {
return node.mods.pos;
- } else if (node.vartype == null) {
+ } else if (node.vartype == null || node.vartype.pos == Position.NOPOS) {
//if there's no type (partially typed lambda parameter)
//simply return node position
return node.pos;
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m Wed Oct 18 21:05:09 2017 +0000
@@ -689,8 +689,15 @@
// attach to a process/thread specified by "pid"
static bool ptrace_attach(pid_t pid) {
int res;
- if ((res = ptrace(PT_ATTACHEXC, pid, 0, 0)) < 0) {
- print_error("ptrace(PT_ATTACHEXC, %d) failed with %d\n", pid, res);
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) {
+ print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
return false;
} else {
return ptrace_waitpid(pid);
--- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py Wed Oct 18 21:05:09 2017 +0000
@@ -6,7 +6,7 @@
# This puts mx/ as a sibling of the JDK build configuration directories
# (e.g., macosx-x86_64-normal-server-release).
- "outputRoot" : "../../../build/mx/hotspot",
+ "outputRoot" : "../../build/mx/hotspot",
"jdklibraries" : {
"JVMCI_SERVICES" : {
@@ -1093,7 +1093,7 @@
},
"jdk.tools.jaotc.test" : {
- "subDir" : "../../test/compiler/aot",
+ "subDir" : "../../test/hotspot/jtreg/compiler/aot",
"sourceDirs" : ["src"],
"dependencies" : [
"mx:JUNIT",
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java Wed Oct 18 21:05:09 2017 +0000
@@ -313,7 +313,8 @@
* @return the 1.4.x style anchor for the executable element.
*/
protected String getErasureAnchor(ExecutableElement executableElement) {
- final StringBuilder buf = new StringBuilder(name(executableElement) + "(");
+ final StringBuilder buf = new StringBuilder(writer.anchorName(executableElement));
+ buf.append("(");
List<? extends VariableElement> parameters = executableElement.getParameters();
boolean foundTypeVariable = false;
for (int i = 0; i < parameters.size(); i++) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Wed Oct 18 21:05:09 2017 +0000
@@ -25,11 +25,15 @@
package jdk.javadoc.internal.doclets.formats.html;
+import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
+import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
@@ -110,15 +114,41 @@
body.addContent(frame);
}
if (configuration.windowtitle.length() > 0) {
- printFramesDocument(configuration.windowtitle, configuration,
- body);
+ printFramesDocument(configuration.windowtitle, body);
} else {
- printFramesDocument(configuration.getText("doclet.Generated_Docs_Untitled"),
- configuration, body);
+ printFramesDocument(configuration.getText("doclet.Generated_Docs_Untitled"), body);
}
}
/**
+ * Print the frames version of the Html file header.
+ * Called only when generating an HTML frames file.
+ *
+ * @param title Title of this HTML document
+ * @param body the body content tree to be added to the HTML document
+ * @throws DocFileIOException if there is an error writing the frames document
+ */
+ private void printFramesDocument(String title, HtmlTree body) throws DocFileIOException {
+ Content htmlDocType = configuration.isOutputHtml5()
+ ? DocType.HTML5
+ : DocType.TRANSITIONAL;
+ Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
+ Content head = new HtmlTree(HtmlTag.HEAD);
+ head.addContent(getGeneratedBy(!configuration.notimestamp));
+ Content windowTitle = HtmlTree.TITLE(new StringContent(title));
+ head.addContent(windowTitle);
+ Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
+ head.addContent(meta);
+ head.addContent(getStyleSheetProperties(configuration));
+ head.addContent(getFramesJavaScript());
+ Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
+ head, body);
+ Content htmlDocument = new HtmlDocument(htmlDocType,
+ htmlComment, htmlTree);
+ write(htmlDocument);
+ }
+
+ /**
* Get the frame sizes and their contents.
*
* @return a content tree for the frame details
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Wed Oct 18 21:05:09 2017 +0000
@@ -33,6 +33,7 @@
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.Name;
@@ -74,6 +75,7 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
@@ -1468,20 +1470,18 @@
if (isProperty) {
return executableElement.getSimpleName().toString();
}
- String signature = utils.signature(executableElement);
- StringBuilder signatureParsed = new StringBuilder();
- int counter = 0;
- for (int i = 0; i < signature.length(); i++) {
- char c = signature.charAt(i);
- if (c == '<') {
- counter++;
- } else if (c == '>') {
- counter--;
- } else if (counter == 0) {
- signatureParsed.append(c);
- }
+ String member = anchorName(executableElement);
+ String erasedSignature = utils.makeSignature(executableElement, true, true);
+ return member + erasedSignature;
+ }
+
+ public String anchorName(Element member) {
+ if (member.getKind() == ElementKind.CONSTRUCTOR
+ && configuration.isOutputHtml5()) {
+ return "<init>";
+ } else {
+ return utils.getSimpleName(member);
}
- return utils.getSimpleName(executableElement) + signatureParsed.toString();
}
public Content seeTagToContent(Element element, DocTree see) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Wed Oct 18 21:05:09 2017 +0000
@@ -37,7 +37,6 @@
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
@@ -60,7 +59,8 @@
public static final String CONTENT_TYPE = "text/html";
- DocPath pathToRoot;
+ private final HtmlConfiguration configuration;
+ private final DocPath pathToRoot;
/**
* Constructor. Initializes the destination file name through the super
@@ -69,8 +69,9 @@
* @param configuration the configuration for this doclet
* @param filename String file name.
*/
- public HtmlDocWriter(BaseConfiguration configuration, DocPath filename) {
+ public HtmlDocWriter(HtmlConfiguration configuration, DocPath filename) {
super(configuration, filename);
+ this.configuration = configuration;
this.pathToRoot = filename.parent().invert();
Messages messages = configuration.getMessages();
messages.notice("doclet.Generating_0",
@@ -81,7 +82,9 @@
* Accessor for configuration.
* @return the configuration for this doclet
*/
- public abstract BaseConfiguration configuration();
+ public BaseConfiguration configuration() {
+ return configuration;
+ }
public Content getHyperLink(DocPath link, String label) {
return getHyperLink(link, new StringContent(label), false, "", "", "");
@@ -167,8 +170,6 @@
* @return a valid HTML name string.
*/
public String getName(String name) {
- StringBuilder sb = new StringBuilder();
- char ch;
/* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions
* that the name/id should begin with a letter followed by other valid characters.
* The HTML 5 spec (draft) is more permissive on names/ids where the only restriction
@@ -179,8 +180,14 @@
* substitute it accordingly, "_" and "$" can appear at the beginning of a member name.
* The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z".
*/
+
+ if (configuration.isOutputHtml5()) {
+ return name.replaceAll(" +", "");
+ }
+
+ StringBuilder sb = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
- ch = name.charAt(i);
+ char ch = name.charAt(i);
switch (ch) {
case '(':
case ')':
@@ -310,36 +317,6 @@
}
/**
- * Print the frames version of the Html file header.
- * Called only when generating an HTML frames file.
- *
- * @param title Title of this HTML document
- * @param configuration the configuration object
- * @param body the body content tree to be added to the HTML document
- * @throws DocFileIOException if there is an error writing the frames document
- */
- public void printFramesDocument(String title, HtmlConfiguration configuration,
- HtmlTree body) throws DocFileIOException {
- Content htmlDocType = configuration.isOutputHtml5()
- ? DocType.HTML5
- : DocType.TRANSITIONAL;
- Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
- Content head = new HtmlTree(HtmlTag.HEAD);
- head.addContent(getGeneratedBy(!configuration.notimestamp));
- Content windowTitle = HtmlTree.TITLE(new StringContent(title));
- head.addContent(windowTitle);
- Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
- head.addContent(meta);
- head.addContent(getStyleSheetProperties(configuration));
- head.addContent(getFramesJavaScript());
- Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
- head, body);
- Content htmlDocument = new HtmlDocument(htmlDocType,
- htmlComment, htmlTree);
- write(htmlDocument);
- }
-
- /**
* Returns a link to the stylesheet file.
*
* @param configuration the configuration for this doclet
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Wed Oct 18 21:05:09 2017 +0000
@@ -181,36 +181,63 @@
return s;
}
- /**
- * A set of ASCII URI characters to be left unencoded.
+ /*
+ * The sets of ASCII URI characters to be left unencoded.
+ * See "Uniform Resource Identifier (URI): Generic Syntax"
+ * IETF RFC 3986. https://tools.ietf.org/html/rfc3986
*/
- public static final BitSet NONENCODING_CHARS = new BitSet(256);
+ public static final BitSet MAIN_CHARS;
+ public static final BitSet QUERY_FRAGMENT_CHARS;
static {
- // alphabetic characters
- for (int i = 'a'; i <= 'z'; i++) {
- NONENCODING_CHARS.set(i);
- }
- for (int i = 'A'; i <= 'Z'; i++) {
- NONENCODING_CHARS.set(i);
+ BitSet alphaDigit = bitSet(bitSet('A', 'Z'), bitSet('a', 'z'), bitSet('0', '9'));
+ BitSet unreserved = bitSet(alphaDigit, bitSet("-._~"));
+ BitSet genDelims = bitSet(":/?#[]@");
+ BitSet subDelims = bitSet("!$&'()*+,;=");
+ MAIN_CHARS = bitSet(unreserved, genDelims, subDelims);
+ BitSet pchar = bitSet(unreserved, subDelims, bitSet(":@"));
+ QUERY_FRAGMENT_CHARS = bitSet(pchar, bitSet("/?"));
+ }
+
+ private static BitSet bitSet(String s) {
+ BitSet result = new BitSet();
+ for (int i = 0; i < s.length(); i++) {
+ result.set(s.charAt(i));
}
- // numeric characters
- for (int i = '0'; i <= '9'; i++) {
- NONENCODING_CHARS.set(i);
- }
- // Reserved characters as per RFC 3986. These are set of delimiting characters.
- String noEnc = ":/?#[]@!$&'()*+,;=";
- // Unreserved characters as per RFC 3986 which should not be percent encoded.
- noEnc += "-._~";
- for (int i = 0; i < noEnc.length(); i++) {
- NONENCODING_CHARS.set(noEnc.charAt(i));
- }
+ return result;
+ }
+
+ private static BitSet bitSet(char from, char to) {
+ BitSet result = new BitSet();
+ result.set(from, to + 1);
+ return result;
}
+ private static BitSet bitSet(BitSet... sets) {
+ BitSet result = new BitSet();
+ for (BitSet set : sets) {
+ result.or(set);
+ }
+ return result;
+ }
+
+ /**
+ * Apply percent-encoding to a URL.
+ * This is similar to {@link java.net.URLEncoder} but
+ * is less aggressive about encoding some characters,
+ * like '(', ')', ',' which are used in the anchor
+ * names for Java methods in HTML5 mode.
+ */
private static String encodeURL(String url) {
+ BitSet nonEncodingChars = MAIN_CHARS;
StringBuilder sb = new StringBuilder();
for (byte c : url.getBytes(Charset.forName("UTF-8"))) {
- if (NONENCODING_CHARS.get(c & 0xFF)) {
+ if (c == '?' || c == '#') {
+ sb.append((char) c);
+ // switch to the more restrictive set inside
+ // the query and/or fragment
+ nonEncodingChars = QUERY_FRAGMENT_CHARS;
+ } else if (nonEncodingChars.get(c & 0xFF)) {
sb.append((char) c);
} else {
sb.append(String.format("%%%02X", c & 0xFF));
--- a/src/jdk.jlink/share/classes/module-info.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.jlink/share/classes/module-info.java Wed Oct 18 21:05:09 2017 +0000
@@ -38,14 +38,13 @@
* or the {@link java.util.ServiceLoader service loader} with the name
* {@code "jlink"} or {@code "jmod"} as appropriate.
*
- * <p> <em>{@extLink jimage_tool_reference jimage}</em> only exists
+ * <p> <em>jimage</em> only exists
* as a command-line tool, and does not provide any direct API.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>{@extLink jlink_tool_reference jlink},
- * {@extLink jmod_tool_reference jmod},
- * {@extLink jimage_tool_reference jimage}
+ * {@extLink jmod_tool_reference jmod}
* </dl>
*
* @provides java.util.spi.ToolProvider
--- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Oct 18 21:05:09 2017 +0000
@@ -295,6 +295,10 @@
Range rtype = dis.treeToRange(baseType);
typeWrap = Wrap.rangeWrap(compileSource, rtype);
} else {
+ AnalyzeTask at = trialCompile(Wrap.methodWrap(compileSource));
+ if (at.hasErrors()) {
+ return compileFailResult(at, userSource, kindOfTree(unitTree));
+ }
Tree init = vt.getInitializer();
if (init != null) {
Range rinit = dis.treeToRange(init);
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java Wed Oct 18 21:05:09 2017 +0000
@@ -477,4 +477,14 @@
public IdentNode setIsDestructuredParameter() {
return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion);
}
+
+ /**
+ * Checks whether the source code for this ident contains a unicode escape sequence by comparing
+ * the length of its name with its length in source code.
+ *
+ * @return true if ident source contains a unicode escape sequence
+ */
+ public boolean containsEscapes() {
+ return Token.descLength(getToken()) != name.length();
+ }
}
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Oct 18 21:05:09 2017 +0000
@@ -786,15 +786,9 @@
if (ch0 == '\\' && ch1 == 'u') {
skip(2);
final int ch = hexSequence(4, TokenType.IDENT);
- if (isWhitespace((char)ch)) {
- return null;
- }
- if (ch < 0) {
- sb.append('\\');
- sb.append('u');
- } else {
- sb.append((char)ch);
- }
+ assert ! isWhitespace((char)ch);
+ assert ch >= 0;
+ sb.append((char)ch);
} else {
// Add regular character.
sb.append(ch0);
@@ -994,9 +988,6 @@
if (ch0 == '\\') {
type = ESCSTRING;
skip(1);
- if (! isEscapeCharacter(ch0)) {
- error(Lexer.message("invalid.escape.char"), STRING, position, limit);
- }
if (isEOL(ch0)) {
// Multiline string literal
skipEOL(false);
@@ -1093,9 +1084,6 @@
} else if (ch0 == '\\') {
skip(1);
// EscapeSequence
- if (!isEscapeCharacter(ch0)) {
- error(Lexer.message("invalid.escape.char"), TEMPLATE, position, limit);
- }
if (isEOL(ch0)) {
// LineContinuation
skipEOL(false);
@@ -1115,16 +1103,6 @@
}
/**
- * Is the given character a valid escape char after "\" ?
- *
- * @param ch character to be checked
- * @return if the given character is valid after "\"
- */
- protected boolean isEscapeCharacter(final char ch) {
- return true;
- }
-
- /**
* Convert string to number.
*
* @param valueString String to convert.
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Oct 18 21:05:09 2017 +0000
@@ -1472,12 +1472,7 @@
*/
private void verifyIdent(final IdentNode ident, final String contextString) {
verifyStrictIdent(ident, contextString);
- if (isES6()) {
- final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
- if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
- throw error(expectMessage(IDENT));
- }
- }
+ checkEscapedKeyword(ident);
}
/**
@@ -1502,6 +1497,18 @@
}
}
+ /**
+ * ES6 11.6.2: A code point in a ReservedWord cannot be expressed by a | UnicodeEscapeSequence.
+ */
+ private void checkEscapedKeyword(final IdentNode ident) {
+ if (isES6() && ident.containsEscapes()) {
+ final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
+ if (tokenType != IDENT && !(tokenType.getKind() == TokenKind.FUTURESTRICT && !isStrictMode)) {
+ throw error(AbstractParser.message("keyword.escaped.character"), ident.getToken());
+ }
+ }
+ }
+
/*
* VariableStatement :
* var VariableDeclarationList ;
@@ -2646,7 +2653,7 @@
});
} else {
// ECMA 12.4.1 strict mode restrictions
- verifyStrictIdent((IdentNode) exception, "catch argument");
+ verifyIdent((IdentNode) exception, "catch argument");
}
@@ -2761,6 +2768,7 @@
break;
}
detectSpecialProperty(ident);
+ checkEscapedKeyword(ident);
return ident;
case OCTAL_LEGACY:
if (isStrictMode) {
@@ -3404,6 +3412,7 @@
// Catch special functions.
if (lhs instanceof IdentNode) {
detectSpecialFunction((IdentNode)lhs);
+ checkEscapedKeyword((IdentNode)lhs);
}
lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
@@ -3779,7 +3788,7 @@
expect(IDENT);
}
name = getIdent();
- verifyStrictIdent(name, "function name");
+ verifyIdent(name, "function name");
} else if (isStatement) {
// Nashorn extension: anonymous function statements.
// Do not allow anonymous function statement if extensions
@@ -4871,7 +4880,7 @@
final String contextString = "function parameter";
if (param instanceof IdentNode) {
final IdentNode ident = (IdentNode)param;
- verifyStrictIdent(ident, contextString);
+ verifyIdent(ident, contextString);
final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
if (currentFunction != null) {
currentFunction.addParameterBinding(ident);
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Oct 18 21:05:09 2017 +0000
@@ -62,6 +62,7 @@
parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON
parser.error.missing.const.assignment=Missing assignment to constant "{0}"
parser.error.unterminated.template.expression=Expected } after expression in template literal
+parser.error.keyword.escaped.character=Keyword must not contain escaped characters
# ES6 mode error messages
parser.error.multiple.constructors=Class contains more than one constructor
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java Wed Oct 18 13:52:32 2017 -0700
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java Wed Oct 18 21:05:09 2017 +0000
@@ -27,10 +27,12 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
+import java.util.Date;
import java.util.regex.PatternSyntaxException;
import java.util.concurrent.TimeUnit;
@@ -106,26 +108,32 @@
* Converts DOS time to Java time (number of milliseconds since epoch).
*/
public static long dosToJavaTime(long dtime) {
- int year;
- int month;
- int day;
+ int year = (int) (((dtime >> 25) & 0x7f) + 1980);
+ int month = (int) ((dtime >> 21) & 0x0f);
+ int day = (int) ((dtime >> 16) & 0x1f);
int hour = (int) ((dtime >> 11) & 0x1f);
int minute = (int) ((dtime >> 5) & 0x3f);
int second = (int) ((dtime << 1) & 0x3e);
- if ((dtime >> 16) == 0) {
- // Interpret the 0 DOS date as 1979-11-30 for compatibility with
- // other implementations.
- year = 1979;
- month = 11;
- day = 30;
- } else {
- year = (int) (((dtime >> 25) & 0x7f) + 1980);
- month = (int) ((dtime >> 21) & 0x0f);
- day = (int) ((dtime >> 16) & 0x1f);
+
+ if (month > 0 && month < 13 && day > 0 && hour < 24 && minute < 60 && second < 60) {
+ try {
+ LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
+ return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
+ ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
+ } catch (DateTimeException dte) {
+ // ignore
+ }
}
- LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
- return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
- ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
+ return overflowDosToJavaTime(year, month, day, hour, minute, second);
+ }
+
+ /*
+ * Deal with corner cases where an arguably mal-formed DOS time is used
+ */
+ @SuppressWarnings("deprecation") // Use of Date constructor
+ private static long overflowDosToJavaTime(int year, int month, int day,
+ int hour, int minute, int second) {
+ return new Date(year - 1900, month - 1, day, hour, minute, second).getTime();
}
/*
--- a/test/TestCommon.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/test/TestCommon.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -360,6 +360,9 @@
JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
endif
+# Make it possible to specify the JIB_DATA_DIR for tests using the
+# JIB Artifact resolver
+JTREG_BASIC_OPTIONS += -e:JIB_DATA_DIR
# Give tests access to JT_JAVA, see JDK-8141609
JTREG_BASIC_OPTIONS += -e:JDK8_HOME=${JT_JAVA}
# Give aot tests access to Visual Studio installation
--- a/test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh Wed Oct 18 13:52:32 2017 -0700
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh Wed Oct 18 21:05:09 2017 +0000
@@ -108,7 +108,7 @@
done
NAME="jvmci"
-DIR="$DIR/../../../../src/jdk.internal.vm.ci"
+DIR="$DIR/../../../../../../src/jdk.internal.vm.ci"
FILES=`find $DIR -type f -name '*.java'`
COUNT=`find $DIR -type f -name '*.java' | wc -l`
--- a/test/hotspot/jtreg/compiler/loopopts/TestMoveStoresOutOfLoops.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/hotspot/jtreg/compiler/loopopts/TestMoveStoresOutOfLoops.java Wed Oct 18 21:05:09 2017 +0000
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8080289
+ * @bug 8080289 8189067
* @summary Move stores out of loops if possible
*
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation
@@ -43,6 +43,7 @@
private static long[] array = new long[10];
private static long[] array2 = new long[10];
private static boolean[] array3 = new boolean[1000];
+ private static int[] array4 = new int[1000];
private static byte[] byte_array = new byte[10];
// Array store should be moved out of the loop, value stored
@@ -108,6 +109,15 @@
}
}
+ // Array store can be moved out of the inner loop
+ static void test_after_7(int idx) {
+ for (int i = 0; i < 1000; i++) {
+ for (int j = 0; j <= 42; j++) {
+ array4[i] = j;
+ }
+ }
+ }
+
// Optimize out redundant stores
static void test_stores_1(int ignored) {
array[0] = 0;
@@ -285,6 +295,17 @@
return success;
}
+ static boolean array_check5(String name) {
+ boolean success = true;
+ for (int i = 0; i < 1000; i++) {
+ if (array4[i] != 42) {
+ success = false;
+ System.out.println(name + " failed: array[" + i + "] = " + array4[i]);
+ }
+ }
+ return success;
+ }
+
static public void main(String[] args) throws Exception {
TestMoveStoresOutOfLoops test = new TestMoveStoresOutOfLoops();
test.doTest("test_after_1", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check);
@@ -295,6 +316,7 @@
test.doTest("test_after_6", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check);
array3[999] = true;
test.doTest("test_after_6", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check);
+ test.doTest("test_after_7", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check5);
test.doTest("test_stores_1", TestMoveStoresOutOfLoops::array_init3, TestMoveStoresOutOfLoops::array_check3);
test.doTest("test_stores_2", TestMoveStoresOutOfLoops::array_init3, TestMoveStoresOutOfLoops::array_check3);
--- a/test/hotspot/jtreg/runtime/getSysPackage/GetSysPkgTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/hotspot/jtreg/runtime/getSysPackage/GetSysPkgTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -25,7 +25,7 @@
* @test
* @modules java.base/jdk.internal.misc
* @modules java.base/jdk.internal.loader
- * java.desktop
+ * java.logging
* @library /test/lib
* @run main/othervm GetSysPkgTest
*/
@@ -134,10 +134,11 @@
getPkg("GetSysPkg_package", null);
// Access a class with a package in a boot loader module other than java.base
- clss = Class.forName("java.awt.Button");
+ clss = Class.forName("java.util.logging.Level");
+
if (clss == null)
- throw new RuntimeException("Could not find class java.awt.Button");
- getPkg("java/awt", "jrt:/java.desktop");
+ throw new RuntimeException("Could not find class java.util.logging.Level");
+ getPkg("java/util/logging", "jrt:/java.logging");
// Test getting the package location from a class found via -Xbootclasspath/a
clss = Class.forName("BootLdr_package.BootLdrPkg");
--- a/test/jdk/ProblemList.txt Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/ProblemList.txt Wed Oct 18 21:05:09 2017 +0000
@@ -301,14 +301,6 @@
com/sun/tools/attach/StartManagementAgent.java 8179700 generic-all
-sun/tools/jhsdb/AlternateHashingTest.java 8184042 macosx-all
-
-sun/tools/jhsdb/BasicLauncherTest.java 8184042 macosx-all
-
-sun/tools/jhsdb/HeapDumpTest.java 8184042 macosx-all
-
-sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8184042 macosx-all
-
############################################################################
# jdk_other
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -147,11 +147,6 @@
throw new AssertionError("Authenticator #2 called " + count(count)
+ " expected it to be called " + expected(expectedIncrement));
}
- count = authTwo.count.get();
- if (count != expectedIncrement) {
- throw new AssertionError("Authenticator #2 called " + count(count)
- + " expected it to be called " + expected(expectedIncrement));
- }
// Connect to the server with a GET request, then with a
// POST that contains "Hello World!"
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketAddress;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -148,62 +149,139 @@
}
/**
- * The HttpServerFactory ensures that the local port used by an HttpServer
- * previously created by the current test/VM will not get reused by
- * a subsequent test in the same VM. This is to avoid having the
- * AuthCache reuse credentials from previous tests - which would
- * invalidate the assumptions made by the current test on when
- * the default authenticator should be called.
+ * The SocketBindableFactory ensures that the local port used by an HttpServer
+ * or a proxy ServerSocket previously created by the current test/VM will not
+ * get reused by a subsequent test in the same VM. This is to avoid having the
+ * AuthCache reuse credentials from previous tests - which would invalidate the
+ * assumptions made by the current test on when the default authenticator should
+ * be called.
*/
- private static final class HttpServerFactory {
+ private static abstract class SocketBindableFactory<B> {
private static final int MAX = 10;
private static final CopyOnWriteArrayList<String> addresses =
new CopyOnWriteArrayList<>();
- private static HttpServer newHttpServer(HttpProtocolType protocol)
- throws IOException {
- switch (protocol) {
- case HTTP: return HttpServer.create();
- case HTTPS: return HttpsServer.create();
- default: throw new InternalError("Unsupported protocol " + protocol);
- }
- }
- static <T extends HttpServer> T create(HttpProtocolType protocol)
- throws IOException {
+ protected B createInternal() throws IOException {
final int max = addresses.size() + MAX;
- final List<HttpServer> toClose = new ArrayList<>();
+ final List<B> toClose = new ArrayList<>();
try {
for (int i = 1; i <= max; i++) {
- HttpServer server = newHttpServer(protocol);
- server.bind(new InetSocketAddress("127.0.0.1", 0), 0);
- InetSocketAddress address = server.getAddress();
+ B bindable = createBindable();
+ SocketAddress address = getAddress(bindable);
String key = address.toString();
if (addresses.addIfAbsent(key)) {
- System.out.println("Server bound to: " + key
+ System.out.println("Socket bound to: " + key
+ " after " + i + " attempt(s)");
- return (T) server;
+ return bindable;
}
System.out.println("warning: address " + key
+ " already used. Retrying bind.");
// keep the port bound until we get a port that we haven't
// used already
- toClose.add(server);
+ toClose.add(bindable);
}
} finally {
- // if we had to retry, then close the servers we're not
+ // if we had to retry, then close the socket we're not
// going to use.
- for (HttpServer s : toClose) {
- try { s.stop(1); } catch (Exception x) { /* ignore */ }
+ for (B b : toClose) {
+ try { close(b); } catch (Exception x) { /* ignore */ }
}
}
- throw new IOException("Couldn't bind servers after " + max + " attempts: "
+ throw new IOException("Couldn't bind socket after " + max + " attempts: "
+ "addresses used before: " + addresses);
}
+
+ protected abstract B createBindable() throws IOException;
+
+ protected abstract SocketAddress getAddress(B bindable);
+
+ protected abstract void close(B bindable) throws IOException;
+ }
+
+ /*
+ * Used to create ServerSocket for a proxy.
+ */
+ private static final class ServerSocketFactory
+ extends SocketBindableFactory<ServerSocket> {
+ private static final ServerSocketFactory instance = new ServerSocketFactory();
+
+ static ServerSocket create() throws IOException {
+ return instance.createInternal();
+ }
+
+ @Override
+ protected ServerSocket createBindable() throws IOException {
+ return new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
+ }
+
+ @Override
+ protected SocketAddress getAddress(ServerSocket socket) {
+ return socket.getLocalSocketAddress();
+ }
+
+ @Override
+ protected void close(ServerSocket socket) throws IOException {
+ socket.close();
+ }
+ }
+
+ /*
+ * Used to create HttpServer for a NTLMTestServer.
+ */
+ private static abstract class WebServerFactory<S extends HttpServer>
+ extends SocketBindableFactory<S> {
+ @Override
+ protected S createBindable() throws IOException {
+ S server = newHttpServer();
+ server.bind(new InetSocketAddress("127.0.0.1", 0), 0);
+ return server;
+ }
+
+ @Override
+ protected SocketAddress getAddress(S server) {
+ return server.getAddress();
+ }
+
+ @Override
+ protected void close(S server) throws IOException {
+ server.stop(1);
+ }
+
+ /*
+ * Returns a HttpServer or a HttpsServer in different subclasses.
+ */
+ protected abstract S newHttpServer() throws IOException;
+ }
+
+ private static final class HttpServerFactory extends WebServerFactory<HttpServer> {
+ private static final HttpServerFactory instance = new HttpServerFactory();
+
+ static HttpServer create() throws IOException {
+ return instance.createInternal();
+ }
+
+ @Override
+ protected HttpServer newHttpServer() throws IOException {
+ return HttpServer.create();
+ }
+ }
+
+ private static final class HttpsServerFactory extends WebServerFactory<HttpsServer> {
+ private static final HttpsServerFactory instance = new HttpsServerFactory();
+
+ static HttpsServer create() throws IOException {
+ return instance.createInternal();
+ }
+
+ @Override
+ protected HttpsServer newHttpServer() throws IOException {
+ return HttpsServer.create();
+ }
}
static HttpServer createHttpServer(HttpProtocolType protocol) throws IOException {
switch (protocol) {
- case HTTP: return HttpServerFactory.create(protocol);
- case HTTPS: return configure(HttpServerFactory.create(protocol));
+ case HTTP: return HttpServerFactory.create();
+ case HTTPS: return configure(HttpsServerFactory.create());
default: throw new InternalError("Unsupported protocol " + protocol);
}
}
@@ -894,7 +972,7 @@
super(server, target, delegate);
System.out.flush();
System.err.println("WARNING: HttpsProxyTunnel is an experimental test class");
- ss = new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
+ ss = ServerSocketFactory.create();
start();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/FileChannel/CleanerTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8147615
+ * @summary Test whether an unreferenced FileChannel is actually cleaned
+ * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "solaris") | (os.family == "aix")
+ * @modules java.management
+ * @run main/othervm CleanerTest
+ */
+
+import com.sun.management.UnixOperatingSystemMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+
+public class CleanerTest {
+ public static void main(String[] args) throws Throwable {
+ OperatingSystemMXBean mxBean =
+ ManagementFactory.getOperatingSystemMXBean();
+ UnixOperatingSystemMXBean unixMxBean = null;
+ if (mxBean instanceof UnixOperatingSystemMXBean) {
+ unixMxBean = (UnixOperatingSystemMXBean)mxBean;
+ } else {
+ System.out.println("Non-Unix system: skipping test.");
+ return;
+ }
+
+ Path path = Paths.get(System.getProperty("test.dir", "."), "junk");
+ try {
+ FileChannel fc = FileChannel.open(path, StandardOpenOption.CREATE,
+ StandardOpenOption.READ, StandardOpenOption.WRITE);
+
+ ReferenceQueue refQueue = new ReferenceQueue();
+ Reference fcRef = new PhantomReference(fc, refQueue);
+
+ long fdCount0 = unixMxBean.getOpenFileDescriptorCount();
+ fc = null;
+
+ // Perform repeated GCs until the reference has been enqueued.
+ do {
+ Thread.sleep(1);
+ System.gc();
+ } while (refQueue.poll() == null);
+
+ // Loop until the open file descriptor count has been decremented.
+ while (unixMxBean.getOpenFileDescriptorCount() > fdCount0 - 1) {
+ Thread.sleep(1);
+ }
+
+ long fdCount = unixMxBean.getOpenFileDescriptorCount();
+ if (fdCount != fdCount0 - 1) {
+ throw new RuntimeException("FD count expected " +
+ (fdCount0 - 1) + "; actual " + fdCount);
+ }
+ } finally {
+ Files.delete(path);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/ServiceLoader/CachingTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Test ServiceLoader caches
+ * @run testng CachingTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import java.util.Spliterator;
+import java.util.stream.Collectors;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class CachingTest {
+
+ // service type
+ public static interface S { }
+
+ // service provider implementations
+ public static class S1 implements S { }
+
+ public static class S2 implements S { }
+
+ private ClassLoader testClassLoader;
+
+ // creates the services configuration file and sets the ClassLoader
+ @BeforeClass
+ void setup() throws Exception {
+ String classes = System.getProperty("test.classes");
+ Path dir = Paths.get(classes, "META-INF", "services");
+ Files.createDirectories(dir);
+ Path config = dir.resolve(S.class.getName());
+ Files.write(config, List.of(S1.class.getName(), S2.class.getName()));
+ this.testClassLoader = CachingTest.class.getClassLoader();
+ }
+
+ private void checkLists(List<?> list1, List<?> list2) {
+ assertTrue(list1.size() == 2);
+ assertTrue(list2.size() == 2);
+ Iterator<?> iterator1 = list1.iterator();
+ Iterator<?> iterator2 = list2.iterator();
+ while (iterator1.hasNext()) {
+ assertTrue(iterator1.next() == iterator2.next());
+ }
+ }
+
+ @Test
+ public void testIterator1() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ List<S> list1 = new ArrayList<>();
+ List<S> list2 = new ArrayList<>();
+
+ // 1-1-2-2
+ sl.forEach(list1::add);
+ sl.forEach(list2::add);
+
+ checkLists(list1, list2);
+ }
+
+ // interleaved
+ @Test
+ public void testIterator2() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ List<S> list1 = new ArrayList<>();
+ List<S> list2 = new ArrayList<>();
+
+ Iterator<S> iterator1 = sl.iterator();
+ Iterator<S> iterator2 = sl.iterator();
+
+ // 1-2-1-2
+ list1.add(iterator1.next());
+ list2.add(iterator2.next());
+ list1.add(iterator1.next());
+ list2.add(iterator2.next());
+
+ checkLists(list1, list2);
+ }
+
+ // interleaved
+ @Test
+ public void testIterator3() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ List<S> list1 = new ArrayList<>();
+ List<S> list2 = new ArrayList<>();
+
+ Iterator<S> iterator1 = sl.iterator();
+ Iterator<S> iterator2 = sl.iterator();
+
+ // 1-2-2-1
+ list1.add(iterator1.next());
+ list2.add(iterator2.next());
+ list2.add(iterator2.next());
+ list1.add(iterator1.next());
+
+ checkLists(list1, list2);
+ }
+
+ @Test
+ public void testStream1() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ // 1-1-2-2
+ List<Provider<S>> list1 = sl.stream().collect(Collectors.toList());
+ List<Provider<S>> list2 = sl.stream().collect(Collectors.toList());
+ checkLists(list1, list2);
+ }
+
+ // interleaved
+ @Test
+ public void testStream2() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ List<Provider<S>> list1 = new ArrayList<>();
+ List<Provider<S>> list2 = new ArrayList<>();
+
+ Spliterator<Provider<S>> spliterator1 = sl.stream().spliterator();
+ Spliterator<Provider<S>> spliterator2 = sl.stream().spliterator();
+
+ // 1-2-1-2
+ spliterator1.tryAdvance(list1::add);
+ spliterator2.tryAdvance(list2::add);
+ spliterator1.tryAdvance(list1::add);
+ spliterator2.tryAdvance(list2::add);
+
+ assertFalse(spliterator1.tryAdvance(e -> assertTrue(false)));
+ assertFalse(spliterator2.tryAdvance(e -> assertTrue(false)));
+
+ checkLists(list1, list2);
+ }
+
+ // interleaved
+ @Test
+ public void testStream3() {
+ ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+ List<Provider<S>> list1 = new ArrayList<>();
+ List<Provider<S>> list2 = new ArrayList<>();
+
+ Spliterator<Provider<S>> spliterator1 = sl.stream().spliterator();
+ Spliterator<Provider<S>> spliterator2 = sl.stream().spliterator();
+
+ // 1-2-2-1
+ spliterator1.tryAdvance(list1::add);
+ spliterator2.tryAdvance(list2::add);
+ spliterator2.tryAdvance(list2::add);
+ spliterator1.tryAdvance(list1::add);
+
+ assertFalse(spliterator1.tryAdvance(e -> assertTrue(false)));
+ assertFalse(spliterator2.tryAdvance(e -> assertTrue(false)));
+
+ checkLists(list1, list2);
+ }
+}
--- a/test/jdk/java/util/ServiceLoader/security/test/module-info.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/ServiceLoader/security/test/module-info.java Wed Oct 18 21:05:09 2017 +0000
@@ -26,8 +26,16 @@
module test {
uses S1;
uses S2;
+ uses S3;
+ uses S4;
+ uses S5;
+ uses S6;
provides S1 with P1;
provides S2 with P2;
+ provides S3 with P3;
+ provides S4 with P4;
+ provides S5 with P5;
+ provides S6 with P6;
requires testng;
exports p to testng;
}
--- a/test/jdk/java/util/ServiceLoader/security/test/p/Tests.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/ServiceLoader/security/test/p/Tests.java Wed Oct 18 21:05:09 2017 +0000
@@ -38,14 +38,16 @@
import java.util.ServiceLoader.Provider;
import static java.security.AccessController.doPrivileged;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
import static org.testng.Assert.*;
/**
- * Basic tests with a security manager to ensure that the provider code
- * is run with permissions restricted by whatever created the ServiceLoader
- * object.
+ * Tests ServiceLoader when running with a security manager, specifically
+ * tests to ensure that provider code is run with permissions restricted by
+ * the creater of ServiceLoader, and also testing of exceptions thrown
+ * when loading or initializing a provider.
*/
public class Tests {
@@ -163,11 +165,35 @@
}
}
+ @DataProvider(name = "failingServices")
+ public Object[][] failingServices() {
+ return new Object[][] {
+ { S3.class, P3.Error3.class },
+ { S4.class, P4.Error4.class },
+ { S5.class, P5.Error5.class },
+ { S6.class, P6.Error6.class },
+ };
+ }
+
+ @Test(dataProvider = "failingServices")
+ public void testFailingService(Class<?> service, Class<? extends Error> errorClass) {
+ ServiceLoader<?> sl = ServiceLoader.load(service);
+ try {
+ sl.iterator().next();
+ assertTrue(false);
+ } catch (ServiceConfigurationError e) {
+ assertTrue(e.getCause().getClass() == errorClass);
+ }
+ }
// service types and implementations
public static interface S1 { }
public static interface S2 { }
+ public static interface S3 { }
+ public static interface S4 { }
+ public static interface S5 { }
+ public static interface S6 { }
public static class P1 implements S1 {
public P1() {
@@ -182,4 +208,36 @@
return new P2();
}
}
+
+ public static class P3 implements S3 {
+ static class Error3 extends Error { }
+ static {
+ if (1==1) throw new Error3(); // fail
+ }
+ public P3() { }
+ }
+
+ public static class P4 implements S4 {
+ static class Error4 extends Error { }
+ static {
+ if (1==1) throw new Error4(); // fail
+ }
+ public static S4 provider() {
+ return new P4();
+ }
+ }
+
+ public static class P5 implements S5 {
+ static class Error5 extends Error { }
+ public P5() {
+ throw new Error5(); // fail
+ }
+ }
+
+ public static class P6 implements S6 {
+ static class Error6 extends Error { }
+ public static S6 provider() {
+ throw new Error6(); // fail
+ }
+ }
}
--- a/test/jdk/java/util/concurrent/ConcurrentQueues/GCRetention.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/ConcurrentQueues/GCRetention.java Wed Oct 18 21:05:09 2017 +0000
@@ -35,7 +35,7 @@
* @bug 6785442
* @summary Benchmark that tries to GC-tenure head, followed by
* many add/remove operations.
- * @run main GCRetention 12345
+ * @run main GCRetention just-testing
*/
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -60,8 +60,8 @@
import java.util.Map;
public class GCRetention {
- // Suitable for benchmarking. Overridden by args[0] for testing.
- int count = 1024 * 1024;
+ boolean benchmarkMode;
+ int count;
/** No guarantees, but effective in practice. */
static void forceFullGc() {
@@ -124,8 +124,9 @@
}
void test(String[] args) {
- if (args.length > 0)
- count = Integer.valueOf(args[0]);
+ benchmarkMode = ! (args.length > 0 && args[0].equals("just-testing"));
+ count = benchmarkMode ? 1024 * 1024 : 30;
+
// Warmup
for (Queue<Boolean> queue : queues())
test(queue);
@@ -140,7 +141,7 @@
long t0 = System.nanoTime();
for (int i = 0; i < count; i++)
check(q.add(Boolean.TRUE));
- forceFullGc();
+ if (benchmarkMode) forceFullGc();
// forceFullGc();
Boolean x;
while ((x = q.poll()) != null)
--- a/test/jdk/java/util/concurrent/ExecutorService/Invoke.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/ExecutorService/Invoke.java Wed Oct 18 21:05:09 2017 +0000
@@ -28,12 +28,18 @@
* @author Martin Buchholz
*/
-import java.util.Arrays;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
public class Invoke {
@@ -61,36 +67,162 @@
check(condition, "Assertion failure");
}
+ static long secondsElapsedSince(long startTime) {
+ return NANOSECONDS.toSeconds(System.nanoTime() - startTime);
+ }
+
+ static void awaitInterrupt(long timeoutSeconds) {
+ long startTime = System.nanoTime();
+ try {
+ Thread.sleep(SECONDS.toMillis(timeoutSeconds));
+ fail("timed out waiting for interrupt");
+ } catch (InterruptedException expected) {
+ check(secondsElapsedSince(startTime) < timeoutSeconds);
+ }
+ }
+
public static void main(String[] args) {
try {
- final AtomicLong count = new AtomicLong(0);
- ExecutorService fixed = Executors.newFixedThreadPool(5);
- class Inc implements Callable<Long> {
- public Long call() throws Exception {
- Thread.sleep(200); // Catch IE from possible cancel
- return count.incrementAndGet();
- }
+ testInvokeAll();
+ testInvokeAny();
+ testInvokeAny_cancellationInterrupt();
+ } catch (Throwable t) { unexpected(t); }
+
+ if (failed > 0)
+ throw new Error(
+ String.format("Passed = %d, failed = %d", passed, failed));
+ }
+
+ static final long timeoutSeconds = 10L;
+
+ static void testInvokeAll() throws Throwable {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final int nThreads = rnd.nextInt(2, 7);
+ final boolean timed = rnd.nextBoolean();
+ final ExecutorService pool = Executors.newFixedThreadPool(nThreads);
+ final AtomicLong count = new AtomicLong(0);
+ class Task implements Callable<Long> {
+ public Long call() throws Exception {
+ return count.incrementAndGet();
}
- List<Inc> tasks = Arrays.asList(new Inc(), new Inc(), new Inc());
- List<Future<Long>> futures = fixed.invokeAll(tasks);
+ }
+
+ try {
+ final List<Task> tasks =
+ IntStream.range(0, nThreads)
+ .mapToObj(i -> new Task())
+ .collect(Collectors.toList());
+
+ List<Future<Long>> futures;
+ if (timed) {
+ long startTime = System.nanoTime();
+ futures = pool.invokeAll(tasks, timeoutSeconds, SECONDS);
+ check(secondsElapsedSince(startTime) < timeoutSeconds);
+ }
+ else
+ futures = pool.invokeAll(tasks);
check(futures.size() == tasks.size());
check(count.get() == tasks.size());
long gauss = 0;
for (Future<Long> future : futures) gauss += future.get();
- check(gauss == ((tasks.size()+1)*tasks.size())/2);
+ check(gauss == (tasks.size()+1)*tasks.size()/2);
+
+ pool.shutdown();
+ check(pool.awaitTermination(10L, SECONDS));
+ } finally {
+ pool.shutdownNow();
+ }
+ }
- ExecutorService single = Executors.newSingleThreadExecutor();
- long save = count.get();
- check(single.invokeAny(tasks) == save + 1);
- check(count.get() == save + 1);
+ static void testInvokeAny() throws Throwable {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final boolean timed = rnd.nextBoolean();
+ final ExecutorService pool = Executors.newSingleThreadExecutor();
+ final AtomicLong count = new AtomicLong(0);
+ class Task implements Callable<Long> {
+ public Long call() throws Exception {
+ long x = count.incrementAndGet();
+ check(x <= 2);
+ if (x == 2)
+ // wait for main thread to interrupt us
+ awaitInterrupt(timeoutSeconds);
+ return x;
+ }
+ }
+
+ try {
+ final List<Task> tasks =
+ IntStream.range(0, rnd.nextInt(1, 7))
+ .mapToObj(i -> new Task())
+ .collect(Collectors.toList());
+
+ long val;
+ if (timed) {
+ long startTime = System.nanoTime();
+ val = pool.invokeAny(tasks, timeoutSeconds, SECONDS);
+ check(secondsElapsedSince(startTime) < timeoutSeconds);
+ }
+ else
+ val = pool.invokeAny(tasks);
+ check(val == 1);
+
+ // inherent race between main thread interrupt and
+ // start of second task
+ check(count.get() == 1 || count.get() == 2);
- fixed.shutdown();
- single.shutdown();
+ pool.shutdown();
+ check(pool.awaitTermination(timeoutSeconds, SECONDS));
+ } finally {
+ pool.shutdownNow();
+ }
+ }
- } catch (Throwable t) { unexpected(t); }
+ /**
+ * Every remaining running task is sent an interrupt for cancellation.
+ */
+ static void testInvokeAny_cancellationInterrupt() throws Throwable {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final int nThreads = rnd.nextInt(2, 7);
+ final boolean timed = rnd.nextBoolean();
+ final ExecutorService pool = Executors.newFixedThreadPool(nThreads);
+ final AtomicLong count = new AtomicLong(0);
+ final AtomicLong interruptedCount = new AtomicLong(0);
+ final CyclicBarrier allStarted = new CyclicBarrier(nThreads);
+ class Task implements Callable<Long> {
+ public Long call() throws Exception {
+ allStarted.await();
+ long x = count.incrementAndGet();
+ if (x > 1)
+ // main thread will interrupt us
+ awaitInterrupt(timeoutSeconds);
+ return x;
+ }
+ }
- System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
- if (failed > 0) throw new Error("Some tests failed");
+ try {
+ final List<Task> tasks =
+ IntStream.range(0, nThreads)
+ .mapToObj(i -> new Task())
+ .collect(Collectors.toList());
+
+ long val;
+ if (timed) {
+ long startTime = System.nanoTime();
+ val = pool.invokeAny(tasks, timeoutSeconds, SECONDS);
+ check(secondsElapsedSince(startTime) < timeoutSeconds);
+ }
+ else
+ val = pool.invokeAny(tasks);
+ check(val == 1);
+
+ pool.shutdown();
+ check(pool.awaitTermination(timeoutSeconds, SECONDS));
+
+ // Check after shutdown to avoid race
+ check(count.get() == nThreads);
+ } finally {
+ pool.shutdownNow();
+ }
}
}
--- a/test/jdk/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -40,7 +40,10 @@
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Random;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.LongAdder;
import junit.framework.Test;
@@ -932,4 +935,78 @@
} catch (NullPointerException success) {}
}
}
+
+ /**
+ * Non-traversing Deque operations are linearizable.
+ * https://bugs.openjdk.java.net/browse/JDK-8188900
+ * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8188900 tck
+ */
+ public void testBug8188900() {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
+ for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
+ ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
+
+ boolean peek = rnd.nextBoolean();
+ Runnable getter = () -> {
+ Integer x = peek ? d.peekFirst() : d.pollFirst();
+ if (x == null) nulls.increment();
+ else if (x == 0) zeros.increment();
+ else
+ throw new AssertionError(
+ String.format(
+ "unexpected value %d after %d nulls and %d zeros",
+ x, nulls.sum(), zeros.sum()));
+ };
+
+ Runnable adder = () -> {
+ d.addFirst(0);
+ d.addLast(42);
+ };
+
+ boolean b = rnd.nextBoolean();
+ Runnable r1 = b ? getter : adder;
+ Runnable r2 = b ? adder : getter;
+ CompletableFuture<Void> f1 = CompletableFuture.runAsync(r1);
+ CompletableFuture<Void> f2 = CompletableFuture.runAsync(r2);
+ f1.join();
+ f2.join();
+ }
+ }
+
+ /**
+ * Reverse direction variant of testBug8188900
+ */
+ public void testBug8188900_reverse() {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
+ for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
+ ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
+
+ boolean peek = rnd.nextBoolean();
+ Runnable getter = () -> {
+ Integer x = peek ? d.peekLast() : d.pollLast();
+ if (x == null) nulls.increment();
+ else if (x == 0) zeros.increment();
+ else
+ throw new AssertionError(
+ String.format(
+ "unexpected value %d after %d nulls and %d zeros",
+ x, nulls.sum(), zeros.sum()));
+ };
+
+ Runnable adder = () -> {
+ d.addLast(0);
+ d.addFirst(42);
+ };
+
+ boolean b = rnd.nextBoolean();
+ Runnable r1 = b ? getter : adder;
+ Runnable r2 = b ? adder : getter;
+ CompletableFuture<Void> f1 = CompletableFuture.runAsync(r1);
+ CompletableFuture<Void> f2 = CompletableFuture.runAsync(r2);
+ f1.join();
+ f2.join();
+ }
+ }
}
--- a/test/jdk/java/util/concurrent/tck/SplittableRandomTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/tck/SplittableRandomTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -31,9 +31,14 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
+import java.util.Arrays;
+import java.util.List;
import java.util.SplittableRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
+import java.lang.reflect.Method;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -552,4 +557,64 @@
assertEquals(size, counter.sum());
}
+ /**
+ * SplittableRandom should implement most of Random's public methods
+ */
+ public void testShouldImplementMostRandomMethods() throws Throwable {
+ Predicate<Method> wasForgotten = method -> {
+ String name = method.getName();
+ // some methods deliberately not implemented
+ if (name.equals("setSeed")) return false;
+ if (name.equals("nextFloat")) return false;
+ if (name.equals("nextGaussian")) return false;
+ try {
+ SplittableRandom.class.getMethod(
+ method.getName(), method.getParameterTypes());
+ } catch (ReflectiveOperationException ex) {
+ return true;
+ }
+ return false;
+ };
+ List<Method> forgotten =
+ Arrays.stream(java.util.Random.class.getMethods())
+ .filter(wasForgotten)
+ .collect(Collectors.toList());
+ if (!forgotten.isEmpty())
+ throw new AssertionError("Please implement: " + forgotten);
+ }
+
+ /**
+ * Repeated calls to nextBytes produce at least values of different signs for every byte
+ */
+ public void testNextBytes() {
+ SplittableRandom sr = new SplittableRandom();
+ int n = sr.nextInt(1, 20);
+ byte[] bytes = new byte[n];
+ outer:
+ for (int i = 0; i < n; i++) {
+ for (int tries = NCALLS; tries-->0; ) {
+ byte before = bytes[i];
+ sr.nextBytes(bytes);
+ byte after = bytes[i];
+ if (after * before < 0)
+ continue outer;
+ }
+ fail("not enough variation in random bytes");
+ }
+ }
+
+ /**
+ * Filling an empty array with random bytes succeeds without effect.
+ */
+ public void testNextBytes_emptyArray() {
+ new SplittableRandom().nextBytes(new byte[0]);
+ }
+
+ public void testNextBytes_nullArray() {
+ try {
+ new SplittableRandom().nextBytes(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
}
--- a/test/jdk/java/util/concurrent/tck/StampedLockTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -35,6 +35,11 @@
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.locks.StampedLock.isLockStamp;
+import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp;
+import static java.util.concurrent.locks.StampedLock.isReadLockStamp;
+import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
+
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -1286,11 +1291,115 @@
} while (stamp == 0);
return Math.hypot(currentX, currentY);
}
+
+ double distanceFromOrigin2() {
+ long stamp = sl.tryOptimisticRead();
+ try {
+ retryHoldingLock:
+ for (;; stamp = sl.readLock()) {
+ if (stamp == 0L)
+ continue retryHoldingLock;
+ // possibly racy reads
+ double currentX = x;
+ double currentY = y;
+ if (!sl.validate(stamp))
+ continue retryHoldingLock;
+ return Math.hypot(currentX, currentY);
+ }
+ } finally {
+ if (StampedLock.isReadLockStamp(stamp))
+ sl.unlockRead(stamp);
+ }
+ }
+
+ void moveIfAtOrigin(double newX, double newY) {
+ long stamp = sl.readLock();
+ try {
+ while (x == 0.0 && y == 0.0) {
+ long ws = sl.tryConvertToWriteLock(stamp);
+ if (ws != 0L) {
+ stamp = ws;
+ x = newX;
+ y = newY;
+ return;
+ }
+ else {
+ sl.unlockRead(stamp);
+ stamp = sl.writeLock();
+ }
+ }
+ } finally {
+ sl.unlock(stamp);
+ }
+ }
}
Point p = new Point();
p.move(3.0, 4.0);
assertEquals(5.0, p.distanceFromOrigin());
+ p.moveIfAtOrigin(5.0, 12.0);
+ assertEquals(5.0, p.distanceFromOrigin2());
+ }
+
+ /**
+ * Stamp inspection methods work as expected, and do not inspect
+ * the state of the lock itself.
+ */
+ public void testStampStateInspectionMethods() {
+ StampedLock lock = new StampedLock();
+
+ assertFalse(isWriteLockStamp(0L));
+ assertFalse(isReadLockStamp(0L));
+ assertFalse(isLockStamp(0L));
+ assertFalse(isOptimisticReadStamp(0L));
+
+ {
+ long stamp = lock.writeLock();
+ for (int i = 0; i < 2; i++) {
+ assertTrue(isWriteLockStamp(stamp));
+ assertFalse(isReadLockStamp(stamp));
+ assertTrue(isLockStamp(stamp));
+ assertFalse(isOptimisticReadStamp(stamp));
+ if (i == 0)
+ lock.unlockWrite(stamp);
+ }
+ }
+
+ {
+ long stamp = lock.readLock();
+ for (int i = 0; i < 2; i++) {
+ assertFalse(isWriteLockStamp(stamp));
+ assertTrue(isReadLockStamp(stamp));
+ assertTrue(isLockStamp(stamp));
+ assertFalse(isOptimisticReadStamp(stamp));
+ if (i == 0)
+ lock.unlockRead(stamp);
+ }
+ }
+
+ {
+ long optimisticStamp = lock.tryOptimisticRead();
+ long readStamp = lock.tryConvertToReadLock(optimisticStamp);
+ long writeStamp = lock.tryConvertToWriteLock(readStamp);
+ for (int i = 0; i < 2; i++) {
+ assertFalse(isWriteLockStamp(optimisticStamp));
+ assertFalse(isReadLockStamp(optimisticStamp));
+ assertFalse(isLockStamp(optimisticStamp));
+ assertTrue(isOptimisticReadStamp(optimisticStamp));
+
+ assertFalse(isWriteLockStamp(readStamp));
+ assertTrue(isReadLockStamp(readStamp));
+ assertTrue(isLockStamp(readStamp));
+ assertFalse(isOptimisticReadStamp(readStamp));
+
+ assertTrue(isWriteLockStamp(writeStamp));
+ assertFalse(isReadLockStamp(writeStamp));
+ assertTrue(isLockStamp(writeStamp));
+ assertFalse(isOptimisticReadStamp(writeStamp));
+ if (i == 0)
+ lock.unlockWrite(writeStamp);
+ }
+ }
}
}
--- a/test/jdk/java/util/concurrent/tck/ThreadLocalRandomTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/concurrent/tck/ThreadLocalRandomTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -412,4 +412,38 @@
fail("all threads generate the same pseudo-random sequence");
}
+ /**
+ * Repeated calls to nextBytes produce at least values of different signs for every byte
+ */
+ public void testNextBytes() {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ int n = rnd.nextInt(1, 20);
+ byte[] bytes = new byte[n];
+ outer:
+ for (int i = 0; i < n; i++) {
+ for (int tries = NCALLS; tries-->0; ) {
+ byte before = bytes[i];
+ rnd.nextBytes(bytes);
+ byte after = bytes[i];
+ if (after * before < 0)
+ continue outer;
+ }
+ fail("not enough variation in random bytes");
+ }
+ }
+
+ /**
+ * Filling an empty array with random bytes succeeds without effect.
+ */
+ public void testNextBytes_emptyArray() {
+ ThreadLocalRandom.current().nextBytes(new byte[0]);
+ }
+
+ public void testNextBytes_nullArray() {
+ try {
+ ThreadLocalRandom.current().nextBytes(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
}
--- a/test/jdk/java/util/zip/ZipFile/ZeroDate.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/java/util/zip/ZipFile/ZeroDate.java Wed Oct 18 21:05:09 2017 +0000
@@ -34,14 +34,16 @@
import java.nio.file.Path;
import java.time.Instant;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/* @test
- * @bug 8184940
+ * @bug 8184940 8188869
* @summary JDK 9 rejects zip files where the modified day or month is 0
+ * or otherwise represent an invalid date, such as 1980-02-30 24:60:60
* @author Liam Miller-Cushon
*/
public class ZeroDate {
@@ -63,12 +65,19 @@
Files.delete(path);
// year, month, day are zero
- testDate(data.clone(), 0, LocalDate.of(1979, 11, 30));
+ testDate(data.clone(), 0, LocalDate.of(1979, 11, 30).atStartOfDay());
// only year is zero
- testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5));
+ testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5).atStartOfDay());
+ // month is greater than 12
+ testDate(data.clone(), 0 << 25 | 13 << 21 | 1 << 16, LocalDate.of(1981, 1, 1).atStartOfDay());
+ // 30th of February
+ testDate(data.clone(), 0 << 25 | 2 << 21 | 30 << 16, LocalDate.of(1980, 3, 1).atStartOfDay());
+ // 30th of February, 24:60:60
+ testDate(data.clone(), 0 << 25 | 2 << 21 | 30 << 16 | 24 << 11 | 60 << 5 | 60 >> 1,
+ LocalDateTime.of(1980, 3, 2, 1, 1, 0));
}
- private static void testDate(byte[] data, int date, LocalDate expected) throws IOException {
+ private static void testDate(byte[] data, int date, LocalDateTime expected) throws IOException {
// set the datetime
int endpos = data.length - ENDHDR;
int cenpos = u16(data, endpos + ENDOFF);
@@ -84,8 +93,7 @@
try (ZipFile zf = new ZipFile(path.toFile())) {
ZipEntry ze = zf.entries().nextElement();
Instant actualInstant = ze.getLastModifiedTime().toInstant();
- Instant expectedInstant =
- expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
+ Instant expectedInstant = expected.atZone(ZoneId.systemDefault()).toInstant();
if (!actualInstant.equals(expectedInstant)) {
throw new AssertionError(
String.format("actual: %s, expected: %s", actualInstant, expectedInstant));
--- a/test/jdk/jdk/nio/zipfs/ZeroDate.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/jdk/jdk/nio/zipfs/ZeroDate.java Wed Oct 18 21:05:09 2017 +0000
@@ -38,14 +38,16 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/* @test
- * @bug 8184940 8186227
+ * @bug 8184940 8186227 8188869
* @summary JDK 9 rejects zip files where the modified day or month is 0
+ * or otherwise represent an invalid date, such as 1980-02-30 24:60:60
* @author Liam Miller-Cushon
*/
public class ZeroDate {
@@ -67,12 +69,19 @@
Files.delete(path);
// year, month, day are zero
- testDate(data.clone(), 0, LocalDate.of(1979, 11, 30));
+ testDate(data.clone(), 0, LocalDate.of(1979, 11, 30).atStartOfDay());
// only year is zero
- testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5));
+ testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5).atStartOfDay());
+ // month is greater than 12
+ testDate(data.clone(), 0 << 25 | 13 << 21 | 1 << 16, LocalDate.of(1981, 1, 1).atStartOfDay());
+ // 30th of February
+ testDate(data.clone(), 0 << 25 | 2 << 21 | 30 << 16, LocalDate.of(1980, 3, 1).atStartOfDay());
+ // 30th of February, 24:60:60
+ testDate(data.clone(), 0 << 25 | 2 << 21 | 30 << 16 | 24 << 11 | 60 << 5 | 60 >> 1,
+ LocalDateTime.of(1980, 3, 2, 1, 1, 0));
}
- private static void testDate(byte[] data, int date, LocalDate expected) throws IOException {
+ private static void testDate(byte[] data, int date, LocalDateTime expected) throws IOException {
// set the datetime
int endpos = data.length - ENDHDR;
int cenpos = u16(data, endpos + ENDOFF);
@@ -93,7 +102,7 @@
.lastModifiedTime()
.toInstant();
Instant expectedInstant =
- expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
+ expected.atZone(ZoneId.systemDefault()).toInstant();
if (!actualInstant.equals(expectedInstant)) {
throw new AssertionError(
String.format("actual: %s, expected: %s", actualInstant, expectedInstant));
--- a/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java Wed Oct 18 21:05:09 2017 +0000
@@ -37,6 +37,8 @@
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.ArrayList;
@@ -46,6 +48,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Function;
@@ -150,6 +153,9 @@
/** The output directory used in the most recent call of javadoc. */
protected File outputDir;
+ /** The output charset used in the most recent call of javadoc. */
+ protected Charset charset = Charset.defaultCharset();
+
/** The exit code of the most recent call of javadoc. */
private int exitCode;
@@ -158,6 +164,8 @@
/** A cache of file content, to avoid reading files unnecessarily. */
private final Map<File,SoftReference<String>> fileContentCache = new HashMap<>();
+ /** The charset used for files in the fileContentCache. */
+ private Charset fileContentCacheCharset = null;
/** Stream used for logging messages. */
protected final PrintStream out = System.out;
@@ -293,13 +301,46 @@
out.println("Running javadoc (run "
+ javadocRunNum + ")...");
}
+
outputDir = new File(".");
+ String charsetArg = null;
+ String docencodingArg = null;
+ String encodingArg = null;
for (int i = 0; i < args.length - 2; i++) {
- if (args[i].equals("-d")) {
- outputDir = new File(args[++i]);
- break;
+ switch (args[i]) {
+ case "-d":
+ outputDir = new File(args[++i]);
+ break;
+ case "-charset":
+ charsetArg = args[++i];
+ break;
+ case "-docencoding":
+ docencodingArg = args[++i];
+ break;
+ case "-encoding":
+ encodingArg = args[++i];
+ break;
}
}
+
+ // The following replicates HtmlConfiguration.finishOptionSettings0
+ // and sets up the charset used to read files.
+ String cs;
+ if (docencodingArg == null) {
+ if (charsetArg == null) {
+ cs = (encodingArg == null) ? "UTF-8" : encodingArg;
+ } else {
+ cs = charsetArg;
+ }
+ } else {
+ cs = docencodingArg;
+ }
+ try {
+ charset = Charset.forName(cs);
+ } catch (UnsupportedCharsetException e) {
+ charset = Charset.defaultCharset();
+ }
+
out.println("args: " + Arrays.toString(args));
// log.setOutDir(outputDir);
@@ -637,6 +678,10 @@
* @return the file in string format
*/
private String readFile(File baseDir, String fileName) throws Error {
+ if (!Objects.equals(fileContentCacheCharset, charset)) {
+ fileContentCache.clear();
+ fileContentCacheCharset = charset;
+ }
try {
File file = new File(baseDir, fileName);
SoftReference<String> ref = fileContentCache.get(file);
@@ -644,7 +689,8 @@
if (content != null)
return content;
- content = new String(Files.readAllBytes(file.toPath()));
+ // charset defaults to a value inferred from latest javadoc run
+ content = new String(Files.readAllBytes(file.toPath()), charset);
fileContentCache.put(file, new SoftReference<>(content));
return content;
} catch (FileNotFoundException e) {
--- a/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,29 +23,37 @@
/*
* @test
- * @bug 8025633 8025524 8081854
+ * @bug 8025633 8025524 8081854 8187521
* @summary Test for valid name attribute in HTML anchors.
* @author Bhavesh Patel
- * @library ../lib
+ * @library /tools/lib ../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
- * @build JavadocTester
+ * @build toolbox.ToolBox JavadocTester
* @run main TestAnchorNames
*/
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.*;
+
public class TestAnchorNames extends JavadocTester {
- private static final String[] ARGS = new String[] {
-
- };
+ public final ToolBox tb;
+ public static void main(String... args) throws Exception {
+ TestAnchorNames tester = new TestAnchorNames();
+ tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
- public static void main(String[] args) throws Exception {
- TestAnchorNames tester = new TestAnchorNames();
- tester.runTests();
+ public TestAnchorNames() {
+ tb = new ToolBox();
}
@Test
- void test() {
- javadoc("-d", "out",
+ void testHtml4(Path ignore) {
+ javadoc("-d", "out-html4",
"-sourcepath", testSrc,
"-source", "8", //so that '_' can be used as an identifier
"-use",
@@ -153,11 +161,169 @@
"<a href=\"#I:Z:Z_\">_");
// The marker name conversion should only affect HTML anchors. It should not
- // affect the lables.
+ // affect the labels.
checkOutput("pkg1/RegClass.html", false,
" Z:Z_",
" Z:Z:Dfield",
" Z:Z_field_In_Class",
" S_:D:D:D:D:DINT");
}
+
+ @Test
+ void testHtml5(Path ignore) {
+ javadoc("-d", "out-html5",
+ "-sourcepath", testSrc,
+ "-source", "8", //so that '_' can be used as an identifier
+ "-use",
+ "-html5",
+ "pkg1");
+ checkExit(Exit.OK);
+
+ // Test some section markers and links to these markers
+ checkOutput("pkg1/RegClass.html", true,
+ "<a id=\"skip.navbar.top\">",
+ "<a href=\"#skip.navbar.top\" title=\"Skip navigation links\">",
+ "<a id=\"nested.class.summary\">",
+ "<a href=\"#nested.class.summary\">",
+ "<a id=\"method.summary\">",
+ "<a href=\"#method.summary\">",
+ "<a id=\"field.detail\">",
+ "<a href=\"#field.detail\">",
+ "<a id=\"constructor.detail\">",
+ "<a href=\"#constructor.detail\">");
+
+ // Test some members and link to these members
+ checkOutput("pkg1/RegClass.html", true,
+ //The marker for this appears in the serialized-form.html which we will
+ //test below
+ "<a href=\"../serialized-form.html#pkg1.RegClass\">");
+
+ // Test some fields
+ checkOutput("pkg1/RegClass.html", true,
+ "<a id=\"_\">",
+ "<a href=\"../pkg1/RegClass.html#_\">",
+ "<a id=\"_$\">",
+ "<a href=\"../pkg1/RegClass.html#_$\">",
+ "<a id=\"$_\">",
+ "<a href=\"../pkg1/RegClass.html#$_\">",
+ "<a id=\"$field\">",
+ "<a href=\"../pkg1/RegClass.html#$field\">",
+ "<a id=\"fieldInCla$$\">",
+ "<a href=\"../pkg1/RegClass.html#fieldInCla$$\">",
+ "<a id=\"S_$$$$$INT\">",
+ "<a href=\"../pkg1/RegClass.html#S_$$$$$INT\">",
+ "<a id=\"method$$\">",
+ "<a href=\"../pkg1/RegClass.html#method$$\">");
+
+ checkOutput("pkg1/DeprMemClass.html", true,
+ "<a id=\"_field_In_Class\">",
+ "<a href=\"../pkg1/DeprMemClass.html#_field_In_Class\">");
+
+ // Test constructor
+ checkOutput("pkg1/RegClass.html", true,
+ "<a id=\"<init>(java.lang.String,int)\">",
+ "<a href=\"../pkg1/RegClass.html#%3Cinit%3E(java.lang.String,int)\">");
+
+ // Test some methods
+ checkOutput("pkg1/RegClass.html", true,
+ "<a id=\"_methodInClass(java.lang.String)\">",
+ "<a href=\"../pkg1/RegClass.html#_methodInClass(java.lang.String)\">",
+ "<a id=\"method()\">",
+ "<a href=\"../pkg1/RegClass.html#method()\">",
+ "<a id=\"foo(java.util.Map)\">",
+ "<a href=\"../pkg1/RegClass.html#foo(java.util.Map)\">",
+ "<a id=\"methodInCla$s(java.lang.String[])\">",
+ "<a href=\"../pkg1/RegClass.html#methodInCla$s(java.lang.String%5B%5D)\">",
+ "<a id=\"_methodInClas$(java.lang.String,int)\">",
+ "<a href=\"../pkg1/RegClass.html#_methodInClas$(java.lang.String,int)\">",
+ "<a id=\"methodD(pkg1.RegClass.$A)\">",
+ "<a href=\"../pkg1/RegClass.html#methodD(pkg1.RegClass.$A)\">",
+ "<a id=\"methodD(pkg1.RegClass.D[])\">",
+ "<a href=\"../pkg1/RegClass.html#methodD(pkg1.RegClass.D%5B%5D)\">");
+
+ checkOutput("pkg1/DeprMemClass.html", true,
+ "<a id=\"$method_In_Class()\">",
+ "<a href=\"../pkg1/DeprMemClass.html#$method_In_Class()\">");
+
+ // Test enum
+ checkOutput("pkg1/RegClass.Te$t_Enum.html", true,
+ "<a id=\"$FLD2\">",
+ "<a href=\"../pkg1/RegClass.Te$t_Enum.html#$FLD2\">");
+
+ // Test nested class
+ checkOutput("pkg1/RegClass._NestedClas$.html", true,
+ "<a id=\"<init>()\">",
+ "<a href=\"../pkg1/RegClass._NestedClas$.html#%3Cinit%3E()\">");
+
+ // Test class use page
+ checkOutput("pkg1/class-use/DeprMemClass.html", true,
+ "<a href=\"../../pkg1/RegClass.html#d____mc\">");
+
+ // Test deprecated list page
+ checkOutput("deprecated-list.html", true,
+ "<a href=\"pkg1/DeprMemClass.html#_field_In_Class\">",
+ "<a href=\"pkg1/DeprMemClass.html#$method_In_Class()\">");
+
+ // Test constant values page
+ checkOutput("constant-values.html", true,
+ "<a href=\"pkg1/RegClass.html#S_$$$$$INT\">");
+
+ // Test serialized form page
+ checkOutput("serialized-form.html", true,
+ //This is the marker for the link that appears in the pkg1.RegClass.html page
+ "<a id=\"pkg1.RegClass\">");
+
+ // Test member name index page
+ checkOutput("index-all.html", true,
+ "<a id=\"I:$\">",
+ "<a href=\"#I:$\">$",
+ "<a href=\"#I:_\">_");
+ }
+
+ /**
+ * The following test is somewhat simplistic, but it is useful
+ * in conjunction with the W3C Validation Service at https://validator.w3.org/nu/#file
+ * @param base A working directory for this method, in which some UTF-8 source files
+ * will be generated
+ * @throws IOException if there is a problem generating the source files
+ */
+ @Test
+ void testNonAscii(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; public class Def {\n"
+ + " public int \u00e0\u00e9;\n" // a`e'
+ + " public void \u00c0\u00c9() { }\n" // A`E'
+ + " public int \u03b1\u03b2\u03b3;\n" // alpha beta gamma
+ + " public void \u0391\u0392\u0393() { }\n" // ALPHA BETA GAMMA
+ + "}",
+ "package p; \n"
+ + "/**\n"
+ + " * {@link Def#\u00e0\u00e9 àé}<br>\n"
+ + " * {@link Def#\u00c0\u00c9() ÀÉ}<br>\n"
+ + " * {@link Def#\u03b1\u03b2\u03b3 αβγ}<br>\n"
+ + " * {@link Def#\u0391\u0392\u0393() ΑΒΓ}<br>\n"
+ + " */\n"
+ + "public class Ref { }");
+
+ javadoc("-d", "out-nonAscii",
+ "-sourcepath", src.toString(),
+ "-html5",
+ "-encoding", "utf-8",
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/Def.html", true,
+ "<a id=\"\u00e0\u00e9\">",
+ "<a id=\"\u00c0\u00c9()\">",
+ "<a id=\"\u03b1\u03b2\u03b3\">",
+ "<a id=\"\u0391\u0392\u0393()\">");
+
+ checkOutput("p/Ref.html", true,
+ "<a href=\"../p/Def.html#%C3%A0%C3%A9\"><code>àé</code></a>",
+ "<a href=\"../p/Def.html#%C3%80%C3%89()\"><code>ÀÉ</code></a>",
+ "<a href=\"../p/Def.html#%CE%B1%CE%B2%CE%B3\"><code>αβγ</code></a>",
+ "<a href=\"../p/Def.html#%CE%91%CE%92%CE%93()\"><code>ΑΒΓ</code></a>");
+
+ }
}
--- a/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java Wed Oct 18 21:05:09 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@
* @run main TestDocEncoding
*/
+import java.nio.charset.Charset;
+
public class TestDocEncoding extends JavadocTester {
public static void main(String... args) throws Exception {
@@ -53,6 +55,13 @@
"pkg");
checkExit(Exit.OK);
+ checkOutput("stylesheet.css", true,
+ "body {\n"
+ + " background-color:#ffffff;");
+
+ // reset the charset, for a negative test, that the -docencoding
+ // was effective and that the output is not in UTF-8.
+ charset = Charset.forName("UTF-8");
checkOutput("stylesheet.css", false,
"body {\n"
+ " background-color:#ffffff;");
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java Wed Oct 18 21:05:09 2017 +0000
@@ -23,7 +23,8 @@
/*
* @test
- * @bug 8141492 8071982 8141636 8147890 8166175 8168965 8176794 8175218 8147881 8181622 8182263 8074407
+ * @bug 8141492 8071982 8141636 8147890 8166175 8168965 8176794 8175218 8147881
+ * 8181622 8182263 8074407 8187521
* @summary Test the search feature of javadoc.
* @author bpatel
* @library ../lib
@@ -64,7 +65,7 @@
checkExit(Exit.OK);
checkInvalidUsageIndexTag();
checkSearchOutput(true);
- checkSingleIndex(true);
+ checkSingleIndex(true, false);
checkSingleIndexSearchTagDuplication();
checkJqueryAndImageFiles(true);
checkSearchJS();
@@ -86,7 +87,7 @@
checkExit(Exit.ERROR);
checkDocLintErrors();
checkSearchOutput(true);
- checkSingleIndex(true);
+ checkSingleIndex(true, false);
checkSingleIndexSearchTagDuplication();
checkJqueryAndImageFiles(true);
checkSearchJS();
@@ -128,7 +129,7 @@
"-use", "pkg", "pkg1", "pkg2", "pkg3");
checkExit(Exit.OK);
checkSearchOutput(true);
- checkSingleIndex(true);
+ checkSingleIndex(true, true);
checkSingleIndexSearchTagDuplication();
checkJqueryAndImageFiles(true);
checkSearchJS();
@@ -280,7 +281,9 @@
"<div class=\"fixedNav\">");
}
- void checkSingleIndex(boolean expectedOutput) {
+ void checkSingleIndex(boolean expectedOutput, boolean html5) {
+ String html_span_see_span = html5 ? "html%3Cspan%3Esee%3C/span%3E" : "html-span-see-/span-";
+
// Test for search tags markup in index file.
checkOutput("index-all.html", expectedOutput,
"<dt><span class=\"searchTagLink\"><a href=\"pkg/package-summary.html#phrasewithspaces\">"
@@ -313,7 +316,7 @@
+ "#nested%7B@indexnested_tag_test%7D\">nested {@index nested_tag_test}</a></span> - "
+ "Search tag in pkg.AnotherClass.ModalExclusionType.NO_EXCLUDE</dt>",
"<dt><span class=\"searchTagLink\"><a href=\"pkg/AnotherClass.ModalExclusionType.html"
- + "#html-span-see-/span-\">html <span> see </span></a></span> - Search "
+ + "#" + html_span_see_span + "\">html <span> see </span></a></span> - Search "
+ "tag in pkg.AnotherClass.ModalExclusionType.APPLICATION_EXCLUDE</dt>",
"<dt><span class=\"searchTagLink\"><a href=\"pkg/AnotherClass.html#quoted\">quoted</a>"
+ "</span> - Search tag in pkg.AnotherClass.CONSTANT1</dt>",
--- a/test/langtools/jdk/jshell/ErrorTranslationTest.java Wed Oct 18 13:52:32 2017 -0700
+++ b/test/langtools/jdk/jshell/ErrorTranslationTest.java Wed Oct 18 21:05:09 2017 +0000
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8188225
* @summary Tests for shell error translation
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -59,6 +60,13 @@
);
}
+ public void testlvtiErrors() {
+ test(
+ a -> assertDiagnostic(a, "var broken = () -> {};", newExpectedDiagnostic(0, 22, 0, -1, -1, Diagnostic.Kind.ERROR)),
+ a -> assertDiagnostic(a, "void t () { var broken = () -> {}; }", newExpectedDiagnostic(12, 34, 0, -1, -1, Diagnostic.Kind.ERROR))
+ );
+ }
+
public void testWarnings() {
List<ReplTest> list = new ArrayList<>();
ExpectedDiagnostic[] diagnostics = new ExpectedDiagnostic[]{
@@ -117,19 +125,16 @@
}
String kind = getKind(expectedDiagnostic.getKind());
assertEquals(lines[0], kind);
- String source;
- String markingLine;
- switch (expectedDiagnostic.getKind()) {
- case ERROR:
- case WARNING:
- source = lines[2];
- markingLine = lines[3];
- break;
- default:
- throw new AssertionError("Unsupported diagnostic kind: " + expectedDiagnostic.getKind());
+ boolean found = false;
+ for (int i = 0; i < lines.length; i++) {
+ if (lines[i].endsWith(expectedSource)) {
+ assertEquals(lines[i + 1], expectedMarkingLine, "Input: " + expectedSource + ", marking line: ");
+ found = true;
+ }
}
- assertTrue(source.endsWith(expectedSource), "Expected: " + expectedSource + ", found: " + source);
- assertEquals(markingLine, expectedMarkingLine, "Input: " + expectedSource + ", marking line: ");
+ if (!found) {
+ throw new AssertionError("Did not find: " + expectedSource + " in: " + s);
+ }
};
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/8169345/T8169345a.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8169345
+ * @summary javac crash when local from enclosing context is captured multiple times
+ */
+
+public class T8169345a {
+ void test() {
+ Object o = new Object();
+ class Local1 {
+ Object test1() {
+ return o;
+ }
+ }
+ class Local2 {
+ void test2() {
+ Object o = new Object();
+ class Local3 extends Local1 {
+ Object test3() {
+ return o;
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Class.forName("T8169345a$1Local1");
+ Class.forName("T8169345a$1Local2$1Local3");
+ Class.forName("T8169345a$1Local2");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/8169345/T8169345b.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8169345
+ * @summary javac crash when local from enclosing context is captured multiple times
+ */
+
+public class T8169345b {
+ void test() {
+ Object o = new Object();
+ class Local1 {
+ Object test1() {
+ return o;
+ }
+ }
+ class Local2 {
+ void test2() {
+ Object o = new Object();
+ class Local3 {
+ Object test3() {
+ return o;
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Class.forName("T8169345b$1Local1");
+ Class.forName("T8169345b$1Local2$1Local3");
+ Class.forName("T8169345b$1Local2");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/8169345/T8169345c.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8169345
+ * @summary javac crash when local from enclosing context is captured multiple times
+ * @compile T8169345c.java
+ */
+
+class T8169345c {
+ void test() {
+ final int b;
+ b = 10;
+ class Local1 {
+ public String toString() {
+ return "" + b;
+ }
+ }
+ class Local2 {
+ void test() {
+ final int b;
+ b = 20;
+ class DeepLocal extends Local1 {
+ public String toString() {
+ return "" + b;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/LambdaInSuperCallCapturingOuterThis.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184989
+ * @summary Incorrect class file created when passing lambda in inner class constructor and outer is subclass
+ * @run main LambdaInSuperCallCapturingOuterThis
+ */
+
+class A8184989 {
+ public boolean test() {
+ return true;
+ }
+
+ class AA {
+ public AA(Condition8184989<AA> condition) {
+ }
+ }
+}
+
+interface Condition8184989<T> {
+ boolean check(T t);
+}
+
+public class LambdaInSuperCallCapturingOuterThis extends A8184989 {
+
+ public LambdaInSuperCallCapturingOuterThis() {
+ new BA();
+ }
+ public class BA extends AA {
+ public BA() {
+ super(o -> test());
+ }
+ }
+ public static void main(String[] args) {
+ LambdaInSuperCallCapturingOuterThis b = new LambdaInSuperCallCapturingOuterThis();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/LambdaInSuperCallCapturingOuterThis2.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184989
+ * @summary Incorrect class file created when passing lambda in inner class constructor and outer is subclass
+ * @run main LambdaInSuperCallCapturingOuterThis2
+ */
+
+class A8184989_2 {
+ public boolean test() {
+ return true;
+ }
+ class AA {
+ public AA(Condition8184989_2<AA> condition) {
+ if (condition.check(this) != true) {
+ throw new AssertionError("Incorrect output");
+ }
+ }
+ }
+}
+
+interface Condition8184989_2<T> {
+ boolean check(T t);
+}
+
+public class LambdaInSuperCallCapturingOuterThis2 extends A8184989_2 {
+ public boolean test() {return false;}
+ public void b() {}
+
+ class C extends A8184989_2 {
+ public class BA extends AA {
+ public BA() {
+ super(o -> {b(); return test();});
+ }
+ }
+ }
+ public static void main(String[] args) {
+ new LambdaInSuperCallCapturingOuterThis2().new C().new BA();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/LambdaInSuperCallCapturingOuterThis3.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184989
+ * @summary Incorrect class file created when passing lambda in inner class constructor and outer is subclass
+ * @run main LambdaInSuperCallCapturingOuterThis3
+ */
+
+interface I8184989_3 {
+ public default boolean test(){
+ return true;
+ }
+}
+
+class A8184989_3 implements I8184989_3 {
+ class AA {
+ public AA(Condition8184989_3<AA> condition) {
+ if (condition.check(this) != true) {
+ throw new AssertionError("Incorrect output");
+ }
+ }
+ }
+}
+
+interface Condition8184989_3<T> {
+ boolean check(T t);
+}
+
+public class LambdaInSuperCallCapturingOuterThis3 extends A8184989_3 {
+ public boolean test() {return false;}
+ public void b() {}
+
+ class C extends A8184989_3 {
+ public class BA extends AA {
+ public BA() {
+ super(o -> {b(); return test();});
+ }
+ }
+ }
+ public static void main(String[] args) {
+ new LambdaInSuperCallCapturingOuterThis3().new C().new BA();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/tree/VarTree.java Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8188225
+ * @summary Check that variables of type var have a consistent model
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ */
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.tools.javac.api.JavacTaskImpl;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+
+public class VarTree {
+ private final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+
+ public static void main(String... args) throws Exception {
+ VarTree test = new VarTree();
+ test.run("|var testVar = 0;| ",
+ "int testVar = 0");
+ test.run("|var testVar = 0;| undef undef;",
+ "int testVar = 0");
+ test.run("|final var testVar = 0;| ",
+ "final int testVar = 0");
+ test.run("for (|var testVar| : java.util.Arrays.asList(0, 1)) {}",
+ "java.lang.Integer testVar");
+ test.run("for (|final var testVar| : java.util.Arrays.asList(0, 1)) {}",
+ "final java.lang.Integer testVar");
+ test.run("java.util.function.Consumer<String> c = |testVar| -> {};",
+ "java.lang.String testVar");
+ test.run("java.util.function.Consumer<String> c = (|testVar|) -> {};",
+ "java.lang.String testVar");
+ }
+
+ void run(String code, String expected) throws IOException {
+ String[] parts = code.split("\\|");
+
+ if (parts.length != 3) {
+ throw new IllegalStateException("Incorrect number of markers.");
+ }
+
+ String prefix = "public class Test { void test() { ";
+ String src = prefix + parts[0] + parts[1] + parts[2] + " } }";
+
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, d -> {},
+ List.of("--should-stop:at=FLOW"),
+ null, Arrays.asList(new MyFileObject(src)));
+
+ Iterable<? extends CompilationUnitTree> units = ct.parse();
+ ct.analyze();
+
+ Trees trees = Trees.instance(ct);
+
+ for (CompilationUnitTree cut : units) {
+ new TreeScanner<Void, Void>() {
+ @Override
+ public Void visitVariable(VariableTree node, Void p) {
+ if (node.getName().contentEquals("testVar")) {
+ if (!expected.equals(node.toString())) {
+ throw new AssertionError("Unexpected tree: " + node.toString());
+ }
+
+ int start = (int) trees.getSourcePositions().getStartPosition(cut, node);
+ int end = (int) trees.getSourcePositions().getEndPosition(cut, node);
+
+ String snip = src.substring(start, end);
+
+ if (start != prefix.length() + parts[0].length() || end != prefix.length() + parts[0].length() + parts[1].length()) {
+ throw new AssertionError("Unexpected span: " + snip);
+ }
+
+ int typeStart = (int) trees.getSourcePositions().getStartPosition(cut, node.getType());
+ int typeEnd = (int) trees.getSourcePositions().getEndPosition(cut, node.getType());
+
+ if (typeStart != (-1) && typeEnd != (-1)) {
+ throw new AssertionError("Unexpected type position: " + typeStart + ", " + typeEnd);
+ }
+ }
+ return super.visitVariable(node, p);
+ }
+
+ }.scan(cut, null);
+ }
+ }
+ class MyFileObject extends SimpleJavaFileObject {
+
+ private String text;
+
+ public MyFileObject(String text) {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ this.text = text;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return text;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/make/TestCopyFiles.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include UtilsForTests.gmk
+
+THIS_FILE := $(TOPDIR)/test/make/TestCopyFiles.gmk
+DEPS := $(THIS_FILE) \
+ $(TOPDIR)/make/common/MakeBase.gmk \
+ #
+
+OUTPUT_DIR := $(TESTMAKE_OUTPUTDIR)/copy-files
+$(call MakeDir, $(OUTPUT_DIR))
+
+################################################################################
+# Test SetupCopyFiles with CacheFind and files with spaces in their names.
+
+SRC_DIR := $(OUTPUT_DIR)/src
+DEST_DIR := $(OUTPUT_DIR)/dest
+
+$(OUTPUT_DIR)/_src_created: $(DEPS)
+ $(RM) -r $(SRC_DIR)
+ $(MKDIR) -p $(SRC_DIR)
+ $(MKDIR) -p $(SRC_DIR)/foo
+ $(TOUCH) $(SRC_DIR)/file
+ $(TOUCH) $(SRC_DIR)/foo/foofile
+ $(TOUCH) "$(SRC_DIR)/foo/foo file"
+ # Spaces in directories only works with gnu make 4.0 or later
+ ifeq (4.0, $(firstword $(sort 4.0 $(MAKE_VERSION))))
+ $(MKDIR) -p "$(SRC_DIR)/foo bar"
+ $(TOUCH) "$(SRC_DIR)/foo bar/foobarfile"
+ $(TOUCH) "$(SRC_DIR)/foo bar/foo bar file"
+ endif
+ $(LN) -s file "$(SRC_DIR)/link to file"
+ $(TOUCH) $@
+
+$(eval $(call SetupCopyFiles, COPY_1, \
+ SRC := $(SRC_DIR), \
+ DEST := $(DEST_DIR), \
+ FILES := $(call CacheFind, $(SRC_DIR)), \
+))
+
+do-copy1: $(COPY_1)
+
+run-test1: $(OUTPUT_DIR)/_src_created
+ +$(MAKE) -f $(THIS_FILE) do-copy1
+ $(DIFF) -r $(SRC_DIR) $(DEST_DIR)
+
+TEST_TARGETS += run-test1
+
+.PHONY: do-copy1 run-test1
+
+################################################################################
+
+all: $(TEST_TARGETS)
--- a/test/make/TestIdea.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/test/make/TestIdea.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -35,11 +35,11 @@
verify-idea:
$(MKDIR) -p $(IDEA_OUTPUT_DIR)
- $(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea1
- $(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea2 java.base
- $(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea3 java.base jdk.compiler
+ MAKEFLAGS= MFLAGS= $(BASH) $(TOPDIR)/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea1
+ MAKEFLAGS= MFLAGS= $(BASH) $(TOPDIR)/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea2 java.base
+ MAKEFLAGS= MFLAGS= $(BASH) $(TOPDIR)/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea3 java.base jdk.compiler
-TEST_TARGETS += verify-idea
+TEST_TARGETS += verify-idea
all: $(TEST_TARGETS)
--- a/test/make/TestJavaCompilation.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/test/make/TestJavaCompilation.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -29,6 +29,7 @@
include MakeBase.gmk
include JarArchive.gmk
include JavaCompilation.gmk
+include UtilsForTests.gmk
THIS_FILE := $(TOPDIR)/test/make/TestJavaCompilation.gmk
DEPS := $(THIS_FILE) \
@@ -90,8 +91,8 @@
create-jar2: $(OUTPUT_DIR)/_jar1_verified
TEST_TARGETS += $(OUTPUT_DIR)/_jar1_verified
-# Change a source file and call this makefile again to force the jar to be
-# updated.
+# Change a source file and call this makefile again to force the jar to be
+# updated.
$(OUTPUT_DIR)/_jar1_updated: $(OUTPUT_DIR)/_jar1_verified
$(ECHO) updated > $(JAR1_SRC_ROOT)/dir1/file1.class
$(ECHO) updated > $(JAR1_SRC_ROOT)/META-INF/metafile
@@ -104,6 +105,7 @@
# Change the manifest file and call this makefile again to force the jar
# to be updated
$(OUTPUT_DIR)/_jar1_updated_manifest: $(OUTPUT_DIR)/_jar1_updated
+ $(SLEEP_ON_MAC)
$(ECHO) "Test-Attribute: foobar" > $(JAR1_MANIFEST)
+$(MAKE) -f $(THIS_FILE) $(BUILD_JAR1)
$(RM) -r $(JAR1_UNZIP)
--- a/test/make/TestMake.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/test/make/TestMake.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -33,10 +33,13 @@
java-compilation:
+$(MAKE) -f TestJavaCompilation.gmk $(TEST_SUBTARGET)
+copy-files:
+ +$(MAKE) -f TestCopyFiles.gmk $(TEST_SUBTARGET)
+
test-idea:
+$(MAKE) -f TestIdea.gmk $(TEST_SUBTARGET)
-all: make-base java-compilation test-idea
+all: make-base java-compilation copy-files test-idea
-.PHONY: default all make-base java-compilation test-idea
+.PHONY: default all make-base java-compilation copy-files test-idea
--- a/test/make/TestMakeBase.gmk Wed Oct 18 13:52:32 2017 -0700
+++ b/test/make/TestMakeBase.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -27,28 +27,13 @@
include $(SPEC)
include MakeBase.gmk
+include UtilsForTests.gmk
THIS_FILE := $(TOPDIR)/test/make/TestMakeBase.gmk
DEPS := $(THIS_FILE) \
$(TOPDIR)/make/common/MakeBase.gmk \
#
-# Assert two strings are equal
-# 1 - Tested value
-# 2 - Exepected value
-# 3 - Error message
-define assert-equals
- ifneq ($$(strip $1),$$(strip $2))
- $$(error $3 - Expected >$$(strip $2)< - Got >$$(strip $1)<)
- endif
-endef
-
-# On macosx, file system timestamps only have 1 second resultion so must add
-# sleeps to properly test dependencies.
-ifeq ($(OPENJDK_BUILD_OS), macosx)
- SLEEP_ON_MAC := sleep 1
-endif
-
OUTPUT_DIR := $(TESTMAKE_OUTPUTDIR)/make-base
$(call MakeDir, $(OUTPUT_DIR))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/make/UtilsForTests.gmk Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# This file contains utilities common for multiple test makefiles.
+
+# Assert two strings are equal
+# 1 - Tested value
+# 2 - Exepected value
+# 3 - Error message
+define assert-equals
+ ifneq ($$(strip $1),$$(strip $2))
+ $$(error $3 - Expected >$$(strip $2)< - Got >$$(strip $1)<)
+ endif
+endef
+
+# On macosx, file system timestamps only have 1 second resultion so must add
+# sleeps to properly test dependencies.
+ifeq ($(OPENJDK_BUILD_OS), macosx)
+ SLEEP_ON_MAC := sleep 1
+endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8027302.js Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8027302: Identifiers containing unicode escapes are not recognized as reserved words
+ *
+ * @test
+ * @run
+ */
+
+// keywords containing escapes
+
+try {
+ eval("v\\u0061r i;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("\\u0069f (true) ;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof ReferenceError); // no SyntaxError in ES5
+}
+
+try {
+ eval("if (true) ; \\u0065lse ;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof ReferenceError); // no SyntaxError in ES5
+}
+
+try {
+ eval("f\\u0075nction x() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var f = f\\u0075nction() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var o = { f: f\\u0075nction() {}}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var a = [f\\u0075nction() {}]");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+// keywords as identifiers, with and without escapes
+
+try {
+ eval("function break() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("function bre\\u0061k() {}");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("function f(break) {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("function f(bre\\u0061k) {}");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("var break = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("'use strict'; var break = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var bre\\u0061k = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("'use strict'; var bre\\u0061k = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("var package = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("'use strict'; var package = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var p\\u0061ckage = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("'use strict'; var p\\u0061ckage = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/es6/JDK-8027302.js Wed Oct 18 21:05:09 2017 +0000
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8027302: Identifiers containing unicode escapes are not recognized as reserved words
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+// keywords containing escapes
+
+try {
+ eval("v\\u0061r i;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("\\u0069f (true) ;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("if (true) ; \\u0065lse ;");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("f\\u0075nction x() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var f = f\\u0075nction() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var o = { f: f\\u0075nction() {}}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var a = [f\\u0075nction() {}]");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+// keywords as identifiers, with and without escapes
+
+try {
+ eval("function break() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("function bre\\u0061k() {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("function f(break) {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("function f(bre\\u0061k) {}");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var break = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("'use strict'; var break = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var bre\\u0061k = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("'use strict'; var bre\\u0061k = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var package = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("'use strict'; var package = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+
+try {
+ eval("var p\\u0061ckage = 3");
+} catch (e) {
+ fail("Unexpected error");
+}
+
+try {
+ eval("'use strict'; var p\\u0061ckage = 3");
+ fail("Expected error");
+} catch (e) {
+ Assert.assertTrue(e instanceof SyntaxError);
+}
+