# HG changeset patch
# User alanb
# Date 1550867802 0
# Node ID 7a45c67e73d0ad4444509777b6e7eaa28867a12c
# Parent 30695f27d7ea32dd157a00bff39542dc6a407e78# Parent 7a6fd71449e7de1d20fae6f7e89e29c111ce44ab
Merge
diff -r 30695f27d7ea -r 7a45c67e73d0 .hgtags
--- a/.hgtags Fri Feb 22 17:03:09 2019 +0000
+++ b/.hgtags Fri Feb 22 20:36:42 2019 +0000
@@ -543,3 +543,6 @@
021917019cda1c0c5853255322274f37693a2431 jdk-13+7
b5f7bb57de2f797be34f6c75d45c3245ad37ab97 jdk-12+31
a535ba736cabc6886acdff36de3a096c46e5ddc5 jdk-13+8
+4ce47bc1fb92cf94c6e3d1f49d582f02dcb851ab jdk-12+32
+c081f3ea6b9300265a4a34e38f970b1e3ddaae9f jdk-13+9
+b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12+33
diff -r 30695f27d7ea -r 7a45c67e73d0 make/RunTests.gmk
--- a/make/RunTests.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/RunTests.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -112,6 +112,9 @@
GTEST_VARIANTS := $(strip $(patsubst $(TEST_IMAGE_DIR)/hotspot/gtest/%, %, \
$(GTEST_LAUNCHER_DIRS)))
+COV_ENVIRONMENT :=
+JTREG_COV_OPTIONS :=
+
ifeq ($(TEST_OPTS_JCOV), true)
JCOV_OUTPUT_DIR := $(TEST_RESULTS_DIR)/jcov-output
JCOV_GRABBER_LOG := $(JCOV_OUTPUT_DIR)/grabber.log
@@ -122,12 +125,18 @@
# Replace our normal test JDK with the JCov image.
JDK_UNDER_TEST := $(JCOV_IMAGE_DIR)
- JCOV_ENVIRONMENT := JAVA_TOOL_OPTIONS="$(JCOV_MEM_OPTIONS)" \
+ COV_ENVIRONMENT += JAVA_TOOL_OPTIONS="$(JCOV_MEM_OPTIONS)" \
_JAVA_OPTIONS="$(JCOV_MEM_OPTIONS)"
- JTREG_JCOV_OPTIONS := -e:JAVA_TOOL_OPTIONS='$(JCOV_MEM_OPTIONS)' \
+ JTREG_COV_OPTIONS += -e:JAVA_TOOL_OPTIONS='$(JCOV_MEM_OPTIONS)' \
-e:_JAVA_OPTIONS='$(JCOV_MEM_OPTIONS)'
endif
+ifeq ($(GCOV_ENABLED), true)
+ GCOV_OUTPUT_DIR := $(TEST_RESULTS_DIR)/gcov-output
+ COV_ENVIRONMENT += GCOV_PREFIX="$(GCOV_OUTPUT_DIR)"
+ JTREG_COV_OPTIONS += -e:GCOV_PREFIX="$(GCOV_OUTPUT_DIR)"
+endif
+
################################################################################
# Optionally create AOT libraries for specified modules before running tests.
# Note, this could not be done during JDK build time.
@@ -170,6 +179,7 @@
$$(call LogWarn, Generating $$(patsubst $$(OUTPUTDIR)/%, %, $$@))
$$(call MakeTargetDir)
$$(call ExecuteWithLog, $$@, \
+ $((COV_ENVIRONMENT) \
$$(FIXPATH) $$(JDK_UNDER_TEST)/bin/jaotc \
$$($1_JAOTC_OPTS) --output $$@ --module $$($1_MODULE) \
)
@@ -658,6 +668,8 @@
# Current tests needs to open java.io
$1_MICRO_JAVA_OPTIONS += --add-opens=java.base/java.io=ALL-UNNAMED
+ # Set library path for native dependencies
+ $1_MICRO_JAVA_OPTIONS += -Djava.library.path=$$(TEST_IMAGE_DIR)/micro/native
# Save output as JSON or CSV file
ifneq ($$(MICRO_RESULTS_FORMAT), )
@@ -690,7 +702,8 @@
$$(call LogWarn, Running test '$$($1_TEST)')
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/micro, \
- $$($1_MICRO_TEST_JDK)/bin/java $$($1_MICRO_JAVA_OPTIONS) -jar $$($1_MICRO_BENCHMARKS_JAR) \
+ $$(FIXPATH) $$($1_MICRO_TEST_JDK)/bin/java $$($1_MICRO_JAVA_OPTIONS) \
+ -jar $$($1_MICRO_BENCHMARKS_JAR) \
$$($1_MICRO_ITER) $$($1_MICRO_FORK) $$($1_MICRO_TIME) \
$$($1_MICRO_WARMUP_ITER) $$($1_MICRO_WARMUP_TIME) \
$$($1_MICRO_VM_OPTIONS) $$($1_MICRO_BASIC_OPTIONS) $$(MICRO_OPTIONS) \
@@ -904,7 +917,7 @@
$$(call LogWarn, Running test '$$($1_TEST)')
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/jtreg, \
- $$(JCOV_ENVIRONMENT) \
+ $$(COV_ENVIRONMENT) \
$$(JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \
-Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \
$$($1_JTREG_BASIC_OPTIONS) \
@@ -914,7 +927,7 @@
-workDir:$$($1_TEST_SUPPORT_DIR) \
$$(JTREG_OPTIONS) \
$$(JTREG_FAILURE_HANDLER_OPTIONS) \
- $$(JTREG_JCOV_OPTIONS) \
+ $$(JTREG_COV_OPTIONS) \
$$($1_TEST_NAME) \
&& $$(ECHO) $$$$? > $$($1_EXITCODE) \
|| $$(ECHO) $$$$? > $$($1_EXITCODE) \
diff -r 30695f27d7ea -r 7a45c67e73d0 make/autoconf/basics.m4
--- a/make/autoconf/basics.m4 Fri Feb 22 17:03:09 2019 +0000
+++ b/make/autoconf/basics.m4 Fri Feb 22 20:36:42 2019 +0000
@@ -618,14 +618,6 @@
BASIC_PATH_PROGS(CPIO, [cpio bsdcpio])
BASIC_PATH_PROGS(NICE, nice)
- BASIC_PATH_PROGS(PANDOC, pandoc)
- if test -n "$PANDOC"; then
- ENABLE_PANDOC="true"
- else
- ENABLE_PANDOC="false"
- fi
- AC_SUBST(ENABLE_PANDOC)
-
BASIC_PATH_PROGS(LSB_RELEASE, lsb_release)
BASIC_PATH_PROGS(CMD, [cmd.exe /mnt/c/Windows/System32/cmd.exe])
])
@@ -1193,6 +1185,7 @@
BASIC_CHECK_FIND_DELETE
BASIC_CHECK_TAR
BASIC_CHECK_GREP
+ BASIC_SETUP_PANDOC
# These tools might not be installed by default,
# need hint on how to install them.
@@ -1379,6 +1372,34 @@
################################################################################
#
+# Setup Pandoc
+#
+AC_DEFUN_ONCE([BASIC_SETUP_PANDOC],
+[
+ BASIC_PATH_PROGS(PANDOC, pandoc)
+
+ PANDOC_MARKDOWN_FLAG="markdown"
+ if test -n "$PANDOC"; then
+ AC_MSG_CHECKING(if the pandoc smart extension needs to be disabled for markdown)
+ if $PANDOC --list-extensions | $GREP -q '\+smart'; then
+ AC_MSG_RESULT([yes])
+ PANDOC_MARKDOWN_FLAG="markdown-smart"
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+
+ if test -n "$PANDOC"; then
+ ENABLE_PANDOC="true"
+ else
+ ENABLE_PANDOC="false"
+ fi
+ AC_SUBST(ENABLE_PANDOC)
+ AC_SUBST(PANDOC_MARKDOWN_FLAG)
+])
+
+################################################################################
+#
# Default make target
#
AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_MAKE_TARGET],
diff -r 30695f27d7ea -r 7a45c67e73d0 make/autoconf/flags-cflags.m4
--- a/make/autoconf/flags-cflags.m4 Fri Feb 22 17:03:09 2019 +0000
+++ b/make/autoconf/flags-cflags.m4 Fri Feb 22 20:36:42 2019 +0000
@@ -121,7 +121,11 @@
# -g0 enables debug symbols without disabling inlining.
CFLAGS_DEBUG_SYMBOLS="-g0 -xs"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- CFLAGS_DEBUG_SYMBOLS="-g"
+ if test "x$XLC_USES_CLANG" = xtrue; then
+ CFLAGS_DEBUG_SYMBOLS="-g1"
+ else
+ CFLAGS_DEBUG_SYMBOLS="-g"
+ fi
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
CFLAGS_DEBUG_SYMBOLS="-Z7 -d2Zi+"
fi
diff -r 30695f27d7ea -r 7a45c67e73d0 make/autoconf/jdk-options.m4
--- a/make/autoconf/jdk-options.m4 Fri Feb 22 17:03:09 2019 +0000
+++ b/make/autoconf/jdk-options.m4 Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -364,7 +364,7 @@
################################################################################
#
-# Gcov coverage data for hotspot
+# Native and Java code coverage
#
AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
[
@@ -372,23 +372,26 @@
[enable native compilation with code coverage data@<:@disabled@:>@])])
GCOV_ENABLED="false"
if test "x$enable_native_coverage" = "xyes"; then
- if test "x$TOOLCHAIN_TYPE" = "xgcc"; then
- AC_MSG_CHECKING([if native coverage is enabled])
- AC_MSG_RESULT([yes])
- GCOV_CFLAGS="-fprofile-arcs -ftest-coverage -fno-inline"
- GCOV_LDFLAGS="-fprofile-arcs"
- JVM_CFLAGS="$JVM_CFLAGS $GCOV_CFLAGS"
- JVM_LDFLAGS="$JVM_LDFLAGS $GCOV_LDFLAGS"
- CFLAGS_JDKLIB="$CFLAGS_JDKLIB $GCOV_CFLAGS"
- CFLAGS_JDKEXE="$CFLAGS_JDKEXE $GCOV_CFLAGS"
- CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $GCOV_CFLAGS"
- CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $GCOV_CFLAGS"
- LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $GCOV_LDFLAGS"
- LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $GCOV_LDFLAGS"
- GCOV_ENABLED="true"
- else
- AC_MSG_ERROR([--enable-native-coverage only works with toolchain type gcc])
- fi
+ case $TOOLCHAIN_TYPE in
+ gcc | clang)
+ AC_MSG_CHECKING([if native coverage is enabled])
+ AC_MSG_RESULT([yes])
+ GCOV_CFLAGS="-fprofile-arcs -ftest-coverage -fno-inline"
+ GCOV_LDFLAGS="-fprofile-arcs"
+ JVM_CFLAGS="$JVM_CFLAGS $GCOV_CFLAGS"
+ JVM_LDFLAGS="$JVM_LDFLAGS $GCOV_LDFLAGS"
+ CFLAGS_JDKLIB="$CFLAGS_JDKLIB $GCOV_CFLAGS"
+ CFLAGS_JDKEXE="$CFLAGS_JDKEXE $GCOV_CFLAGS"
+ CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $GCOV_CFLAGS"
+ CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $GCOV_CFLAGS"
+ LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $GCOV_LDFLAGS"
+ LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $GCOV_LDFLAGS"
+ GCOV_ENABLED="true"
+ ;;
+ *)
+ AC_MSG_ERROR([--enable-native-coverage only works with toolchain type gcc or clang])
+ ;;
+ esac
elif test "x$enable_native_coverage" = "xno"; then
AC_MSG_CHECKING([if native coverage is enabled])
AC_MSG_RESULT([no])
diff -r 30695f27d7ea -r 7a45c67e73d0 make/autoconf/spec.gmk.in
--- a/make/autoconf/spec.gmk.in Fri Feb 22 17:03:09 2019 +0000
+++ b/make/autoconf/spec.gmk.in Fri Feb 22 20:36:42 2019 +0000
@@ -774,6 +774,7 @@
UCRT_DLL_DIR:=@UCRT_DLL_DIR@
STLPORT_LIB:=@STLPORT_LIB@
ENABLE_PANDOC:=@ENABLE_PANDOC@
+PANDOC_MARKDOWN_FLAG:=@PANDOC_MARKDOWN_FLAG@
####################################################
#
diff -r 30695f27d7ea -r 7a45c67e73d0 make/autoconf/toolchain.m4
--- a/make/autoconf/toolchain.m4 Fri Feb 22 17:03:09 2019 +0000
+++ b/make/autoconf/toolchain.m4 Fri Feb 22 20:36:42 2019 +0000
@@ -276,6 +276,20 @@
fi
AC_SUBST(TOOLCHAIN_TYPE)
+ # on AIX, check for xlclang++ on the PATH and TOOLCHAIN_PATH and use it if it is available
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ if test "x$TOOLCHAIN_PATH" != x; then
+ XLC_TEST_PATH=${TOOLCHAIN_PATH}/
+ fi
+
+ XLCLANG_VERSION_OUTPUT=`${XLC_TEST_PATH}xlclang++ -qversion 2>&1 | $HEAD -n 1`
+ $ECHO "$XLCLANG_VERSION_OUTPUT" | $GREP "IBM XL C/C++ for AIX" > /dev/null
+ if test $? -eq 0; then
+ AC_MSG_NOTICE([xlclang++ output: $XLCLANG_VERSION_OUTPUT])
+ XLC_USES_CLANG=true
+ fi
+ fi
+
TOOLCHAIN_CC_BINARY_clang="clang"
TOOLCHAIN_CC_BINARY_gcc="gcc"
TOOLCHAIN_CC_BINARY_microsoft="cl$EXE_SUFFIX"
@@ -288,6 +302,14 @@
TOOLCHAIN_CXX_BINARY_solstudio="CC"
TOOLCHAIN_CXX_BINARY_xlc="xlC_r"
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ if test "x$XLC_USES_CLANG" = xtrue; then
+ AC_MSG_NOTICE([xlclang++ detected, using it])
+ TOOLCHAIN_CC_BINARY_xlc="xlclang"
+ TOOLCHAIN_CXX_BINARY_xlc="xlclang++"
+ fi
+ fi
+
# Use indirect variable referencing
toolchain_var_name=TOOLCHAIN_DESCRIPTION_$TOOLCHAIN_TYPE
TOOLCHAIN_DESCRIPTION=${!toolchain_var_name}
diff -r 30695f27d7ea -r 7a45c67e73d0 make/common/MakeBase.gmk
--- a/make/common/MakeBase.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/common/MakeBase.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -392,9 +392,10 @@
#
# Param 1 - Dirs to find in
# Param 2 - (optional) specialization. Normally "-a \( ... \)" expression.
+ # Param 3 - (optional) options to find.
define CacheFind
$(if $(filter-out $(addsuffix /%,- $(FIND_CACHE_DIRS)) $(FIND_CACHE_DIRS),$1), \
- $(if $(wildcard $1), $(shell $(FIND) $(wildcard $1) \( -type f -o -type l \) $2 \
+ $(if $(wildcard $1), $(shell $(FIND) $3 $(wildcard $1) \( -type f -o -type l \) $2 \
| $(TR) ' ' '?')), \
$(filter $(addsuffix /%,$(patsubst %/,%,$1)) $1,$(FIND_CACHE)))
endef
diff -r 30695f27d7ea -r 7a45c67e73d0 make/common/ProcessMarkdown.gmk
--- a/make/common/ProcessMarkdown.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/common/ProcessMarkdown.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -80,7 +80,8 @@
$$(call LogInfo, Converting $2 to $$($1_FORMAT))
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT)))
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \
- $$(PANDOC) $$($1_OPTIONS) -f markdown-smart -t $$($1_FORMAT) --standalone \
+ $$(PANDOC) $$($1_OPTIONS) -f $$(PANDOC_MARKDOWN_FLAG) \
+ -t $$($1_FORMAT) --standalone \
$$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS) '$$($1_$2_PANDOC_INPUT)' \
-o '$$($1_$2_PANDOC_OUTPUT)')
ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
diff -r 30695f27d7ea -r 7a45c67e73d0 make/common/ZipArchive.gmk
--- a/make/common/ZipArchive.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/common/ZipArchive.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -62,8 +62,9 @@
$1_FIND_LIST := $$($1_SRC)
endif
- # Find all files in the source tree.
- $1_ALL_SRCS := $$(call not-containing,_the.,$$(call CacheFind,$$($1_FIND_LIST)))
+ # Find all files in the source tree. Follow symlinks in this find since that is
+ # what zip does.
+ $1_ALL_SRCS := $$(call not-containing,_the.,$$(call CacheFind,$$($1_FIND_LIST), , -L))
# Filter on suffixes if set
ifneq ($$($1_SUFFIXES),)
@@ -126,10 +127,14 @@
$$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS)
$$(call LogWarn, Updating $$($1_NAME))
$$(call MakeTargetDir)
- $$(foreach s,$$($1_SRC),(cd $$s && $(ZIPEXE) -qru $$($1_ZIP_OPTIONS) $$@ . \
- $$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* \
- $$($1_ZIP_EXCLUDES_$$s) \
- || test "$$$$?" = "12" )$$(NEWLINE)) true
+ $$(foreach s,$$($1_SRC), $$(call ExecuteWithLog, \
+ $$(SUPPORT_OUTPUTDIR)/zip/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \
+ (cd $$s && $(ZIPEXE) -qru $$($1_ZIP_OPTIONS) $$@ . \
+ $$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* \
+ $$($1_ZIP_EXCLUDES_$$s) \
+ || test "$$$$?" = "12" \
+ ))$$(NEWLINE) \
+ ) true \
$(TOUCH) $$@
# Add zip to target list
diff -r 30695f27d7ea -r 7a45c67e73d0 make/conf/jib-profiles.js
--- a/make/conf/jib-profiles.js Fri Feb 22 17:03:09 2019 +0000
+++ b/make/conf/jib-profiles.js Fri Feb 22 20:36:42 2019 +0000
@@ -241,7 +241,7 @@
common.main_profile_names = [
"linux-x64", "linux-x86", "macosx-x64", "solaris-x64",
"solaris-sparcv9", "windows-x64", "windows-x86",
- "linux-aarch64", "linux-arm32"
+ "linux-aarch64", "linux-arm32", "linux-ppc64le", "linux-s390x"
];
// These are the base setttings for all the main build profiles.
@@ -464,6 +464,28 @@
"--with-abi-profile=arm-vfp-hflt", "--disable-warnings-as-errors"
],
},
+
+ "linux-ppc64le": {
+ target_os: "linux",
+ target_cpu: "ppc64le",
+ build_cpu: "x64",
+ dependencies: ["devkit", "build_devkit", "cups"],
+ configure_args: [
+ "--openjdk-target=ppc64le-linux-gnu", "--with-freetype=bundled",
+ "--disable-warnings-as-errors"
+ ],
+ },
+
+ "linux-s390x": {
+ target_os: "linux",
+ target_cpu: "s390x",
+ build_cpu: "x64",
+ dependencies: ["devkit", "build_devkit", "cups"],
+ configure_args: [
+ "--openjdk-target=s390x-linux-gnu", "--with-freetype=bundled",
+ "--disable-warnings-as-errors"
+ ],
+ },
};
// Add the base settings to all the main profiles
@@ -499,6 +521,15 @@
profiles[maketestName].default_make_targets = [ "test-make" ];
});
+ // Generate -gcov profiles
+ [ "linux-x64", "macosx-x64" ].forEach(function (name) {
+ var gcovName = name + "-gcov";
+ profiles[gcovName] = clone(profiles[name]);
+ profiles[gcovName].default_make_targets = ["product-bundles", "test-bundles"];
+ profiles[gcovName].configure_args = concat(profiles[gcovName].configure_args,
+ ["--enable-native-coverage", "--disable-warnings-as-errors"]);
+ });
+
// Profiles for building the zero jvm variant. These are used for verification.
var zeroProfiles = {
"linux-x64-zero": {
@@ -626,6 +657,12 @@
},
"linux-arm32": {
platform: "linux-arm32",
+ },
+ "linux-ppc64le": {
+ platform: "linux-ppc64le",
+ },
+ "linux-s390x": {
+ platform: "linux-s390x",
}
}
// Generate common artifacts for all main profiles
@@ -744,6 +781,40 @@
};
});
+ // Artifacts of gcov (native-code-coverage) profiles
+ [ "linux-x64", "macosx-x64" ].forEach(function (name) {
+ var o = artifactData[name]
+ var pf = o.platform
+ var jdk_subdir = (o.jdk_subdir != null ? o.jdk_subdir : "jdk-" + data.version);
+ var jdk_suffix = (o.jdk_suffix != null ? o.jdk_suffix : "tar.gz");
+ var gcovName = name + "-gcov";
+ profiles[gcovName].artifacts = {
+ jdk: {
+ local: "bundles/\\(jdk.*bin." + jdk_suffix + "\\)",
+ remote: [
+ "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin-gcov." + jdk_suffix,
+ ],
+ subdir: jdk_subdir,
+ exploded: "images/jdk",
+ },
+ test: {
+ local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
+ remote: [
+ "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin-gcov-tests.tar.gz",
+ ],
+ exploded: "images/test"
+ },
+ jdk_symbols: {
+ local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
+ remote: [
+ "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin-gcov-symbols.tar.gz",
+ ],
+ subdir: jdk_subdir,
+ exploded: "images/jdk"
+ },
+ };
+ });
+
// Profiles used to run tests.
var testOnlyProfiles = {
"run-test": {
@@ -770,6 +841,10 @@
} else {
testedProfileTest = testedProfile + ".test";
}
+ var testOnlyMake = [ "run-test-prebuilt", "LOG_CMDLINES=true", "JTREG_VERBOSE=fail,error,time" ];
+ if (testedProfile.endsWith("-gcov")) {
+ testOnlyMake = concat(testOnlyMake, "GCOV_ENABLED=true")
+ }
var testOnlyProfilesPrebuilt = {
"run-test-prebuilt": {
target_os: input.build_os,
@@ -779,7 +854,7 @@
testedProfileTest
],
src: "src.conf",
- make_args: [ "run-test-prebuilt", "LOG_CMDLINES=true", "JTREG_VERBOSE=fail,error,time" ],
+ make_args: testOnlyMake,
environment: {
"BOOT_JDK": common.boot_jdk_home,
"JDK_IMAGE_DIR": input.get(testedProfileJDK, "home_path"),
@@ -870,7 +945,9 @@
solaris_sparcv9: "SS12u6-Solaris11u3+1.0",
windows_x64: "VS2017-15.5.5+1.0",
linux_aarch64: "gcc7.3.0-Fedora27+1.2",
- linux_arm: "gcc7.3.0-Fedora27+1.2"
+ linux_arm: "gcc7.3.0-Fedora27+1.2",
+ linux_ppc64le: "gcc7.3.0-Fedora27+1.0",
+ linux_s390x: "gcc7.3.0-Fedora27+1.0"
};
var devkit_platform = (input.target_cpu == "x86"
@@ -930,7 +1007,7 @@
jtreg: {
server: "javare",
revision: "4.2",
- build_number: "b13",
+ build_number: "b14",
checksum_file: "MD5_VALUES",
file: "jtreg_bin-4.2.zip",
environment_name: "JT_HOME",
diff -r 30695f27d7ea -r 7a45c67e73d0 make/copy/CopyCommon.gmk
--- a/make/copy/CopyCommon.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/copy/CopyCommon.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -66,6 +66,8 @@
# Setup make rules for copying legal files. This is only needed if the files
# need to be filtered due to optional components being enabled/disabled.
# Otherwise CreateJmods.gmk will find the legal files in the original src dirs.
+# If multiple license files with the same name are found, only the first one
+# found will get copied.
#
# Parameter 1 is the name of the rule.
#
@@ -75,10 +77,12 @@
define SetupCopyLegalFilesBody
$$(foreach f, $$(filter-out $$(addprefix %/, $$($1_EXCLUDES)), \
$$(wildcard $$(addsuffix /*, $$(call FindModuleLegalSrcDirs, $$(MODULE))))), \
- $$(eval $$(call SetupCopyFiles, $1_$$(notdir $$f), \
- DEST := $$(LEGAL_DST_DIR), \
- FILES := $$f, \
- )) \
- $$(eval $1 += $$($1_$$(notdir $$f))) \
+ $$(if $$(filter $$($1_$$(notdir $$f)), $$($1)), , \
+ $$(eval $$(call SetupCopyFiles, $1_$$(notdir $$f), \
+ DEST := $$(LEGAL_DST_DIR), \
+ FILES := $$f, \
+ )) \
+ $$(eval $1 += $$($1_$$(notdir $$f))) \
+ ) \
)
endef
diff -r 30695f27d7ea -r 7a45c67e73d0 make/test/BuildMicrobenchmark.gmk
--- a/make/test/BuildMicrobenchmark.gmk Fri Feb 22 17:03:09 2019 +0000
+++ b/make/test/BuildMicrobenchmark.gmk Fri Feb 22 20:36:42 2019 +0000
@@ -30,6 +30,7 @@
include MakeBase.gmk
include JavaCompilation.gmk
include SetupJavaCompilers.gmk
+include TestFilesCompilation.gmk
ifeq ($(JMH_CORE_JAR), )
$(info Error: JMH is missing. Please use configure --with-jmh.)
@@ -39,7 +40,8 @@
#### Variables
MICROBENCHMARK_SRC := $(TOPDIR)/test/micro
-MICROBENCHMARK_JAR := $(IMAGES_OUTPUTDIR)/test/micro/benchmarks.jar
+MICROBENCHMARK_IMAGE_DIR := $(TEST_IMAGE_DIR)/micro
+MICROBENCHMARK_JAR := $(MICROBENCHMARK_IMAGE_DIR)/benchmarks.jar
MICROBENCHMARK_OUTPUT := $(SUPPORT_OUTPUTDIR)/test/micro
MICROBENCHMARK_CLASSES := $(MICROBENCHMARK_OUTPUT)/classes
@@ -54,6 +56,11 @@
MICROBENCHMARK_CLASSPATH := $(call PathList, $(JMH_COMPILE_JARS))
+# Native dependencies
+MICROBENCHMARK_NATIVE_SRC_DIRS := $(MICROBENCHMARK_SRC)
+MICROBENCHMARK_NATIVE_OUTPUT := $(MICROBENCHMARK_OUTPUT)/native
+MICROBENCHMARK_NATIVE_EXCLUDE :=
+
###
# Need double \n to get new lines and no trailing spaces
@@ -108,6 +115,22 @@
JAR := $(MICROBENCHMARK_JAR), \
))
-all: $(MICROBENCHMARK_JAR)
+# Setup compilation of native library dependencies
+$(eval $(call SetupTestFilesCompilation, BUILD_MICROBENCHMARK_LIBRARIES, \
+ TYPE := LIBRARY, \
+ SOURCE_DIRS := $(MICROBENCHMARK_NATIVE_SRC_DIRS), \
+ OUTPUT_DIR := $(MICROBENCHMARK_NATIVE_OUTPUT), \
+ EXCLUDE := $(MICROBENCHMARK_NATIVE_EXCLUDE), \
+))
+
+# Setup copy of native dependencies to image output dir
+$(eval $(call SetupCopyFiles, COPY_MICROBENCHMARK_NATIVE, \
+ SRC := $(MICROBENCHMARK_NATIVE_OUTPUT), \
+ DEST := $(MICROBENCHMARK_IMAGE_DIR)/native, \
+ FILES := $(BUILD_MICROBENCHMARK_LIBRARIES), \
+ FLATTEN := true, \
+))
+
+all: $(MICROBENCHMARK_JAR) $(BUILD_MICROBENCHMARK_LIBRARIES) $(COPY_MICROBENCHMARK_NATIVE)
.PHONY: all
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/ppc/nativeInst_ppc.cpp
--- a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -362,8 +362,8 @@
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
CodeBuffer cb(code_pos, BytesPerInstWord + 1);
- MacroAssembler* a = new MacroAssembler(&cb);
- a->b(entry);
+ MacroAssembler a(&cb);
+ a.b(entry);
ICache::ppc64_flush_icache_bytes(code_pos, NativeGeneralJump::instruction_size);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/s390/frame_s390.cpp
--- a/src/hotspot/cpu/s390/frame_s390.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/s390/frame_s390.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -479,6 +479,7 @@
// name
Method* method = *(Method**)((address)current_fp + _z_ijava_state_neg(method));
if (method) {
+ ResourceMark rm;
if (method->is_synchronized()) st->print("synchronized ");
if (method->is_static()) st->print("static ");
if (method->is_native()) st->print("native ");
@@ -543,6 +544,7 @@
// name
Method* method = ((nmethod *)blob)->method();
if (method) {
+ ResourceMark rm;
method->name_and_sig_as_C_string(buf, sizeof(buf));
st->print("%s ", buf);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/s390/stubGenerator_s390.cpp
--- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1842,6 +1842,51 @@
}
+ // Compute GHASH function.
+ address generate_ghash_processBlocks() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
+
+ const Register state = Z_ARG1;
+ const Register subkeyH = Z_ARG2;
+ const Register data = Z_ARG3; // 1st of even-odd register pair.
+ const Register blocks = Z_ARG4;
+ const Register len = blocks; // 2nd of even-odd register pair.
+
+ const int param_block_size = 4 * 8;
+ const int frame_resize = param_block_size + 8; // Extra space for copy of fp.
+
+ // Reserve stack space for parameter block (R1).
+ __ z_lgr(Z_R1, Z_SP);
+ __ resize_frame(-frame_resize, Z_R0, true);
+ __ z_aghi(Z_R1, -param_block_size);
+
+ // Fill parameter block.
+ __ z_mvc(Address(Z_R1) , Address(state) , 16);
+ __ z_mvc(Address(Z_R1, 16), Address(subkeyH), 16);
+
+ // R4+5: data pointer + length
+ __ z_llgfr(len, blocks); // Cast to 64-bit.
+
+ // R0: function code
+ __ load_const_optimized(Z_R0, (int)VM_Version::MsgDigest::_GHASH);
+
+ // Compute.
+ __ z_sllg(len, len, 4); // In bytes.
+ __ kimd(data);
+
+ // Copy back result and free parameter block.
+ __ z_mvc(Address(state), Address(Z_R1), 16);
+ __ z_xc(Address(Z_R1), param_block_size, Address(Z_R1));
+ __ z_aghi(Z_SP, frame_resize);
+
+ __ z_br(Z_R14);
+
+ return __ addr_at(start_off);
+ }
+
+
// Call interface for all SHA* stubs.
//
// Z_ARG1 - source data block. Ptr to leftmost byte to be processed.
@@ -2305,6 +2350,11 @@
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_AES_decrypt("AES_decryptBlock_chaining");
}
+ // Generate GHASH intrinsics code
+ if (UseGHASHIntrinsics) {
+ StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+ }
+
// Generate SHA1/SHA256/SHA512 intrinsics code.
if (UseSHA1Intrinsics) {
StubRoutines::_sha1_implCompress = generate_SHA1_stub(false, "SHA1_singleBlock");
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/s390/vm_version_s390.cpp
--- a/src/hotspot/cpu/s390/vm_version_s390.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/s390/vm_version_s390.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -165,8 +165,10 @@
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
}
- // TODO: implement GHASH intrinsics
- if (UseGHASHIntrinsics) {
+ if (FLAG_IS_DEFAULT(UseGHASHIntrinsics) && has_Crypto_GHASH()) {
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, true);
+ }
+ if (UseGHASHIntrinsics && !has_Crypto_GHASH()) {
warning("GHASH intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/x86/c2_init_x86.cpp
--- a/src/hotspot/cpu/x86/c2_init_x86.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/x86/c2_init_x86.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -29,6 +29,8 @@
// processor dependent initialization for i486
+LP64_ONLY(extern void reg_mask_init();)
+
void Compile::pd_compiler2_init() {
guarantee(CodeEntryAlignment >= InteriorEntryAlignment, "" );
// QQQ presumably all 64bit cpu's support this. Seems like the ifdef could
@@ -58,4 +60,5 @@
OptoReg::invalidate(i);
}
}
+ LP64_ONLY(reg_mask_init();)
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -359,7 +359,7 @@
// ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded().
static address generate_load_barrier_stub(StubCodeGenerator* cgen, Register raddr, DecoratorSet decorators) {
// Don't generate stub for invalid registers
- if (raddr == rsp || raddr == r12 || raddr == r15) {
+ if (raddr == rsp || raddr == r15) {
return NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/x86/gc/z/z_x86_64.ad
--- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad Fri Feb 22 20:36:42 2019 +0000
@@ -26,9 +26,8 @@
#include "gc/z/zBarrierSetAssembler.hpp"
static void z_load_barrier_slow_reg(MacroAssembler& _masm, Register dst, Address src, bool weak) {
- assert(dst != r12, "Invalid register");
+ assert(dst != rsp, "Invalid register");
assert(dst != r15, "Invalid register");
- assert(dst != rsp, "Invalid register");
const address stub = weak ? ZBarrierSet::assembler()->load_barrier_weak_slow_stub(dst)
: ZBarrierSet::assembler()->load_barrier_slow_stub(dst);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/x86/vm_version_x86.hpp
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -336,7 +336,7 @@
#define CPU_AVX512_VPOPCNTDQ ((uint64_t)UCONST64(0x2000000000)) // Vector popcount
#define CPU_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication
#define CPU_VAES ((uint64_t)UCONST64(0x8000000000)) // Vector AES instructions
-#define CPU_VNNI ((uint64_t)UCONST64(0x16000000000)) // Vector Neural Network Instructions
+#define CPU_VNNI ((uint64_t)UCONST64(0x10000000000)) // Vector Neural Network Instructions
enum Extended_Family {
// AMD
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/cpu/x86/x86_64.ad
--- a/src/hotspot/cpu/x86/x86_64.ad Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/cpu/x86/x86_64.ad Fri Feb 22 20:36:42 2019 +0000
@@ -169,135 +169,94 @@
// Empty register class.
reg_class no_reg();
-// Class for all pointer registers (including RSP and RBP)
-reg_class any_reg_with_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- RSP, RSP_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R12, R12_H,
- R13, R13_H,
- R14, R14_H,
- R15, R15_H);
-
-// Class for all pointer registers (including RSP, but excluding RBP)
-reg_class any_reg_no_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- RSP, RSP_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R12, R12_H,
- R13, R13_H,
- R14, R14_H,
- R15, R15_H);
-
-// Dynamic register class that selects at runtime between register classes
-// any_reg_no_rbp and any_reg_with_rbp (depending on the value of the flag PreserveFramePointer).
-// Equivalent to: return PreserveFramePointer ? any_reg_no_rbp : any_reg_with_rbp;
-reg_class_dynamic any_reg(any_reg_no_rbp, any_reg_with_rbp, %{ PreserveFramePointer %});
+// Class for all pointer/long registers
+reg_class all_reg(RAX, RAX_H,
+ RDX, RDX_H,
+ RBP, RBP_H,
+ RDI, RDI_H,
+ RSI, RSI_H,
+ RCX, RCX_H,
+ RBX, RBX_H,
+ RSP, RSP_H,
+ R8, R8_H,
+ R9, R9_H,
+ R10, R10_H,
+ R11, R11_H,
+ R12, R12_H,
+ R13, R13_H,
+ R14, R14_H,
+ R15, R15_H);
+
+// Class for all int registers
+reg_class all_int_reg(RAX
+ RDX,
+ RBP,
+ RDI,
+ RSI,
+ RCX,
+ RBX,
+ R8,
+ R9,
+ R10,
+ R11,
+ R12,
+ R13,
+ R14);
+
+// Class for all pointer registers
+reg_class any_reg %{
+ return _ANY_REG_mask;
+%}
// Class for all pointer registers (excluding RSP)
-reg_class ptr_reg_with_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
+reg_class ptr_reg %{
+ return _PTR_REG_mask;
+%}
// Class for all pointer registers (excluding RSP and RBP)
-reg_class ptr_reg_no_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between ptr_reg_no_rbp and ptr_reg_with_rbp.
-reg_class_dynamic ptr_reg(ptr_reg_no_rbp, ptr_reg_with_rbp, %{ PreserveFramePointer %});
+reg_class ptr_reg_no_rbp %{
+ return _PTR_REG_NO_RBP_mask;
+%}
// Class for all pointer registers (excluding RAX and RSP)
-reg_class ptr_no_rax_reg_with_rbp(RDX, RDX_H,
- RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Class for all pointer registers (excluding RAX, RSP, and RBP)
-reg_class ptr_no_rax_reg_no_rbp(RDX, RDX_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between ptr_no_rax_reg_no_rbp and ptr_no_rax_reg_with_rbp.
-reg_class_dynamic ptr_no_rax_reg(ptr_no_rax_reg_no_rbp, ptr_no_rax_reg_with_rbp, %{ PreserveFramePointer %});
+reg_class ptr_no_rax_reg %{
+ return _PTR_NO_RAX_REG_mask;
+%}
// Class for all pointer registers (excluding RAX, RBX, and RSP)
-reg_class ptr_no_rax_rbx_reg_with_rbp(RDX, RDX_H,
- RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Class for all pointer registers (excluding RAX, RBX, RSP, and RBP)
-reg_class ptr_no_rax_rbx_reg_no_rbp(RDX, RDX_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between ptr_no_rax_rbx_reg_no_rbp and ptr_no_rax_rbx_reg_with_rbp.
-reg_class_dynamic ptr_no_rax_rbx_reg(ptr_no_rax_rbx_reg_no_rbp, ptr_no_rax_rbx_reg_with_rbp, %{ PreserveFramePointer %});
+reg_class ptr_no_rax_rbx_reg %{
+ return _PTR_NO_RAX_RBX_REG_mask;
+%}
+
+// Class for all long registers (excluding RSP)
+reg_class long_reg %{
+ return _LONG_REG_mask;
+%}
+
+// Class for all long registers (excluding RAX, RDX and RSP)
+reg_class long_no_rax_rdx_reg %{
+ return _LONG_NO_RAX_RDX_REG_mask;
+%}
+
+// Class for all long registers (excluding RCX and RSP)
+reg_class long_no_rcx_reg %{
+ return _LONG_NO_RCX_REG_mask;
+%}
+
+// Class for all int registers (excluding RSP)
+reg_class int_reg %{
+ return _INT_REG_mask;
+%}
+
+// Class for all int registers (excluding RAX, RDX, and RSP)
+reg_class int_no_rax_rdx_reg %{
+ return _INT_NO_RAX_RDX_REG_mask;
+%}
+
+// Class for all int registers (excluding RCX and RSP)
+reg_class int_no_rcx_reg %{
+ return _INT_NO_RCX_REG_mask;
+%}
// Singleton class for RAX pointer register
reg_class ptr_rax_reg(RAX, RAX_H);
@@ -317,96 +276,6 @@
// Singleton class for TLS pointer
reg_class ptr_r15_reg(R15, R15_H);
-// Class for all long registers (excluding RSP)
-reg_class long_reg_with_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Class for all long registers (excluding RSP and RBP)
-reg_class long_reg_no_rbp(RAX, RAX_H,
- RDX, RDX_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between long_reg_no_rbp and long_reg_with_rbp.
-reg_class_dynamic long_reg(long_reg_no_rbp, long_reg_with_rbp, %{ PreserveFramePointer %});
-
-// Class for all long registers (excluding RAX, RDX and RSP)
-reg_class long_no_rax_rdx_reg_with_rbp(RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Class for all long registers (excluding RAX, RDX, RSP, and RBP)
-reg_class long_no_rax_rdx_reg_no_rbp(RDI, RDI_H,
- RSI, RSI_H,
- RCX, RCX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between long_no_rax_rdx_reg_no_rbp and long_no_rax_rdx_reg_with_rbp.
-reg_class_dynamic long_no_rax_rdx_reg(long_no_rax_rdx_reg_no_rbp, long_no_rax_rdx_reg_with_rbp, %{ PreserveFramePointer %});
-
-// Class for all long registers (excluding RCX and RSP)
-reg_class long_no_rcx_reg_with_rbp(RBP, RBP_H,
- RDI, RDI_H,
- RSI, RSI_H,
- RAX, RAX_H,
- RDX, RDX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Class for all long registers (excluding RCX, RSP, and RBP)
-reg_class long_no_rcx_reg_no_rbp(RDI, RDI_H,
- RSI, RSI_H,
- RAX, RAX_H,
- RDX, RDX_H,
- RBX, RBX_H,
- R8, R8_H,
- R9, R9_H,
- R10, R10_H,
- R11, R11_H,
- R13, R13_H,
- R14, R14_H);
-
-// Dynamic register class that selects between long_no_rcx_reg_no_rbp and long_no_rcx_reg_with_rbp.
-reg_class_dynamic long_no_rcx_reg(long_no_rcx_reg_no_rbp, long_no_rcx_reg_with_rbp, %{ PreserveFramePointer %});
-
// Singleton class for RAX long register
reg_class long_rax_reg(RAX, RAX_H);
@@ -416,96 +285,6 @@
// Singleton class for RDX long register
reg_class long_rdx_reg(RDX, RDX_H);
-// Class for all int registers (excluding RSP)
-reg_class int_reg_with_rbp(RAX,
- RDX,
- RBP,
- RDI,
- RSI,
- RCX,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Class for all int registers (excluding RSP and RBP)
-reg_class int_reg_no_rbp(RAX,
- RDX,
- RDI,
- RSI,
- RCX,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Dynamic register class that selects between int_reg_no_rbp and int_reg_with_rbp.
-reg_class_dynamic int_reg(int_reg_no_rbp, int_reg_with_rbp, %{ PreserveFramePointer %});
-
-// Class for all int registers (excluding RCX and RSP)
-reg_class int_no_rcx_reg_with_rbp(RAX,
- RDX,
- RBP,
- RDI,
- RSI,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Class for all int registers (excluding RCX, RSP, and RBP)
-reg_class int_no_rcx_reg_no_rbp(RAX,
- RDX,
- RDI,
- RSI,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Dynamic register class that selects between int_no_rcx_reg_no_rbp and int_no_rcx_reg_with_rbp.
-reg_class_dynamic int_no_rcx_reg(int_no_rcx_reg_no_rbp, int_no_rcx_reg_with_rbp, %{ PreserveFramePointer %});
-
-// Class for all int registers (excluding RAX, RDX, and RSP)
-reg_class int_no_rax_rdx_reg_with_rbp(RBP,
- RDI,
- RSI,
- RCX,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Class for all int registers (excluding RAX, RDX, RSP, and RBP)
-reg_class int_no_rax_rdx_reg_no_rbp(RDI,
- RSI,
- RCX,
- RBX,
- R8,
- R9,
- R10,
- R11,
- R13,
- R14);
-
-// Dynamic register class that selects between int_no_rax_rdx_reg_no_rbp and int_no_rax_rdx_reg_with_rbp.
-reg_class_dynamic int_no_rax_rdx_reg(int_no_rax_rdx_reg_no_rbp, int_no_rax_rdx_reg_with_rbp, %{ PreserveFramePointer %});
-
// Singleton class for RAX int register
reg_class int_rax_reg(RAX);
@@ -529,12 +308,123 @@
//----------SOURCE BLOCK-------------------------------------------------------
// This is a block of C++ code which provides values, functions, and
// definitions necessary in the rest of the architecture description
+source_hpp %{
+
+extern RegMask _ANY_REG_mask;
+extern RegMask _PTR_REG_mask;
+extern RegMask _PTR_REG_NO_RBP_mask;
+extern RegMask _PTR_NO_RAX_REG_mask;
+extern RegMask _PTR_NO_RAX_RBX_REG_mask;
+extern RegMask _LONG_REG_mask;
+extern RegMask _LONG_NO_RAX_RDX_REG_mask;
+extern RegMask _LONG_NO_RCX_REG_mask;
+extern RegMask _INT_REG_mask;
+extern RegMask _INT_NO_RAX_RDX_REG_mask;
+extern RegMask _INT_NO_RCX_REG_mask;
+
+extern RegMask _STACK_OR_PTR_REG_mask;
+extern RegMask _STACK_OR_LONG_REG_mask;
+extern RegMask _STACK_OR_INT_REG_mask;
+
+inline const RegMask& STACK_OR_PTR_REG_mask() { return _STACK_OR_PTR_REG_mask; }
+inline const RegMask& STACK_OR_LONG_REG_mask() { return _STACK_OR_LONG_REG_mask; }
+inline const RegMask& STACK_OR_INT_REG_mask() { return _STACK_OR_INT_REG_mask; }
+
+%}
+
source %{
#define RELOC_IMM64 Assembler::imm_operand
#define RELOC_DISP32 Assembler::disp32_operand
#define __ _masm.
+RegMask _ANY_REG_mask;
+RegMask _PTR_REG_mask;
+RegMask _PTR_REG_NO_RBP_mask;
+RegMask _PTR_NO_RAX_REG_mask;
+RegMask _PTR_NO_RAX_RBX_REG_mask;
+RegMask _LONG_REG_mask;
+RegMask _LONG_NO_RAX_RDX_REG_mask;
+RegMask _LONG_NO_RCX_REG_mask;
+RegMask _INT_REG_mask;
+RegMask _INT_NO_RAX_RDX_REG_mask;
+RegMask _INT_NO_RCX_REG_mask;
+RegMask _STACK_OR_PTR_REG_mask;
+RegMask _STACK_OR_LONG_REG_mask;
+RegMask _STACK_OR_INT_REG_mask;
+
+static bool need_r12_heapbase() {
+ return UseCompressedOops || UseCompressedClassPointers;
+}
+
+void reg_mask_init() {
+ // _ALL_REG_mask is generated by adlc from the all_reg register class below.
+ // We derive a number of subsets from it.
+ _ANY_REG_mask = _ALL_REG_mask;
+
+ if (PreserveFramePointer) {
+ _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
+ _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next()));
+ }
+ if (need_r12_heapbase()) {
+ _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()));
+ _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()->next()));
+ }
+
+ _PTR_REG_mask = _ANY_REG_mask;
+ _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()));
+ _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()->next()));
+ _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()));
+ _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()->next()));
+
+ _STACK_OR_PTR_REG_mask = _PTR_REG_mask;
+ _STACK_OR_PTR_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
+
+ _PTR_REG_NO_RBP_mask = _PTR_REG_mask;
+ _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
+ _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next()));
+
+ _PTR_NO_RAX_REG_mask = _PTR_REG_mask;
+ _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
+ _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next()));
+
+ _PTR_NO_RAX_RBX_REG_mask = _PTR_NO_RAX_REG_mask;
+ _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()));
+ _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()->next()));
+
+ _LONG_REG_mask = _PTR_REG_mask;
+ _STACK_OR_LONG_REG_mask = _LONG_REG_mask;
+ _STACK_OR_LONG_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
+
+ _LONG_NO_RAX_RDX_REG_mask = _LONG_REG_mask;
+ _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
+ _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next()));
+ _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()));
+ _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()->next()));
+
+ _LONG_NO_RCX_REG_mask = _LONG_REG_mask;
+ _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()));
+ _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()->next()));
+
+ _INT_REG_mask = _ALL_INT_REG_mask;
+ if (PreserveFramePointer) {
+ _INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
+ }
+ if (need_r12_heapbase()) {
+ _INT_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()));
+ }
+
+ _STACK_OR_INT_REG_mask = _INT_REG_mask;
+ _STACK_OR_INT_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
+
+ _INT_NO_RAX_RDX_REG_mask = _INT_REG_mask;
+ _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
+ _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()));
+
+ _INT_NO_RCX_REG_mask = _INT_REG_mask;
+ _INT_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()));
+}
+
static bool generate_vzeroupper(Compile* C) {
return (VM_Version::supports_vzeroupper() && (C->max_vector_size() > 16 || C->clear_upper_avx() == true)) ? true: false; // Generate vzeroupper
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/aix/os_aix.inline.hpp
--- a/src/hotspot/os/aix/os_aix.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/aix/os_aix.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -27,6 +27,7 @@
#define OS_AIX_OS_AIX_INLINE_HPP
#include "runtime/os.hpp"
+#include "os_posix.inline.hpp"
// System includes
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/aix/os_perf_aix.cpp
--- a/src/hotspot/os/aix/os_perf_aix.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/aix/os_perf_aix.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -859,11 +859,7 @@
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
if (str != NULL) {
- size_t len = strlen(str);
- char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
- strncpy(tmp, str, len);
- tmp[len] = '\0';
- return tmp;
+ return os::strdup_check_oom(str, mtInternal);
}
return NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/bsd/os_bsd.cpp
--- a/src/hotspot/os/bsd/os_bsd.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/bsd/os_bsd.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -37,6 +37,7 @@
#include "memory/filemap.hpp"
#include "oops/oop.inline.hpp"
#include "os_bsd.inline.hpp"
+#include "os_posix.inline.hpp"
#include "os_share_bsd.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/bsd/os_bsd.inline.hpp
--- a/src/hotspot/os/bsd/os_bsd.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/bsd/os_bsd.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -26,6 +26,7 @@
#define OS_BSD_OS_BSD_INLINE_HPP
#include "runtime/os.hpp"
+#include "os_posix.inline.hpp"
// System includes
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/linux/globals_linux.hpp
--- a/src/hotspot/os/linux/globals_linux.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/linux/globals_linux.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -70,7 +70,12 @@
diagnostic(bool, DumpPrivateMappingsInCore, true, \
"If true, sets bit 2 of /proc/PID/coredump_filter, thus " \
"resulting in file-backed private mappings of the process to "\
- "be dumped into the corefile, if UseSharedSpaces is true.") \
+ "be dumped into the corefile.") \
+ \
+ diagnostic(bool, DumpSharedMappingsInCore, true, \
+ "If true, sets bit 3 of /proc/PID/coredump_filter, thus " \
+ "resulting in file-backed shared mappings of the process to " \
+ "be dumped into the corefile.") \
\
diagnostic(bool, UseCpuAllocPath, false, \
"Use CPU_ALLOC code path in os::active_processor_count ")
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/linux/os_linux.cpp
--- a/src/hotspot/os/linux/os_linux.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -38,6 +38,7 @@
#include "memory/filemap.hpp"
#include "oops/oop.inline.hpp"
#include "os_linux.inline.hpp"
+#include "os_posix.inline.hpp"
#include "os_share_linux.hpp"
#include "osContainer_linux.hpp"
#include "prims/jniFastGetField.hpp"
@@ -131,6 +132,7 @@
enum CoredumpFilterBit {
FILE_BACKED_PVT_BIT = 1 << 2,
+ FILE_BACKED_SHARED_BIT = 1 << 3,
LARGEPAGES_BIT = 1 << 6,
DAX_SHARED_BIT = 1 << 8
};
@@ -1357,11 +1359,9 @@
void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
-#if INCLUDE_CDS
- if (UseSharedSpaces && DumpPrivateMappingsInCore) {
+ if (DumpPrivateMappingsInCore) {
ClassLoader::close_jrt_image();
}
-#endif
#ifndef PRODUCT
fdStream out(defaultStream::output_fd());
out.print_raw("Current thread is ");
@@ -3432,8 +3432,6 @@
return result;
}
-// Set the coredump_filter bits to include largepages in core dump (bit 6)
-//
// From the coredump_filter documentation:
//
// - (bit 0) anonymous private memory
@@ -5131,11 +5129,13 @@
set_coredump_filter(DAX_SHARED_BIT);
}
-#if INCLUDE_CDS
- if (UseSharedSpaces && DumpPrivateMappingsInCore) {
+ if (DumpPrivateMappingsInCore) {
set_coredump_filter(FILE_BACKED_PVT_BIT);
}
-#endif
+
+ if (DumpSharedMappingsInCore) {
+ set_coredump_filter(FILE_BACKED_SHARED_BIT);
+ }
return JNI_OK;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/linux/os_perf_linux.cpp
--- a/src/hotspot/os/linux/os_perf_linux.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/linux/os_perf_linux.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -861,11 +861,7 @@
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
if (str != NULL) {
- size_t len = strlen(str);
- char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
- strncpy(tmp, str, len);
- tmp[len] = '\0';
- return tmp;
+ return os::strdup_check_oom(str, mtInternal);
}
return NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/posix/os_posix.cpp
--- a/src/hotspot/os/posix/os_posix.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -180,13 +180,14 @@
const char name_template[] = "/jvmheap.XXXXXX";
- char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal);
+ size_t fullname_len = strlen(dir) + strlen(name_template);
+ char *fullname = (char*)os::malloc(fullname_len + 1, mtInternal);
if (fullname == NULL) {
vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));
return -1;
}
- (void)strncpy(fullname, dir, strlen(dir)+1);
- (void)strncat(fullname, name_template, strlen(name_template));
+ int n = snprintf(fullname, fullname_len + 1, "%s%s", dir, name_template);
+ assert((size_t)n == fullname_len, "Unexpected number of characters in string");
os::native_path(fullname);
@@ -2218,22 +2219,6 @@
assert_status(status == 0, status, "mutex_destroy");
}
-void os::PlatformMonitor::lock() {
- int status = pthread_mutex_lock(&_mutex);
- assert_status(status == 0, status, "mutex_lock");
-}
-
-void os::PlatformMonitor::unlock() {
- int status = pthread_mutex_unlock(&_mutex);
- assert_status(status == 0, status, "mutex_unlock");
-}
-
-bool os::PlatformMonitor::try_lock() {
- int status = pthread_mutex_trylock(&_mutex);
- assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
- return status == 0;
-}
-
// Must already be locked
int os::PlatformMonitor::wait(jlong millis) {
assert(millis >= 0, "negative timeout");
@@ -2262,14 +2247,4 @@
}
}
-void os::PlatformMonitor::notify() {
- int status = pthread_cond_signal(&_cond);
- assert_status(status == 0, status, "cond_signal");
-}
-
-void os::PlatformMonitor::notify_all() {
- int status = pthread_cond_broadcast(&_cond);
- assert_status(status == 0, status, "cond_broadcast");
-}
-
#endif // !SOLARIS
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/posix/os_posix.hpp
--- a/src/hotspot/os/posix/os_posix.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -177,7 +177,7 @@
* These event objects are type-stable and immortal - we never delete them.
* Events are associated with a thread for the lifetime of the thread.
*/
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj {
private:
double cachePad[4]; // Increase odds that _mutex is sole occupant of cache line
volatile int _event; // Event count/permit: -1, 0 or 1
@@ -212,7 +212,7 @@
// API updates of course). But Parker methods use fastpaths that break that
// level of encapsulation - so combining the two remains a future project.
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj {
protected:
enum {
REL_INDEX = 0,
@@ -230,7 +230,7 @@
};
// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj {
+class PlatformMonitor : public CHeapObj {
private:
pthread_mutex_t _mutex; // Native mutex for locking
pthread_cond_t _cond; // Native condition variable for blocking
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/posix/os_posix.inline.hpp
--- a/src/hotspot/os/posix/os_posix.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -42,6 +42,39 @@
inline int os::Posix::clock_getres(clockid_t clock_id, struct timespec *tp) {
return _clock_getres != NULL ? _clock_getres(clock_id, tp) : -1;
}
+
#endif // SUPPORTS_CLOCK_MONOTONIC
+#ifndef SOLARIS
+
+// Platform Monitor implementation
+
+inline void os::PlatformMonitor::lock() {
+ int status = pthread_mutex_lock(&_mutex);
+ assert_status(status == 0, status, "mutex_lock");
+}
+
+inline void os::PlatformMonitor::unlock() {
+ int status = pthread_mutex_unlock(&_mutex);
+ assert_status(status == 0, status, "mutex_unlock");
+}
+
+inline bool os::PlatformMonitor::try_lock() {
+ int status = pthread_mutex_trylock(&_mutex);
+ assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
+ return status == 0;
+}
+
+inline void os::PlatformMonitor::notify() {
+ int status = pthread_cond_signal(&_cond);
+ assert_status(status == 0, status, "cond_signal");
+}
+
+inline void os::PlatformMonitor::notify_all() {
+ int status = pthread_cond_broadcast(&_cond);
+ assert_status(status == 0, status, "cond_broadcast");
+}
+
+#endif // !SOLARIS
+
#endif // OS_POSIX_OS_POSIX_INLINE_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/solaris/os_perf_solaris.cpp
--- a/src/hotspot/os/solaris/os_perf_solaris.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/solaris/os_perf_solaris.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -544,11 +544,7 @@
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
if (str != NULL) {
- size_t len = strlen(str);
- char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
- strncpy(tmp, str, len);
- tmp[len] = '\0';
- return tmp;
+ return os::strdup_check_oom(str, mtInternal);
}
return NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/solaris/os_solaris.hpp
--- a/src/hotspot/os/solaris/os_solaris.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/solaris/os_solaris.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -281,7 +281,7 @@
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj {
private:
double CachePad[4]; // increase odds that _mutex is sole occupant of cache line
volatile int _Event;
@@ -317,7 +317,7 @@
void unpark();
};
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj {
protected:
mutex_t _mutex[1];
cond_t _cond[1];
@@ -336,7 +336,7 @@
};
// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj {
+class PlatformMonitor : public CHeapObj {
private:
mutex_t _mutex; // Native mutex for locking
cond_t _cond; // Native condition variable for blocking
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/windows/os_perf_windows.cpp
--- a/src/hotspot/os/windows/os_perf_windows.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/windows/os_perf_windows.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1253,14 +1253,7 @@
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
if (str != NULL) {
- size_t len = strlen(str);
- char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
- if (NULL == tmp) {
- return NULL;
- }
- strncpy(tmp, str, len);
- tmp[len] = '\0';
- return tmp;
+ return os::strdup_check_oom(str, mtInternal);
}
return NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/windows/os_windows.cpp
--- a/src/hotspot/os/windows/os_windows.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/windows/os_windows.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -2970,14 +2970,15 @@
int os::create_file_for_heap(const char* dir) {
const char name_template[] = "/jvmheap.XXXXXX";
- char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal);
+
+ size_t fullname_len = strlen(dir) + strlen(name_template);
+ char *fullname = (char*)os::malloc(fullname_len + 1, mtInternal);
if (fullname == NULL) {
vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));
return -1;
}
-
- (void)strncpy(fullname, dir, strlen(dir)+1);
- (void)strncat(fullname, name_template, strlen(name_template));
+ int n = snprintf(fullname, fullname_len + 1, "%s%s", dir, name_template);
+ assert((size_t)n == fullname_len, "Unexpected number of characters in string");
os::native_path(fullname);
@@ -5319,27 +5320,6 @@
// Platform Monitor implementation
-os::PlatformMonitor::PlatformMonitor() {
- InitializeConditionVariable(&_cond);
- InitializeCriticalSection(&_mutex);
-}
-
-os::PlatformMonitor::~PlatformMonitor() {
- DeleteCriticalSection(&_mutex);
-}
-
-void os::PlatformMonitor::lock() {
- EnterCriticalSection(&_mutex);
-}
-
-void os::PlatformMonitor::unlock() {
- LeaveCriticalSection(&_mutex);
-}
-
-bool os::PlatformMonitor::try_lock() {
- return TryEnterCriticalSection(&_mutex);
-}
-
// Must already be locked
int os::PlatformMonitor::wait(jlong millis) {
assert(millis >= 0, "negative timeout");
@@ -5358,14 +5338,6 @@
return ret;
}
-void os::PlatformMonitor::notify() {
- WakeConditionVariable(&_cond);
-}
-
-void os::PlatformMonitor::notify_all() {
- WakeAllConditionVariable(&_cond);
-}
-
// Run the specified command in a separate process. Return its exit value,
// or -1 on failure (e.g. can't create a new process).
int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/windows/os_windows.hpp
--- a/src/hotspot/os/windows/os_windows.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/windows/os_windows.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -148,7 +148,7 @@
static volatile intptr_t _crash_mux;
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj {
private:
double CachePad [4] ; // increase odds that _Event is sole occupant of cache line
volatile int _Event ;
@@ -174,7 +174,7 @@
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj {
protected:
HANDLE _ParkEvent ;
@@ -188,7 +188,7 @@
} ;
// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj {
+class PlatformMonitor : public CHeapObj {
private:
CRITICAL_SECTION _mutex; // Native mutex for locking
CONDITION_VARIABLE _cond; // Native condition variable for blocking
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/os/windows/os_windows.inline.hpp
--- a/src/hotspot/os/windows/os_windows.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/os/windows/os_windows.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -86,4 +86,35 @@
win32::exit_process_or_thread(win32::EPT_PROCESS, num);
}
+// Platform Monitor implementation
+
+inline os::PlatformMonitor::PlatformMonitor() {
+ InitializeConditionVariable(&_cond);
+ InitializeCriticalSection(&_mutex);
+}
+
+inline os::PlatformMonitor::~PlatformMonitor() {
+ DeleteCriticalSection(&_mutex);
+}
+
+inline void os::PlatformMonitor::lock() {
+ EnterCriticalSection(&_mutex);
+}
+
+inline void os::PlatformMonitor::unlock() {
+ LeaveCriticalSection(&_mutex);
+}
+
+inline bool os::PlatformMonitor::try_lock() {
+ return TryEnterCriticalSection(&_mutex);
+}
+
+inline void os::PlatformMonitor::notify() {
+ WakeConditionVariable(&_cond);
+}
+
+inline void os::PlatformMonitor::notify_all() {
+ WakeAllConditionVariable(&_cond);
+}
+
#endif // OS_WINDOWS_OS_WINDOWS_INLINE_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/adlc/formsopt.hpp
--- a/src/hotspot/share/adlc/formsopt.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/adlc/formsopt.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -242,9 +242,6 @@
char* code_snippet() {
return _code_snippet;
}
- void set_stack_version(bool flag) {
- assert(false, "User defined register classes are not allowed to spill to the stack.");
- }
void declare_register_masks(FILE* fp);
void build_register_masks(FILE* fp) {
// We do not need to generate register masks because we select at runtime
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/c1/c1_Optimizer.cpp
--- a/src/hotspot/share/c1/c1_Optimizer.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/c1/c1_Optimizer.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -174,6 +174,12 @@
for_each_phi_fun(t_block, phi, return; );
for_each_phi_fun(f_block, phi, return; );
+ // Only replace safepoint gotos if state_before information is available (if is a safepoint)
+ bool is_safepoint = if_->is_safepoint();
+ if (!is_safepoint && (t_goto->is_safepoint() || f_goto->is_safepoint())) {
+ return;
+ }
+
// 2) substitute conditional expression
// with an IfOp followed by a Goto
// cut if_ away and get node before
@@ -202,7 +208,7 @@
// append Goto to successor
ValueStack* state_before = if_->state_before();
- Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
+ Goto* goto_ = new Goto(sux, state_before, is_safepoint);
// prepare state for Goto
ValueStack* goto_state = if_state;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/ci/ciReplay.cpp
--- a/src/hotspot/share/ci/ciReplay.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/ci/ciReplay.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -33,6 +33,7 @@
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/constantPool.hpp"
#include "oops/method.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/classFileParser.cpp
--- a/src/hotspot/share/classfile/classFileParser.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/classFileParser.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -5743,16 +5743,13 @@
ClassLoader::package_from_name(unsafe_anonymous_host->name()->as_C_string(), NULL);
if (host_pkg_name != NULL) {
- size_t host_pkg_len = strlen(host_pkg_name);
+ int host_pkg_len = (int)strlen(host_pkg_name);
int class_name_len = _class_name->utf8_length();
- char* new_anon_name =
- NEW_RESOURCE_ARRAY(char, host_pkg_len + 1 + class_name_len);
- // Copy host package name and trailing /.
- strncpy(new_anon_name, host_pkg_name, host_pkg_len);
- new_anon_name[host_pkg_len] = '/';
- // Append unsafe anonymous class name. The unsafe anonymous class name can contain odd
- // characters. So, do a strncpy instead of using sprintf("%s...").
- strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len);
+ int symbol_len = host_pkg_len + 1 + class_name_len;
+ char* new_anon_name = NEW_RESOURCE_ARRAY(char, symbol_len + 1);
+ int n = snprintf(new_anon_name, symbol_len + 1, "%s/%.*s",
+ host_pkg_name, class_name_len, _class_name->base());
+ assert(n == symbol_len, "Unexpected number of characters in string");
// Decrement old _class_name to avoid leaking.
_class_name->decrement_refcount();
@@ -5761,9 +5758,7 @@
// The new class name is created with a refcount of one. When installed into the InstanceKlass,
// it'll be two and when the ClassFileParser destructor runs, it'll go back to one and get deleted
// when the class is unloaded.
- _class_name = SymbolTable::new_symbol(new_anon_name,
- (int)host_pkg_len + 1 + class_name_len,
- CHECK);
+ _class_name = SymbolTable::new_symbol(new_anon_name, symbol_len, CHECK);
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/classLoader.cpp
--- a/src/hotspot/share/classfile/classLoader.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/classLoader.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -101,7 +101,6 @@
static JImageFindResource_t JImageFindResource = NULL;
static JImageGetResource_t JImageGetResource = NULL;
static JImageResourceIterator_t JImageResourceIterator = NULL;
-static JImage_ResourcePath_t JImageResourcePath = NULL;
// Globals
@@ -621,13 +620,14 @@
update_module_path_entry_list(path, THREAD);
}
+#endif // INCLUDE_CDS
+
void ClassLoader::close_jrt_image() {
- assert(ClassLoader::has_jrt_entry(), "Not applicable for exploded builds");
+ // Not applicable for exploded builds
+ if (!ClassLoader::has_jrt_entry()) return;
_jrt_entry->close_jimage();
}
-#endif // INCLUDE_CDS
-
// Construct the array of module/path pairs as specified to --patch-module
// for the boot loader to search ahead of the jimage, if the class being
// loaded is defined to a module that has been specified to --patch-module.
@@ -1094,8 +1094,6 @@
guarantee(JImageGetResource != NULL, "function JIMAGE_GetResource not found");
JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, os::dll_lookup(handle, "JIMAGE_ResourceIterator"));
guarantee(JImageResourceIterator != NULL, "function JIMAGE_ResourceIterator not found");
- JImageResourcePath = CAST_TO_FN_PTR(JImage_ResourcePath_t, os::dll_lookup(handle, "JIMAGE_ResourcePath"));
- guarantee(JImageResourcePath != NULL, "function JIMAGE_ResourcePath not found");
}
jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/classLoader.hpp
--- a/src/hotspot/share/classfile/classLoader.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/classLoader.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -247,12 +247,12 @@
static void load_zip_library();
static void load_jimage_library();
+
+ public:
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
bool throw_exception,
bool is_boot_append, TRAPS);
- public:
-
// If the package for the fully qualified class name is in the boot
// loader's package entry table then add_package() sets the classpath_index
// field so that get_system_package() will know to return a non-null value
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/classLoaderExt.cpp
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -203,13 +203,13 @@
file_end = end;
}
- int name_len = (int)strlen(file_start);
+ size_t name_len = strlen(file_start);
if (name_len > 0) {
ResourceMark rm(THREAD);
- char* libname = NEW_RESOURCE_ARRAY(char, dir_len + name_len + 1);
- *libname = 0;
- strncat(libname, dir_name, dir_len);
- strncat(libname, file_start, name_len);
+ size_t libname_len = dir_len + name_len;
+ char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1);
+ int n = snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
+ assert((size_t)n == libname_len, "Unexpected number of characters in string");
trace_class_path("library = ", libname);
ClassLoader::update_class_path_entry_list(libname, true, false);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/klassFactory.cpp
--- a/src/hotspot/share/classfile/klassFactory.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/klassFactory.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,22 +46,22 @@
InstanceKlass* ik,
Symbol* class_name,
Handle class_loader,
- Handle protection_domain, TRAPS) {
+ Handle protection_domain,
+ const ClassFileStream *cfs,
+ TRAPS) {
#if INCLUDE_CDS && INCLUDE_JVMTI
assert(ik != NULL, "sanity");
assert(ik->is_shared(), "expecting a shared class");
-
if (JvmtiExport::should_post_class_file_load_hook()) {
assert(THREAD->is_Java_thread(), "must be JavaThread");
// Post the CFLH
JvmtiCachedClassFileData* cached_class_file = NULL;
- JvmtiCachedClassFileData* archived_class_data = ik->get_archived_class_data();
- assert(archived_class_data != NULL, "shared class has no archived class data");
- unsigned char* ptr =
- VM_RedefineClasses::get_cached_class_file_bytes(archived_class_data);
- unsigned char* end_ptr =
- ptr + VM_RedefineClasses::get_cached_class_file_len(archived_class_data);
+ if (cfs == NULL) {
+ cfs = FileMapInfo::open_stream_for_jvmti(ik, CHECK_NULL);
+ }
+ unsigned char* ptr = (unsigned char*)cfs->buffer();
+ unsigned char* end_ptr = ptr + cfs->length();
unsigned char* old_ptr = ptr;
JvmtiExport::post_class_file_load_hook(class_name,
class_loader,
@@ -75,25 +75,9 @@
ClassLoaderData* loader_data =
ClassLoaderData::class_loader_data(class_loader());
int path_index = ik->shared_classpath_index();
- const char* pathname;
- if (path_index < 0) {
- // shared classes loaded by user defined class loader
- // do not have shared_classpath_index
- ModuleEntry* mod_entry = ik->module();
- if (mod_entry != NULL && (mod_entry->location() != NULL)) {
- ResourceMark rm;
- pathname = (const char*)(mod_entry->location()->as_C_string());
- } else {
- pathname = "";
- }
- } else {
- SharedClassPathEntry* ent =
- (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
- pathname = ent == NULL ? NULL : ent->name();
- }
ClassFileStream* stream = new ClassFileStream(ptr,
end_ptr - ptr,
- pathname,
+ cfs->source(),
ClassFileStream::verify);
ClassFileParser parser(stream,
class_name,
@@ -236,24 +220,6 @@
#if INCLUDE_CDS
if (DumpSharedSpaces) {
ClassLoader::record_result(result, stream, THREAD);
-#if INCLUDE_JVMTI
- assert(cached_class_file == NULL, "Sanity");
- // Archive the class stream data into the optional data section
- JvmtiCachedClassFileData *p;
- int len;
- const unsigned char *bytes;
- // event based tracing might set cached_class_file
- if ((bytes = result->get_cached_class_file_bytes()) != NULL) {
- len = result->get_cached_class_file_len();
- } else {
- len = stream->length();
- bytes = stream->buffer();
- }
- p = (JvmtiCachedClassFileData*)os::malloc(offset_of(JvmtiCachedClassFileData, data) + len, mtInternal);
- p->length = len;
- memcpy(p->data, bytes, len);
- result->set_archived_class_data(p);
-#endif // INCLUDE_JVMTI
}
#endif // INCLUDE_CDS
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/klassFactory.hpp
--- a/src/hotspot/share/classfile/klassFactory.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/klassFactory.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -80,7 +80,9 @@
InstanceKlass* ik,
Symbol* class_name,
Handle class_loader,
- Handle protection_domain, TRAPS);
+ Handle protection_domain,
+ const ClassFileStream *cfs,
+ TRAPS);
};
#endif // SHARE_CLASSFILE_KLASSFACTORY_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/stackMapTable.cpp
--- a/src/hotspot/share/classfile/stackMapTable.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/stackMapTable.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -26,6 +26,7 @@
#include "classfile/stackMapTable.hpp"
#include "classfile/verifier.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/constantPool.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/symbolTable.cpp
--- a/src/hotspot/share/classfile/symbolTable.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/symbolTable.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -436,18 +436,16 @@
}
}
-void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
- int names_count, const char** names, int* lengths,
- int* cp_indices, unsigned int* hashValues, TRAPS) {
+void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHandle& cp,
+ int names_count, const char** names, int* lengths,
+ int* cp_indices, unsigned int* hashValues, TRAPS) {
bool c_heap = !loader_data->is_the_null_class_loader_data();
for (int i = 0; i < names_count; i++) {
const char *name = names[i];
int len = lengths[i];
unsigned int hash = hashValues[i];
- Symbol* sym = SymbolTable::the_table()->lookup_common(name, len, hash);
- if (sym == NULL) {
- sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
- }
+ assert(SymbolTable::the_table()->lookup_shared(name, len, hash) == NULL, "must have checked already");
+ Symbol* sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, c_heap, CHECK);
assert(sym->refcount() != 0, "lookup should have incremented the count");
cp->symbol_at_put(cp_indices[i], sym);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/symbolTable.hpp
--- a/src/hotspot/share/classfile/symbolTable.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/symbolTable.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -144,18 +144,11 @@
Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS);
// Adding elements
- static void add(ClassLoaderData* loader_data,
- const constantPoolHandle& cp, int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS);
-
static void new_symbols(ClassLoaderData* loader_data,
const constantPoolHandle& cp, int names_count,
const char** name, int* lengths,
int* cp_indices, unsigned int* hashValues,
- TRAPS) {
- add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
- }
+ TRAPS);
static Symbol* lookup_shared(const char* name, int len, unsigned int hash);
Symbol* lookup_dynamic(const char* name, int len, unsigned int hash);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/systemDictionary.cpp
--- a/src/hotspot/share/classfile/systemDictionary.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1174,7 +1174,7 @@
TRAPS) {
InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name);
if (ik != NULL && ik->is_shared_boot_class()) {
- return load_shared_class(ik, Handle(), Handle(), THREAD);
+ return load_shared_class(ik, Handle(), Handle(), NULL, THREAD);
}
return NULL;
}
@@ -1274,7 +1274,9 @@
InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
Handle class_loader,
- Handle protection_domain, TRAPS) {
+ Handle protection_domain,
+ const ClassFileStream *cfs,
+ TRAPS) {
if (ik != NULL) {
Symbol* class_name = ik->name();
@@ -1321,7 +1323,7 @@
}
InstanceKlass* new_ik = KlassFactory::check_shared_class_file_load_hook(
- ik, class_name, class_loader, protection_domain, CHECK_NULL);
+ ik, class_name, class_loader, protection_domain, cfs, CHECK_NULL);
if (new_ik != NULL) {
// The class is changed by CFLH. Return the new class. The shared class is
// not used.
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/systemDictionary.hpp
--- a/src/hotspot/share/classfile/systemDictionary.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/systemDictionary.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -628,6 +628,7 @@
static InstanceKlass* load_shared_class(InstanceKlass* ik,
Handle class_loader,
Handle protection_domain,
+ const ClassFileStream *cfs,
TRAPS);
static InstanceKlass* load_shared_boot_class(Symbol* class_name,
TRAPS);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/systemDictionaryShared.cpp
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -803,7 +803,7 @@
SystemDictionary::is_platform_class_loader(class_loader()))) {
Handle protection_domain =
SystemDictionaryShared::init_security_info(class_loader, ik, CHECK_NULL);
- return load_shared_class(ik, class_loader, protection_domain, THREAD);
+ return load_shared_class(ik, class_loader, protection_domain, NULL, THREAD);
}
}
return NULL;
@@ -873,13 +873,15 @@
}
return acquire_class_for_current_thread(record->_klass, class_loader,
- protection_domain, THREAD);
+ protection_domain, cfs,
+ THREAD);
}
InstanceKlass* SystemDictionaryShared::acquire_class_for_current_thread(
InstanceKlass *ik,
Handle class_loader,
Handle protection_domain,
+ const ClassFileStream *cfs,
TRAPS) {
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
@@ -900,7 +902,8 @@
loader_data->add_class(ik);
// Load and check super/interfaces, restore unsharable info
- InstanceKlass* shared_klass = load_shared_class(ik, class_loader, protection_domain, THREAD);
+ InstanceKlass* shared_klass = load_shared_class(ik, class_loader, protection_domain,
+ cfs, THREAD);
if (shared_klass == NULL || HAS_PENDING_EXCEPTION) {
// TODO: clean up so it can be used again
return NULL;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/systemDictionaryShared.hpp
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -207,6 +207,7 @@
InstanceKlass *ik,
Handle class_loader,
Handle protection_domain,
+ const ClassFileStream* cfs,
TRAPS);
static DumpTimeSharedClassInfo* find_or_allocate_info_for(InstanceKlass* k);
static void write_dictionary(RunTimeSharedDictionary* dictionary, bool is_builtin);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/verifier.cpp
--- a/src/hotspot/share/classfile/verifier.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/verifier.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2981,18 +2981,16 @@
}
// add one dimension to component
length++;
- arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length);
- arr_sig_str[0] = '[';
- strncpy(&arr_sig_str[1], component_name, length - 1);
+ arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1);
+ int n = snprintf(arr_sig_str, length + 1, "[%s", component_name);
+ assert(n == length, "Unexpected number of characters in string");
} else { // it's an object or interface
const char* component_name = component_type.name()->as_utf8();
// add one dimension to component with 'L' prepended and ';' postpended.
length = (int)strlen(component_name) + 3;
- arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length);
- arr_sig_str[0] = '[';
- arr_sig_str[1] = 'L';
- strncpy(&arr_sig_str[2], component_name, length - 2);
- arr_sig_str[length - 1] = ';';
+ arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1);
+ int n = snprintf(arr_sig_str, length + 1, "[L%s;", component_name);
+ assert(n == length, "Unexpected number of characters in string");
}
Symbol* arr_sig = create_temporary_symbol(
arr_sig_str, length, CHECK_VERIFY(this));
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/classfile/verifier.hpp
--- a/src/hotspot/share/classfile/verifier.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/classfile/verifier.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -49,7 +49,7 @@
// Return false if the class is loaded by the bootstrap loader,
// or if defineClass was called requesting skipping verification
- // -Xverify:all/none override this value
+ // -Xverify:all overrides this value
static bool should_verify_for(oop class_loader, bool should_verify_class);
// Relax certain access checks to enable some broken 1.1 apps to run on 1.2.
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -2761,7 +2761,7 @@
CMSPhaseAccounting::~CMSPhaseAccounting() {
_collector->gc_timer_cm()->register_gc_concurrent_end();
_collector->stopTimer();
- log_debug(gc)("Concurrent active time: %.3fms", TimeHelper::counter_to_seconds(_collector->timerTicks()));
+ log_debug(gc)("Concurrent active time: %.3fms", TimeHelper::counter_to_millis(_collector->timerTicks()));
log_trace(gc)(" (CMS %s yielded %d times)", _title, _collector->yields());
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1Allocator.cpp
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -321,16 +321,26 @@
}
}
-void G1PLABAllocator::waste(size_t& wasted, size_t& undo_wasted) {
- wasted = 0;
- undo_wasted = 0;
+size_t G1PLABAllocator::waste() const {
+ size_t result = 0;
for (uint state = 0; state < InCSetState::Num; state++) {
PLAB * const buf = _alloc_buffers[state];
if (buf != NULL) {
- wasted += buf->waste();
- undo_wasted += buf->undo_waste();
+ result += buf->waste();
}
}
+ return result;
+}
+
+size_t G1PLABAllocator::undo_waste() const {
+ size_t result = 0;
+ for (uint state = 0; state < InCSetState::Num; state++) {
+ PLAB * const buf = _alloc_buffers[state];
+ if (buf != NULL) {
+ result += buf->undo_waste();
+ }
+ }
+ return result;
}
bool G1ArchiveAllocator::_archive_check_enabled = false;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1Allocator.hpp
--- a/src/hotspot/share/gc/g1/g1Allocator.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Allocator.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -155,7 +155,8 @@
public:
G1PLABAllocator(G1Allocator* allocator);
- void waste(size_t& wasted, size_t& undo_wasted);
+ size_t waste() const;
+ size_t undo_waste() const;
// Allocate word_sz words in dest, either directly into the regions or by
// allocating a new PLAB. Returns the address of the allocated memory, NULL if
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1CollectedHeap.cpp
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -3282,10 +3282,6 @@
_root_processor->evacuate_roots(pss, worker_id);
- // We pass a weak code blobs closure to the remembered set scanning because we want to avoid
- // treating the nmethods visited to act as roots for concurrent marking.
- // We only want to make sure that the oops in the nmethods are adjusted with regard to the
- // objects copied by the current evacuation.
_g1h->g1_rem_set()->oops_into_collection_set_do(pss, worker_id);
double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
@@ -3303,27 +3299,22 @@
G1GCPhaseTimes* p = _g1h->g1_policy()->phase_times();
p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_id, elapsed_sec - term_sec);
+
+ p->record_or_add_thread_work_item(G1GCPhaseTimes::ObjCopy,
+ worker_id,
+ pss->lab_waste_words() * HeapWordSize,
+ G1GCPhaseTimes::ObjCopyLABWaste);
+ p->record_or_add_thread_work_item(G1GCPhaseTimes::ObjCopy,
+ worker_id,
+ pss->lab_undo_waste_words() * HeapWordSize,
+ G1GCPhaseTimes::ObjCopyLABUndoWaste);
+
p->record_time_secs(G1GCPhaseTimes::Termination, worker_id, term_sec);
p->record_thread_work_item(G1GCPhaseTimes::Termination, worker_id, evac_term_attempts);
}
assert(pss->queue_is_empty(), "should be empty");
- if (log_is_enabled(Debug, gc, task, stats)) {
- MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
- size_t lab_waste;
- size_t lab_undo_waste;
- pss->waste(lab_waste, lab_undo_waste);
- _g1h->print_termination_stats(worker_id,
- (os::elapsedTime() - start_sec) * 1000.0, /* elapsed time */
- strong_roots_sec * 1000.0, /* strong roots time */
- term_sec * 1000.0, /* evac term time */
- evac_term_attempts, /* evac term attempts */
- lab_waste, /* alloc buffer waste */
- lab_undo_waste /* undo waste */
- );
- }
-
// Close the inner scope so that the ResourceMark and HandleMark
// destructors are executed here and are included as part of the
// "GC Worker Time".
@@ -3332,31 +3323,6 @@
}
};
-void G1CollectedHeap::print_termination_stats_hdr() {
- log_debug(gc, task, stats)("GC Termination Stats");
- log_debug(gc, task, stats)(" elapsed --strong roots-- -------termination------- ------waste (KiB)------");
- log_debug(gc, task, stats)("thr ms ms %% ms %% attempts total alloc undo");
- log_debug(gc, task, stats)("--- --------- --------- ------ --------- ------ -------- ------- ------- -------");
-}
-
-void G1CollectedHeap::print_termination_stats(uint worker_id,
- double elapsed_ms,
- double strong_roots_ms,
- double term_ms,
- size_t term_attempts,
- size_t alloc_buffer_waste,
- size_t undo_waste) const {
- log_debug(gc, task, stats)
- ("%3d %9.2f %9.2f %6.2f "
- "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
- SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
- worker_id, elapsed_ms, strong_roots_ms, strong_roots_ms * 100 / elapsed_ms,
- term_ms, term_ms * 100 / elapsed_ms, term_attempts,
- (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
- alloc_buffer_waste * HeapWordSize / K,
- undo_waste * HeapWordSize / K);
-}
-
void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
bool class_unloading_occurred) {
uint num_workers = workers()->active_workers();
@@ -3767,8 +3733,6 @@
G1RootProcessor root_processor(this, n_workers);
G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
- print_termination_stats_hdr();
-
workers()->run_task(&g1_par_task);
end_par_time_sec = os::elapsedTime();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1CollectedHeap.hpp
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -738,16 +738,6 @@
void pre_evacuate_collection_set();
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
- // Print the header for the per-thread termination statistics.
- static void print_termination_stats_hdr();
- // Print actual per-thread termination statistics.
- void print_termination_stats(uint worker_id,
- double elapsed_ms,
- double strong_roots_ms,
- double term_ms,
- size_t term_attempts,
- size_t alloc_buffer_waste,
- size_t undo_waste) const;
// Update object copying statistics.
void record_obj_copy_mem_stats();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,26 +71,19 @@
}
if (!_g1h->is_in_closed_subset(obj)) {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- yy.print_cr("Field " PTR_FORMAT
- " of live obj " PTR_FORMAT " in region "
- "[" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(p), p2i(_containing_obj),
- p2i(from->bottom()), p2i(from->end()));
+ yy.print_cr("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
print_object(&yy, _containing_obj);
yy.print_cr("points to obj " PTR_FORMAT " not in the heap",
- p2i(obj));
+ p2i(obj));
} else {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
- yy.print_cr("Field " PTR_FORMAT
- " of live obj " PTR_FORMAT " in region "
- "[" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(p), p2i(_containing_obj),
- p2i(from->bottom()), p2i(from->end()));
+ yy.print_cr("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
print_object(&yy, _containing_obj);
- yy.print_cr("points to dead obj " PTR_FORMAT " in region "
- "[" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(obj), p2i(to->bottom()), p2i(to->end()));
+ yy.print_cr("points to dead obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(obj), HR_FORMAT_PARAMS(to));
print_object(&yy, obj);
}
yy.print_cr("----------");
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -60,6 +60,9 @@
_gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots (ms):");
_gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots (ms):");
_gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots (ms):");
+#if INCLUDE_AOT
+ _gc_par_phases[AOTCodeRoots] = new WorkerDataArray(max_gc_threads, "AOT Root Scan (ms):");
+#endif
_gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots (ms):");
_gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD (ms):");
_gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots (ms):");
@@ -74,9 +77,6 @@
_gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS (ms):");
_gc_par_phases[OptScanRS] = new WorkerDataArray(max_gc_threads, "Optional Scan RS (ms):");
_gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning (ms):");
-#if INCLUDE_AOT
- _gc_par_phases[AOTCodeRoots] = new WorkerDataArray(max_gc_threads, "AOT Root Scanning (ms):");
-#endif
_gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy (ms):");
_gc_par_phases[OptObjCopy] = new WorkerDataArray(max_gc_threads, "Optional Object Copy (ms):");
_gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination (ms):");
@@ -107,6 +107,11 @@
_update_rs_skipped_cards = new WorkerDataArray(max_gc_threads, "Skipped Cards:");
_gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_skipped_cards, UpdateRSSkippedCards);
+ _obj_copy_lab_waste = new WorkerDataArray(max_gc_threads, "LAB Waste");
+ _gc_par_phases[ObjCopy]->link_thread_work_items(_obj_copy_lab_waste, ObjCopyLABWaste);
+ _obj_copy_lab_undo_waste = new WorkerDataArray(max_gc_threads, "LAB Undo Waste");
+ _gc_par_phases[ObjCopy]->link_thread_work_items(_obj_copy_lab_undo_waste, ObjCopyLABUndoWaste);
+
_termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:");
_gc_par_phases[Termination]->link_thread_work_items(_termination_attempts);
@@ -383,15 +388,12 @@
for (int i = ThreadRoots; i <= SATBFiltering; i++) {
trace_phase(_gc_par_phases[i]);
}
+ if (G1HotCardCache::default_use_cache()) {
+ debug_phase(_gc_par_phases[ScanHCC]);
+ }
debug_phase(_gc_par_phases[UpdateRS]);
- if (G1HotCardCache::default_use_cache()) {
- trace_phase(_gc_par_phases[ScanHCC]);
- }
debug_phase(_gc_par_phases[ScanRS]);
debug_phase(_gc_par_phases[CodeRoots]);
-#if INCLUDE_AOT
- debug_phase(_gc_par_phases[AOTCodeRoots]);
-#endif
debug_phase(_gc_par_phases[ObjCopy]);
debug_phase(_gc_par_phases[Termination]);
debug_phase(_gc_par_phases[Other]);
@@ -503,6 +505,9 @@
"SystemDictionaryRoots",
"CLDGRoots",
"JVMTIRoots",
+#if INCLUDE_AOT
+ "AOTCodeRoots",
+#endif
"CMRefRoots",
"WaitForStrongCLD",
"WeakCLDRoots",
@@ -512,9 +517,6 @@
"ScanRS",
"OptScanRS",
"CodeRoots",
-#if INCLUDE_AOT
- "AOTCodeRoots",
-#endif
"ObjCopy",
"OptObjCopy",
"Termination",
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -55,6 +55,9 @@
SystemDictionaryRoots,
CLDGRoots,
JVMTIRoots,
+#if INCLUDE_AOT
+ AOTCodeRoots,
+#endif
CMRefRoots,
WaitForStrongCLD,
WeakCLDRoots,
@@ -64,9 +67,6 @@
ScanRS,
OptScanRS,
CodeRoots,
-#if INCLUDE_AOT
- AOTCodeRoots,
-#endif
ObjCopy,
OptObjCopy,
Termination,
@@ -93,6 +93,11 @@
UpdateRSSkippedCards
};
+ enum GCObjCopyWorkItems {
+ ObjCopyLABWaste,
+ ObjCopyLABUndoWaste
+ };
+
enum GCOptCSetWorkItems {
OptCSetScannedCards,
OptCSetClaimedCards,
@@ -114,6 +119,9 @@
WorkerDataArray* _scan_rs_claimed_cards;
WorkerDataArray* _scan_rs_skipped_cards;
+ WorkerDataArray* _obj_copy_lab_waste;
+ WorkerDataArray* _obj_copy_lab_undo_waste;
+
WorkerDataArray* _opt_cset_scanned_cards;
WorkerDataArray* _opt_cset_claimed_cards;
WorkerDataArray* _opt_cset_skipped_cards;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -106,8 +106,12 @@
delete[] _oops_into_optional_regions;
}
-void G1ParScanThreadState::waste(size_t& wasted, size_t& undo_wasted) {
- _plab_allocator->waste(wasted, undo_wasted);
+size_t G1ParScanThreadState::lab_waste_words() const {
+ return _plab_allocator->waste();
+}
+
+size_t G1ParScanThreadState::lab_undo_waste_words() const {
+ return _plab_allocator->undo_waste();
}
#ifdef ASSERT
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -127,9 +127,8 @@
G1EvacuationRootClosures* closures() { return _closures; }
uint worker_id() { return _worker_id; }
- // Returns the current amount of waste due to alignment or not being able to fit
- // objects within LABs and the undo waste.
- virtual void waste(size_t& wasted, size_t& undo_wasted);
+ size_t lab_waste_words() const;
+ size_t lab_undo_waste_words() const;
size_t* surviving_young_words() {
// We add one to hide entry 0 which accumulates surviving words for
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/g1RemSet.cpp
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -409,6 +409,10 @@
void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
EventGCPhaseParallel event;
+ // We pass a weak code blobs closure to the remembered set scanning because we want to avoid
+ // treating the nmethods visited to act as roots for concurrent marking.
+ // We only want to make sure that the oops in the nmethods are adjusted with regard to the
+ // objects copied by the current evacuation.
r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::CodeRoots));
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/g1/heapRegion.cpp
--- a/src/hotspot/share/gc/g1/heapRegion.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -336,8 +336,8 @@
// Object is in the region. Check that its less than top
if (_hr->top() <= (HeapWord*)obj) {
// Object is above top
- log_error(gc, verify)("Object " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ") is above top " PTR_FORMAT,
- p2i(obj), p2i(_hr->bottom()), p2i(_hr->end()), p2i(_hr->top()));
+ log_error(gc, verify)("Object " PTR_FORMAT " in region " HR_FORMAT " is above top ",
+ p2i(obj), HR_FORMAT_PARAMS(_hr));
_failures = true;
return;
}
@@ -415,8 +415,8 @@
// on its strong code root list
if (is_empty()) {
if (strong_code_roots_length > 0) {
- log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] is empty but has " SIZE_FORMAT " code root entries",
- p2i(bottom()), p2i(end()), strong_code_roots_length);
+ log_error(gc, verify)("region " HR_FORMAT " is empty but has " SIZE_FORMAT " code root entries",
+ HR_FORMAT_PARAMS(this), strong_code_roots_length);
*failures = true;
}
return;
@@ -524,21 +524,22 @@
ResourceMark rm;
if (!_g1h->is_in_closed_subset(obj)) {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
+ log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
LogStream ls(log.error());
print_object(&ls, _containing_obj);
HeapRegion* const to = _g1h->heap_region_containing(obj);
- log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT " remset %s", p2i(obj), HR_FORMAT_PARAMS(to), to->rem_set()->get_state_str());
+ log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT " remset %s",
+ p2i(obj), HR_FORMAT_PARAMS(to), to->rem_set()->get_state_str());
} else {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
- log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
+ log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
LogStream ls(log.error());
print_object(&ls, _containing_obj);
- log.error("points to dead obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
- p2i(obj), p2i(to->bottom()), p2i(to->end()));
+ log.error("points to dead obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(obj), HR_FORMAT_PARAMS(to));
print_object(&ls, obj);
}
log.error("----------");
@@ -593,12 +594,13 @@
log.error("----------");
}
log.error("Missing rem set entry:");
- log.error("Field " PTR_FORMAT " of obj " PTR_FORMAT ", in region " HR_FORMAT,
- p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
+ log.error("Field " PTR_FORMAT " of obj " PTR_FORMAT " in region " HR_FORMAT,
+ p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
ResourceMark rm;
LogStream ls(log.error());
_containing_obj->print_on(&ls);
- log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT " remset %s", p2i(obj), HR_FORMAT_PARAMS(to), to->rem_set()->get_state_str());
+ log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT " remset %s",
+ p2i(obj), HR_FORMAT_PARAMS(to), to->rem_set()->get_state_str());
if (oopDesc::is_oop(obj)) {
obj->print_on(&ls);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shared/genOopClosures.hpp
--- a/src/hotspot/share/gc/shared/genOopClosures.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shared/genOopClosures.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -29,7 +29,6 @@
#include "oops/oop.hpp"
class Generation;
-class HeapWord;
class CardTableRS;
class CardTableBarrierSet;
class DefNewGeneration;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shared/spaceDecorator.cpp
--- a/src/hotspot/share/gc/shared/spaceDecorator.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shared/spaceDecorator.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
// pattern.
bool SpaceMangler::is_mangled(HeapWord* q) {
// This test loses precision but is good enough
- return badHeapWord == (max_juint & (uintptr_t) q->value());
+ return badHeapWord == (max_juint & reinterpret_cast(*q));
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shared/vmStructs_gc.hpp
--- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,8 +156,6 @@
nonstatic_field(GenCollectedHeap, _young_gen_spec, GenerationSpec*) \
nonstatic_field(GenCollectedHeap, _old_gen_spec, GenerationSpec*) \
\
- nonstatic_field(HeapWord, i, char*) \
- \
nonstatic_field(MemRegion, _start, HeapWord*) \
nonstatic_field(MemRegion, _word_size, size_t) \
\
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -335,7 +335,7 @@
// Filter marked objects before hitting the SATB queues. The same predicate would
// be used by SATBMQ::filter to eliminate already marked objects downstream, but
// filtering here helps to avoid wasteful SATB queueing work to begin with.
- if (!_heap->requires_marking(obj)) return;
+ if (!_heap->requires_marking(obj)) return;
Thread* thr = Thread::current();
if (thr->is_Java_thread()) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -2639,6 +2639,10 @@
return memory_pools;
}
+MemoryUsage ShenandoahHeap::memory_usage() {
+ return _memory_pool->get_memory_usage();
+}
+
void ShenandoahHeap::enter_evacuation() {
_oom_evac_handler.enter_evacuation();
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -511,6 +511,7 @@
GrowableArray memory_managers();
GrowableArray memory_pools();
+ MemoryUsage memory_usage();
GCTracer* tracer();
GCTimer* gc_timer() const;
CollectorPolicy* collector_policy() const;
@@ -676,6 +677,7 @@
void reset_mark_bitmap();
// SATB barriers hooks
+ template
inline bool requires_marking(const void* entry) const;
void force_satb_flush_all_threads();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -316,8 +316,13 @@
}
}
+template
inline bool ShenandoahHeap::requires_marking(const void* entry) const {
- return !_marking_context->is_marked(oop(entry));
+ oop obj = oop(entry);
+ if (RESOLVE) {
+ obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+ }
+ return !_marking_context->is_marked(obj);
}
template
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
@@ -29,8 +29,6 @@
#include "memory/memRegion.hpp"
#include "oops/oopsHierarchy.hpp"
-class HeapWord;
-
/**
* Encapsulate a marking bitmap with the top-at-mark-start and top-bitmaps array.
*/
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -26,7 +26,7 @@
ShenandoahMemoryPool::ShenandoahMemoryPool(ShenandoahHeap* heap) :
CollectedMemoryPool("Shenandoah",
- heap->capacity(),
+ heap->initial_capacity(),
heap->max_capacity(),
true /* support_usage_threshold */),
_heap(heap) {}
@@ -37,9 +37,15 @@
size_t used = used_in_bytes();
size_t committed = _heap->committed();
+ // These asserts can never fail: max is stable, and all updates to other values never overflow max.
assert(initial <= max, "initial: " SIZE_FORMAT ", max: " SIZE_FORMAT, initial, max);
assert(used <= max, "used: " SIZE_FORMAT ", max: " SIZE_FORMAT, used, max);
assert(committed <= max, "committed: " SIZE_FORMAT ", max: " SIZE_FORMAT, committed, max);
+
+ // Committed and used are updated concurrently and independently. They can momentarily break
+ // the assert below, which would also fail in downstream code. To avoid that, adjust values
+ // to make sense under the race. See JDK-8207200.
+ committed = MAX2(used, committed);
assert(used <= committed, "used: " SIZE_FORMAT ", committed: " SIZE_FORMAT, used, committed);
return MemoryUsage(initial, used, committed, max);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
@@ -27,7 +27,6 @@
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
-class HeapWord;
class JavaThread;
class oopDesc;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -49,12 +49,9 @@
return ShenandoahThreadLocalData::satb_mark_queue(t);
}
-static inline bool discard_entry(const void* entry, ShenandoahHeap* heap) {
- return !heap->requires_marking(entry);
-}
-
+template
class ShenandoahSATBMarkQueueFilterFn {
- ShenandoahHeap* _heap;
+ ShenandoahHeap* const _heap;
public:
ShenandoahSATBMarkQueueFilterFn(ShenandoahHeap* heap) : _heap(heap) {}
@@ -62,13 +59,17 @@
// Return true if entry should be filtered out (removed), false if
// it should be retained.
bool operator()(const void* entry) const {
- return discard_entry(entry, _heap);
+ return !_heap->requires_marking(entry);
}
};
void ShenandoahSATBMarkQueueSet::filter(SATBMarkQueue* queue) {
assert(_heap != NULL, "SATB queue set not initialized");
- apply_filter(ShenandoahSATBMarkQueueFilterFn(_heap), queue);
+ if (_heap->has_forwarded_objects()) {
+ apply_filter(ShenandoahSATBMarkQueueFilterFn(_heap), queue);
+ } else {
+ apply_filter(ShenandoahSATBMarkQueueFilterFn(_heap), queue);
+ }
}
bool ShenandoahSATBMarkQueue::should_enqueue_buffer() {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/vmStructs_z.cpp
--- a/src/hotspot/share/gc/z/vmStructs_z.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/vmStructs_z.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
ZGlobalsForVMStructs::ZGlobalsForVMStructs() :
_ZGlobalPhase(&ZGlobalPhase),
+ _ZGlobalSeqNum(&ZGlobalSeqNum),
_ZAddressGoodMask(&ZAddressGoodMask),
_ZAddressBadMask(&ZAddressBadMask),
_ZAddressWeakBadMask(&ZAddressWeakBadMask),
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/vmStructs_z.hpp
--- a/src/hotspot/share/gc/z/vmStructs_z.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/vmStructs_z.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -42,6 +42,8 @@
uint32_t* _ZGlobalPhase;
+ uint32_t* _ZGlobalSeqNum;
+
uintptr_t* _ZAddressGoodMask;
uintptr_t* _ZAddressBadMask;
uintptr_t* _ZAddressWeakBadMask;
@@ -55,6 +57,7 @@
#define VM_STRUCTS_ZGC(nonstatic_field, volatile_nonstatic_field, static_field) \
static_field(ZGlobalsForVMStructs, _instance_p, ZGlobalsForVMStructs*) \
nonstatic_field(ZGlobalsForVMStructs, _ZGlobalPhase, uint32_t*) \
+ nonstatic_field(ZGlobalsForVMStructs, _ZGlobalSeqNum, uint32_t*) \
nonstatic_field(ZGlobalsForVMStructs, _ZAddressGoodMask, uintptr_t*) \
nonstatic_field(ZGlobalsForVMStructs, _ZAddressBadMask, uintptr_t*) \
nonstatic_field(ZGlobalsForVMStructs, _ZAddressWeakBadMask, uintptr_t*) \
@@ -67,7 +70,10 @@
nonstatic_field(ZHeap, _pagetable, ZPageTable) \
\
nonstatic_field(ZPage, _type, const uint8_t) \
+ nonstatic_field(ZPage, _seqnum, uint32_t) \
nonstatic_field(ZPage, _virtual, const ZVirtualMemory) \
+ volatile_nonstatic_field(ZPage, _top, uintptr_t) \
+ volatile_nonstatic_field(ZPage, _refcount, uint32_t) \
nonstatic_field(ZPage, _forwarding, ZForwardingTable) \
\
nonstatic_field(ZPageAllocator, _physical, ZPhysicalMemoryManager) \
@@ -101,6 +107,7 @@
declare_constant(ZAddressOffsetShift) \
declare_constant(ZAddressOffsetBits) \
declare_constant(ZAddressOffsetMask) \
+ declare_constant(ZAddressOffsetMax) \
declare_constant(ZAddressSpaceStart)
#define VM_TYPES_ZGC(declare_type, declare_toplevel_type, declare_integer_type) \
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zBarrierSetNMethod.cpp
--- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -27,12 +27,12 @@
#include "gc/z/zGlobals.hpp"
#include "gc/z/zLock.inline.hpp"
#include "gc/z/zOopClosures.hpp"
-#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethod.hpp"
#include "gc/z/zThreadLocalData.hpp"
#include "logging/log.hpp"
bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
- ZLocker locker(ZNMethodTable::lock_for_nmethod(nm));
+ ZLocker locker(ZNMethod::lock_for_nmethod(nm));
log_trace(nmethod, barrier)("Entered critical zone for %p", nm);
if (!is_armed(nm)) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zCollectedHeap.cpp
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zHeap.inline.hpp"
-#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethod.hpp"
#include "gc/z/zServiceability.hpp"
#include "gc/z/zStat.hpp"
#include "gc/z/zUtils.inline.hpp"
@@ -118,10 +118,6 @@
return is_in(p);
}
-void ZCollectedHeap::fill_with_dummy_object(HeapWord* start, HeapWord* end, bool zap) {
- // Does nothing, not a parsable heap
-}
-
HeapWord* ZCollectedHeap::allocate_new_tlab(size_t min_size, size_t requested_size, size_t* actual_size) {
const size_t size_in_bytes = ZUtils::words_to_bytes(align_object_size(requested_size));
const uintptr_t addr = _heap.alloc_tlab(size_in_bytes);
@@ -259,11 +255,11 @@
}
void ZCollectedHeap::register_nmethod(nmethod* nm) {
- ZNMethodTable::register_nmethod(nm);
+ ZNMethod::register_nmethod(nm);
}
void ZCollectedHeap::unregister_nmethod(nmethod* nm) {
- ZNMethodTable::unregister_nmethod(nm);
+ ZNMethod::unregister_nmethod(nm);
}
void ZCollectedHeap::verify_nmethod(nmethod* nm) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zCollectedHeap.hpp
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,8 +75,6 @@
virtual bool is_in(const void* p) const;
virtual bool is_in_closed_subset(const void* p) const;
- virtual void fill_with_dummy_object(HeapWord* start, HeapWord* end, bool zap);
-
virtual HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
virtual MetaWord* satisfy_failed_metadata_allocation(ClassLoaderData* loader_data,
size_t size,
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zInitialize.cpp
--- a/src/hotspot/share/gc/z/zInitialize.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zInitialize.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
#include "gc/z/zLargePages.hpp"
#include "gc/z/zNUMA.hpp"
#include "gc/z/zStat.hpp"
-#include "gc/z/zStatTLAB.hpp"
+#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zTracer.hpp"
#include "logging/log.hpp"
#include "runtime/vm_version.hpp"
@@ -46,7 +46,7 @@
ZNUMA::initialize();
ZCPU::initialize();
ZStatValue::initialize();
- ZStatTLAB::initialize();
+ ZThreadLocalAllocBuffer::initialize();
ZTracer::initialize();
ZLargePages::initialize();
ZBarrierSet::set_barrier_set(barrier_set);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zMark.cpp
--- a/src/hotspot/share/gc/z/zMark.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zMark.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,9 @@
#include "gc/z/zPageTable.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
#include "gc/z/zStat.hpp"
-#include "gc/z/zStatTLAB.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zThread.hpp"
+#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zUtils.inline.hpp"
#include "gc/z/zWorkers.inline.hpp"
#include "logging/log.hpp"
@@ -121,24 +121,19 @@
class ZMarkRootsIteratorClosure : public ZRootsIteratorClosure {
public:
ZMarkRootsIteratorClosure() {
- ZStatTLAB::reset();
+ ZThreadLocalAllocBuffer::reset_statistics();
}
~ZMarkRootsIteratorClosure() {
- ZStatTLAB::publish();
+ ZThreadLocalAllocBuffer::publish_statistics();
}
virtual void do_thread(Thread* thread) {
- ZRootsIteratorClosure::do_thread(thread);
-
// Update thread local address bad mask
ZThreadLocalData::set_address_bad_mask(thread, ZAddressBadMask);
// Retire TLAB
- if (UseTLAB && thread->is_Java_thread()) {
- thread->tlab().retire(ZStatTLAB::get());
- thread->tlab().resize();
- }
+ ZThreadLocalAllocBuffer::retire(thread);
}
virtual void do_oop(oop* p) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethod.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethod.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "code/relocInfo.hpp"
+#include "code/nmethod.hpp"
+#include "code/icBuffer.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetNMethod.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zLock.inline.hpp"
+#include "gc/z/zNMethod.hpp"
+#include "gc/z/zNMethodData.hpp"
+#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zOopClosures.inline.hpp"
+#include "gc/z/zTask.hpp"
+#include "gc/z/zWorkers.hpp"
+#include "logging/log.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/iterator.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+#include "utilities/debug.hpp"
+
+static ZNMethodData* gc_data(const nmethod* nm) {
+ return nm->gc_data();
+}
+
+static void set_gc_data(nmethod* nm, ZNMethodData* data) {
+ return nm->set_gc_data(data);
+}
+
+void ZNMethod::attach_gc_data(nmethod* nm) {
+ GrowableArray immediate_oops;
+ bool non_immediate_oops = false;
+
+ // Find all oops relocations
+ RelocIterator iter(nm);
+ while (iter.next()) {
+ if (iter.type() != relocInfo::oop_type) {
+ // Not an oop
+ continue;
+ }
+
+ oop_Relocation* r = iter.oop_reloc();
+
+ if (!r->oop_is_immediate()) {
+ // Non-immediate oop found
+ non_immediate_oops = true;
+ continue;
+ }
+
+ if (r->oop_value() != NULL) {
+ // Non-NULL immediate oop found. NULL oops can safely be
+ // ignored since the method will be re-registered if they
+ // are later patched to be non-NULL.
+ immediate_oops.push(r->oop_addr());
+ }
+ }
+
+ // Attach GC data to nmethod
+ ZNMethodData* data = gc_data(nm);
+ if (data == NULL) {
+ data = ZNMethodData::create(nm);
+ set_gc_data(nm, data);
+ }
+
+ // Attach oops in GC data
+ ZNMethodDataOops* const new_oops = ZNMethodDataOops::create(immediate_oops, non_immediate_oops);
+ ZNMethodDataOops* const old_oops = data->swap_oops(new_oops);
+ ZNMethodDataOops::destroy(old_oops);
+}
+
+void ZNMethod::detach_gc_data(nmethod* nm) {
+ // Destroy GC data
+ ZNMethodData::destroy(gc_data(nm));
+ set_gc_data(nm, NULL);
+}
+
+ZReentrantLock* ZNMethod::lock_for_nmethod(nmethod* nm) {
+ ZNMethodData* const data = gc_data(nm);
+ if (data == NULL) {
+ return NULL;
+ }
+ return data->lock();
+}
+
+void ZNMethod::log_register(const nmethod* nm) {
+ LogTarget(Trace, gc, nmethod) log;
+ if (!log.is_enabled()) {
+ return;
+ }
+
+ const ZNMethodDataOops* const oops = gc_data(nm)->oops();
+
+ log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
+ "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
+ nm->method()->method_holder()->external_name(),
+ nm->method()->name()->as_C_string(),
+ p2i(nm),
+ nm->compiler_name(),
+ nm->oops_count() - 1,
+ oops->immediates_count(),
+ oops->has_non_immediates() ? "Yes" : "No");
+
+ LogTarget(Trace, gc, nmethod, oops) log_oops;
+ if (!log_oops.is_enabled()) {
+ return;
+ }
+
+ // Print nmethod oops table
+ {
+ oop* const begin = nm->oops_begin();
+ oop* const end = nm->oops_end();
+ for (oop* p = begin; p < end; p++) {
+ log_oops.print(" Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
+ (p - begin), p2i(*p), (*p)->klass()->external_name());
+ }
+ }
+
+ // Print nmethod immediate oops
+ {
+ oop** const begin = oops->immediates_begin();
+ oop** const end = oops->immediates_end();
+ for (oop** p = begin; p < end; p++) {
+ log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
+ (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
+ }
+ }
+}
+
+void ZNMethod::log_unregister(const nmethod* nm) {
+ LogTarget(Debug, gc, nmethod) log;
+ if (!log.is_enabled()) {
+ return;
+ }
+
+ log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
+ nm->method()->method_holder()->external_name(),
+ nm->method()->name()->as_C_string(),
+ p2i(nm));
+}
+
+void ZNMethod::register_nmethod(nmethod* nm) {
+ ResourceMark rm;
+
+ // Create and attach gc data
+ attach_gc_data(nm);
+
+ log_register(nm);
+
+ ZNMethodTable::register_nmethod(nm);
+
+ // Disarm nmethod entry barrier
+ disarm_nmethod(nm);
+}
+
+void ZNMethod::unregister_nmethod(nmethod* nm) {
+ assert(CodeCache_lock->owned_by_self(), "Lock must be held");
+
+ if (Thread::current()->is_Code_cache_sweeper_thread()) {
+ // The sweeper must wait for any ongoing iteration to complete
+ // before it can unregister an nmethod.
+ ZNMethodTable::wait_until_iteration_done();
+ }
+
+ ResourceMark rm;
+
+ log_unregister(nm);
+
+ ZNMethodTable::unregister_nmethod(nm);
+
+ // Destroy and detach gc data
+ detach_gc_data(nm);
+}
+
+void ZNMethod::disarm_nmethod(nmethod* nm) {
+ BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
+ if (bs != NULL) {
+ bs->disarm(nm);
+ }
+}
+
+void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {
+ // Process oops table
+ {
+ oop* const begin = nm->oops_begin();
+ oop* const end = nm->oops_end();
+ for (oop* p = begin; p < end; p++) {
+ if (*p != Universe::non_oop_word()) {
+ cl->do_oop(p);
+ }
+ }
+ }
+
+ ZNMethodDataOops* const oops = gc_data(nm)->oops();
+
+ // Process immediate oops
+ {
+ oop** const begin = oops->immediates_begin();
+ oop** const end = oops->immediates_end();
+ for (oop** p = begin; p < end; p++) {
+ if (**p != Universe::non_oop_word()) {
+ cl->do_oop(*p);
+ }
+ }
+ }
+
+ // Process non-immediate oops
+ if (oops->has_non_immediates()) {
+ nm->fix_oop_relocations();
+ }
+}
+
+class ZNMethodToOopsDoClosure : public NMethodClosure {
+private:
+ OopClosure* _cl;
+
+public:
+ ZNMethodToOopsDoClosure(OopClosure* cl) :
+ _cl(cl) {}
+
+ virtual void do_nmethod(nmethod* nm) {
+ ZNMethod::nmethod_oops_do(nm, _cl);
+ }
+};
+
+void ZNMethod::oops_do_begin() {
+ ZNMethodTable::nmethods_do_begin();
+}
+
+void ZNMethod::oops_do_end() {
+ ZNMethodTable::nmethods_do_end();
+}
+
+void ZNMethod::oops_do(OopClosure* cl) {
+ ZNMethodToOopsDoClosure nmethod_cl(cl);
+ ZNMethodTable::nmethods_do(&nmethod_cl);
+}
+
+class ZNMethodUnlinkClosure : public NMethodClosure {
+private:
+ bool _unloading_occurred;
+ volatile bool _failed;
+
+ void set_failed() {
+ Atomic::store(true, &_failed);
+ }
+
+public:
+ ZNMethodUnlinkClosure(bool unloading_occurred) :
+ _unloading_occurred(unloading_occurred),
+ _failed(false) {}
+
+ virtual void do_nmethod(nmethod* nm) {
+ if (failed()) {
+ return;
+ }
+
+ if (!nm->is_alive()) {
+ return;
+ }
+
+ ZLocker locker(ZNMethod::lock_for_nmethod(nm));
+
+ if (nm->is_unloading()) {
+ // Unlinking of the dependencies must happen before the
+ // handshake separating unlink and purge.
+ nm->flush_dependencies(false /* delete_immediately */);
+
+ // We don't need to take the lock when unlinking nmethods from
+ // the Method, because it is only concurrently unlinked by
+ // the entry barrier, which acquires the per nmethod lock.
+ nm->unlink_from_method(false /* acquire_lock */);
+ return;
+ }
+
+ // Heal oops and disarm
+ ZNMethodOopClosure cl;
+ ZNMethod::nmethod_oops_do(nm, &cl);
+ ZNMethod::disarm_nmethod(nm);
+
+ // Clear compiled ICs and exception caches
+ if (!nm->unload_nmethod_caches(_unloading_occurred)) {
+ set_failed();
+ }
+ }
+
+ bool failed() const {
+ return Atomic::load(&_failed);
+ }
+};
+
+class ZNMethodUnlinkTask : public ZTask {
+private:
+ ZNMethodUnlinkClosure _cl;
+ ICRefillVerifier* _verifier;
+
+public:
+ ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
+ ZTask("ZNMethodUnlinkTask"),
+ _cl(unloading_occurred),
+ _verifier(verifier) {
+ ZNMethodTable::nmethods_do_begin();
+ }
+
+ ~ZNMethodUnlinkTask() {
+ ZNMethodTable::nmethods_do_end();
+ }
+
+ virtual void work() {
+ ICRefillVerifierMark mark(_verifier);
+ ZNMethodTable::nmethods_do(&_cl);
+ }
+
+ bool success() const {
+ return !_cl.failed();
+ }
+};
+
+void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
+ for (;;) {
+ ICRefillVerifier verifier;
+
+ {
+ ZNMethodUnlinkTask task(unloading_occurred, &verifier);
+ workers->run_concurrent(&task);
+ if (task.success()) {
+ return;
+ }
+ }
+
+ // Cleaning failed because we ran out of transitional IC stubs,
+ // so we have to refill and try again. Refilling requires taking
+ // a safepoint, so we temporarily leave the suspendible thread set.
+ SuspendibleThreadSetLeaver sts;
+ InlineCacheBuffer::refill_ic_stubs();
+ }
+}
+
+class ZNMethodPurgeClosure : public NMethodClosure {
+public:
+ virtual void do_nmethod(nmethod* nm) {
+ if (nm->is_alive() && nm->is_unloading()) {
+ nm->make_unloaded();
+ }
+ }
+};
+
+class ZNMethodPurgeTask : public ZTask {
+private:
+ ZNMethodPurgeClosure _cl;
+
+public:
+ ZNMethodPurgeTask() :
+ ZTask("ZNMethodPurgeTask"),
+ _cl() {
+ ZNMethodTable::nmethods_do_begin();
+ }
+
+ ~ZNMethodPurgeTask() {
+ ZNMethodTable::nmethods_do_end();
+ }
+
+ virtual void work() {
+ ZNMethodTable::nmethods_do(&_cl);
+ }
+};
+
+void ZNMethod::purge(ZWorkers* workers) {
+ ZNMethodPurgeTask task;
+ workers->run_concurrent(&task);
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethod.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethod.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_GC_Z_ZNMETHOD_HPP
+#define SHARE_GC_Z_ZNMETHOD_HPP
+
+#include "memory/allocation.hpp"
+
+class nmethod;
+class OopClosure;
+class ZReentrantLock;
+class ZWorkers;
+
+class ZNMethod : public AllStatic {
+private:
+ static void attach_gc_data(nmethod* nm);
+ static void detach_gc_data(nmethod* nm);
+
+ static void log_register(const nmethod* nm);
+ static void log_unregister(const nmethod* nm);
+
+public:
+ static void register_nmethod(nmethod* nm);
+ static void unregister_nmethod(nmethod* nm);
+
+ static void disarm_nmethod(nmethod* nm);
+
+ static void nmethod_oops_do(nmethod* nm, OopClosure* cl);
+
+ static void oops_do_begin();
+ static void oops_do_end();
+ static void oops_do(OopClosure* cl);
+
+ static ZReentrantLock* lock_for_nmethod(nmethod* nm);
+
+ static void unlink(ZWorkers* workers, bool unloading_occurred);
+ static void purge(ZWorkers* workers);
+};
+
+#endif // SHARE_GC_Z_ZNMETHOD_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodAllocator.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodAllocator.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zArray.inline.hpp"
+#include "gc/z/zNMethodAllocator.hpp"
+#include "memory/allocation.hpp"
+
+ZArray ZNMethodAllocator::_deferred_frees;
+bool ZNMethodAllocator::_defer_frees(false);
+
+void ZNMethodAllocator::immediate_free(void* data) {
+ FREE_C_HEAP_ARRAY(uint8_t, data);
+}
+
+void ZNMethodAllocator::deferred_free(void* data) {
+ _deferred_frees.add(data);
+}
+
+void* ZNMethodAllocator::allocate(size_t size) {
+ return NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
+}
+
+void ZNMethodAllocator::free(void* data) {
+ if (data == NULL) {
+ return;
+ }
+
+ if (_defer_frees) {
+ deferred_free(data);
+ } else {
+ immediate_free(data);
+ }
+}
+
+void ZNMethodAllocator::activate_deferred_frees() {
+ assert(_deferred_frees.is_empty(), "precondition");
+ _defer_frees = true;
+}
+
+void ZNMethodAllocator::deactivate_and_process_deferred_frees() {
+ _defer_frees = false;
+
+ ZArrayIterator iter(&_deferred_frees);
+ for (void* data; iter.next(&data);) {
+ immediate_free(data);
+ }
+ _deferred_frees.clear();
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodAllocator.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodAllocator.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
+#define SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
+
+#include "memory/allocation.hpp"
+#include "gc/z/zArray.hpp"
+
+class ZNMethodAllocator : public AllStatic {
+private:
+ static ZArray _deferred_frees;
+ static bool _defer_frees;
+
+ static void immediate_free(void* data);
+ static void deferred_free(void* data);
+
+public:
+ static void* allocate(size_t size);
+ static void free(void* data);
+
+ static void activate_deferred_frees();
+ static void deactivate_and_process_deferred_frees();
+};
+
+#endif // SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodData.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodData.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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/z/zLock.inline.hpp"
+#include "gc/z/zNMethodAllocator.hpp"
+#include "gc/z/zNMethodData.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+#include "utilities/align.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/growableArray.hpp"
+
+size_t ZNMethodDataOops::header_size() {
+ const size_t size = sizeof(ZNMethodDataOops);
+ assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
+ return size;
+}
+
+ZNMethodDataOops* ZNMethodDataOops::create(const GrowableArray& immediates, bool has_non_immediates) {
+ // Allocate memory for the ZNMethodDataOops object
+ // plus the immediate oop* array that follows right after.
+ const size_t size = ZNMethodDataOops::header_size() + (sizeof(oop*) * immediates.length());
+ void* const mem = ZNMethodAllocator::allocate(size);
+ return ::new (mem) ZNMethodDataOops(immediates, has_non_immediates);
+}
+
+void ZNMethodDataOops::destroy(ZNMethodDataOops* oops) {
+ ZNMethodAllocator::free(oops);
+}
+
+ZNMethodDataOops::ZNMethodDataOops(const GrowableArray& immediates, bool has_non_immediates) :
+ _nimmediates(immediates.length()),
+ _has_non_immediates(has_non_immediates) {
+ // Save all immediate oops
+ for (size_t i = 0; i < _nimmediates; i++) {
+ immediates_begin()[i] = immediates.at(i);
+ }
+}
+
+size_t ZNMethodDataOops::immediates_count() const {
+ return _nimmediates;
+}
+
+oop** ZNMethodDataOops::immediates_begin() const {
+ // The immediate oop* array starts immediately after this object
+ return (oop**)((uintptr_t)this + header_size());
+}
+
+oop** ZNMethodDataOops::immediates_end() const {
+ return immediates_begin() + immediates_count();
+}
+
+bool ZNMethodDataOops::has_non_immediates() const {
+ return _has_non_immediates;
+}
+
+ZNMethodData* ZNMethodData::create(nmethod* nm) {
+ void* const mem = ZNMethodAllocator::allocate(sizeof(ZNMethodData));
+ return ::new (mem) ZNMethodData(nm);
+}
+
+void ZNMethodData::destroy(ZNMethodData* data) {
+ ZNMethodAllocator::free(data->oops());
+ ZNMethodAllocator::free(data);
+}
+
+ZNMethodData::ZNMethodData(nmethod* nm) :
+ _lock(),
+ _oops(NULL) {}
+
+ZReentrantLock* ZNMethodData::lock() {
+ return &_lock;
+}
+
+ZNMethodDataOops* ZNMethodData::oops() const {
+ return OrderAccess::load_acquire(&_oops);
+}
+
+ZNMethodDataOops* ZNMethodData::swap_oops(ZNMethodDataOops* new_oops) {
+ return Atomic::xchg(new_oops, &_oops);
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodData.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodData.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "gc/z/zLock.hpp"
+#include "oops/oopsHierarchy.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+#ifndef SHARE_GC_Z_ZNMETHODDATA_HPP
+#define SHARE_GC_Z_ZNMETHODDATA_HPP
+
+class nmethod;
+template class GrowableArray;
+
+class ZNMethodDataOops {
+private:
+ const size_t _nimmediates;
+ bool _has_non_immediates;
+
+ static size_t header_size();
+
+ ZNMethodDataOops(const GrowableArray& immediates, bool has_non_immediates);
+
+public:
+ static ZNMethodDataOops* create(const GrowableArray& immediates, bool has_non_immediates);
+ static void destroy(ZNMethodDataOops* oops);
+
+ size_t immediates_count() const;
+ oop** immediates_begin() const;
+ oop** immediates_end() const;
+
+ bool has_non_immediates() const;
+};
+
+class ZNMethodData {
+private:
+ ZReentrantLock _lock;
+ ZNMethodDataOops* volatile _oops;
+
+ ZNMethodData(nmethod* nm);
+
+public:
+ static ZNMethodData* create(nmethod* nm);
+ static void destroy(ZNMethodData* data);
+
+ ZReentrantLock* lock();
+
+ ZNMethodDataOops* oops() const;
+ ZNMethodDataOops* swap_oops(ZNMethodDataOops* oops);
+};
+
+#endif // SHARE_GC_Z_ZNMETHODDATA_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodTable.cpp
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,205 +27,38 @@
#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
-#include "gc/z/zArray.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zHash.inline.hpp"
#include "gc/z/zLock.inline.hpp"
+#include "gc/z/zNMethodAllocator.hpp"
+#include "gc/z/zNMethodData.hpp"
#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethodTableEntry.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
#include "gc/z/zOopClosures.inline.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zWorkers.hpp"
#include "logging/log.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
+#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
-#include "runtime/os.hpp"
#include "utilities/debug.hpp"
-class ZNMethodDataImmediateOops {
-private:
- const size_t _nimmediate_oops;
-
- static size_t header_size();
-
- ZNMethodDataImmediateOops(const GrowableArray& immediate_oops);
-
-public:
- static ZNMethodDataImmediateOops* create(const GrowableArray& immediate_oops);
- static void destroy(ZNMethodDataImmediateOops* data_immediate_oops);
-
- size_t immediate_oops_count() const;
- oop** immediate_oops_begin() const;
- oop** immediate_oops_end() const;
-};
-
-size_t ZNMethodDataImmediateOops::header_size() {
- const size_t size = sizeof(ZNMethodDataImmediateOops);
- assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
- return size;
-}
-
-ZNMethodDataImmediateOops* ZNMethodDataImmediateOops::create(const GrowableArray& immediate_oops) {
- // Allocate memory for the ZNMethodDataImmediateOops object
- // plus the immediate oop* array that follows right after.
- const size_t size = ZNMethodDataImmediateOops::header_size() + (sizeof(oop*) * immediate_oops.length());
- void* const data_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
- return ::new (data_immediate_oops) ZNMethodDataImmediateOops(immediate_oops);
-}
-
-void ZNMethodDataImmediateOops::destroy(ZNMethodDataImmediateOops* data_immediate_oops) {
- ZNMethodTable::safe_delete(data_immediate_oops);
-}
-
-ZNMethodDataImmediateOops::ZNMethodDataImmediateOops(const GrowableArray& immediate_oops) :
- _nimmediate_oops(immediate_oops.length()) {
- // Save all immediate oops
- for (size_t i = 0; i < _nimmediate_oops; i++) {
- immediate_oops_begin()[i] = immediate_oops.at(i);
- }
-}
-
-size_t ZNMethodDataImmediateOops::immediate_oops_count() const {
- return _nimmediate_oops;
-}
-
-oop** ZNMethodDataImmediateOops::immediate_oops_begin() const {
- // The immediate oop* array starts immediately after this object
- return (oop**)((uintptr_t)this + header_size());
-}
-
-oop** ZNMethodDataImmediateOops::immediate_oops_end() const {
- return immediate_oops_begin() + immediate_oops_count();
-}
-
-class ZNMethodData {
-private:
- ZReentrantLock _lock;
- ZNMethodDataImmediateOops* volatile _immediate_oops;
-
- ZNMethodData(nmethod* nm);
-
-public:
- static ZNMethodData* create(nmethod* nm);
- static void destroy(ZNMethodData* data);
-
- ZReentrantLock* lock();
-
- ZNMethodDataImmediateOops* immediate_oops() const;
- ZNMethodDataImmediateOops* swap_immediate_oops(const GrowableArray& immediate_oops);
-};
-
-ZNMethodData* ZNMethodData::create(nmethod* nm) {
- void* const method = NEW_C_HEAP_ARRAY(uint8_t, sizeof(ZNMethodData), mtGC);
- return ::new (method) ZNMethodData(nm);
-}
-
-void ZNMethodData::destroy(ZNMethodData* data) {
- ZNMethodDataImmediateOops::destroy(data->immediate_oops());
- ZNMethodTable::safe_delete(data);
-}
-
-ZNMethodData::ZNMethodData(nmethod* nm) :
- _lock(),
- _immediate_oops(NULL) {}
-
-ZReentrantLock* ZNMethodData::lock() {
- return &_lock;
-}
-
-ZNMethodDataImmediateOops* ZNMethodData::immediate_oops() const {
- return OrderAccess::load_acquire(&_immediate_oops);
-}
-
-ZNMethodDataImmediateOops* ZNMethodData::swap_immediate_oops(const GrowableArray& immediate_oops) {
- ZNMethodDataImmediateOops* const data_immediate_oops =
- immediate_oops.is_empty() ? NULL : ZNMethodDataImmediateOops::create(immediate_oops);
- return Atomic::xchg(data_immediate_oops, &_immediate_oops);
-}
-
-static ZNMethodData* gc_data(const nmethod* nm) {
- return nm->gc_data();
-}
-
-static void set_gc_data(nmethod* nm, ZNMethodData* data) {
- return nm->set_gc_data(data);
-}
-
ZNMethodTableEntry* ZNMethodTable::_table = NULL;
size_t ZNMethodTable::_size = 0;
-ZLock ZNMethodTable::_iter_lock;
-ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL;
-size_t ZNMethodTable::_iter_table_size = 0;
-ZArray ZNMethodTable::_iter_deferred_deletes;
size_t ZNMethodTable::_nregistered = 0;
size_t ZNMethodTable::_nunregistered = 0;
-volatile size_t ZNMethodTable::_claimed = 0;
-
-void ZNMethodTable::safe_delete(void* data) {
- if (data == NULL) {
- return;
- }
+ZNMethodTableIteration ZNMethodTable::_iteration;
- ZLocker locker(&_iter_lock);
- if (_iter_table != NULL) {
- // Iteration in progress, defer delete
- _iter_deferred_deletes.add(data);
- } else {
- // Iteration not in progress, delete now
- FREE_C_HEAP_ARRAY(uint8_t, data);
- }
+ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
+ void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
+ return ::new (mem) ZNMethodTableEntry[size];
}
-ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
- GrowableArray immediate_oops;
- bool non_immediate_oops = false;
-
- // Find all oops relocations
- RelocIterator iter(nm);
- while (iter.next()) {
- if (iter.type() != relocInfo::oop_type) {
- // Not an oop
- continue;
- }
-
- oop_Relocation* r = iter.oop_reloc();
-
- if (!r->oop_is_immediate()) {
- // Non-immediate oop found
- non_immediate_oops = true;
- continue;
- }
-
- if (r->oop_value() != NULL) {
- // Non-NULL immediate oop found. NULL oops can safely be
- // ignored since the method will be re-registered if they
- // are later patched to be non-NULL.
- immediate_oops.push(r->oop_addr());
- }
- }
-
- // Attach GC data to nmethod
- ZNMethodData* data = gc_data(nm);
- if (data == NULL) {
- data = ZNMethodData::create(nm);
- set_gc_data(nm, data);
- }
-
- // Attach immediate oops in GC data
- ZNMethodDataImmediateOops* const old_data_immediate_oops = data->swap_immediate_oops(immediate_oops);
- ZNMethodDataImmediateOops::destroy(old_data_immediate_oops);
-
- // Create entry
- return ZNMethodTableEntry(nm, non_immediate_oops, !immediate_oops.is_empty());
-}
-
-ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) {
- ZNMethodData* const data = gc_data(nm);
- if (data == NULL) {
- return NULL;
- }
- return data->lock();
+void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
+ ZNMethodAllocator::free(table);
}
size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
@@ -241,8 +74,8 @@
return (prev_index + 1) & mask;
}
-bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry) {
- const nmethod* const nm = entry.method();
+bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) {
+ const ZNMethodTableEntry entry(nm);
size_t index = first_index(nm, size);
for (;;) {
@@ -265,11 +98,6 @@
}
void ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) {
- if (size == 0) {
- // Table is empty
- return;
- }
-
size_t index = first_index(nm, size);
for (;;) {
@@ -279,10 +107,6 @@
if (table_entry.registered() && table_entry.method() == nm) {
// Remove entry
table[index] = ZNMethodTableEntry(true /* unregistered */);
-
- // Destroy GC data
- ZNMethodData::destroy(gc_data(nm));
- set_gc_data(nm, NULL);
return;
}
@@ -291,7 +115,8 @@
}
void ZNMethodTable::rebuild(size_t new_size) {
- ZLocker locker(&_iter_lock);
+ assert(CodeCache_lock->owned_by_self(), "Lock must be held");
+
assert(is_power_of_2(new_size), "Invalid size");
log_debug(gc, nmethod)("Rebuilding NMethod Table: "
@@ -303,20 +128,18 @@
_nunregistered, percent_of(_nunregistered, _size), 0.0);
// Allocate new table
- ZNMethodTableEntry* const new_table = new ZNMethodTableEntry[new_size];
+ ZNMethodTableEntry* const new_table = ZNMethodTable::create(new_size);
// Transfer all registered entries
for (size_t i = 0; i < _size; i++) {
const ZNMethodTableEntry entry = _table[i];
if (entry.registered()) {
- register_entry(new_table, new_size, entry);
+ register_entry(new_table, new_size, entry.method());
}
}
- if (_iter_table != _table) {
- // Delete old table
- delete [] _table;
- }
+ // Free old table
+ ZNMethodTable::destroy(_table);
// Install new table
_table = new_table;
@@ -353,61 +176,6 @@
}
}
-void ZNMethodTable::log_register(const nmethod* nm, ZNMethodTableEntry entry) {
- LogTarget(Trace, gc, nmethod) log;
- if (!log.is_enabled()) {
- return;
- }
-
- log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
- "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
- nm->method()->method_holder()->external_name(),
- nm->method()->name()->as_C_string(),
- p2i(nm),
- nm->compiler_name(),
- nm->oops_count() - 1,
- entry.immediate_oops() ? gc_data(nm)->immediate_oops()->immediate_oops_count() : 0,
- entry.non_immediate_oops() ? "Yes" : "No");
-
- LogTarget(Trace, gc, nmethod, oops) log_oops;
- if (!log_oops.is_enabled()) {
- return;
- }
-
- // Print nmethod oops table
- oop* const begin = nm->oops_begin();
- oop* const end = nm->oops_end();
- for (oop* p = begin; p < end; p++) {
- log_oops.print(" Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
- (p - begin), p2i(*p), (*p)->klass()->external_name());
- }
-
- if (entry.immediate_oops()) {
- // Print nmethod immediate oops
- const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
- if (nmi != NULL) {
- oop** const begin = nmi->immediate_oops_begin();
- oop** const end = nmi->immediate_oops_end();
- for (oop** p = begin; p < end; p++) {
- log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
- (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
- }
- }
- }
-}
-
-void ZNMethodTable::log_unregister(const nmethod* nm) {
- LogTarget(Debug, gc, nmethod) log;
- if (!log.is_enabled()) {
- return;
- }
-
- log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
- nm->method()->method_holder()->external_name(),
- nm->method()->name()->as_C_string(),
- p2i(nm));
-}
-
size_t ZNMethodTable::registered_nmethods() {
return _nregistered;
}
@@ -418,48 +186,29 @@
void ZNMethodTable::register_nmethod(nmethod* nm) {
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
- ResourceMark rm;
// Grow/Shrink/Prune table if needed
rebuild_if_needed();
- // Create entry
- const ZNMethodTableEntry entry = create_entry(nm);
-
- log_register(nm, entry);
-
// Insert new entry
- if (register_entry(_table, _size, entry)) {
+ if (register_entry(_table, _size, nm)) {
// New entry registered. When register_entry() instead returns
// false the nmethod was already in the table so we do not want
// to increase number of registered entries in that case.
_nregistered++;
}
-
- // Disarm nmethod entry barrier
- disarm_nmethod(nm);
}
-void ZNMethodTable::sweeper_wait_for_iteration() {
- // The sweeper must wait for any ongoing iteration to complete
- // before it can unregister an nmethod.
- if (!Thread::current()->is_Code_cache_sweeper_thread()) {
- return;
- }
+void ZNMethodTable::wait_until_iteration_done() {
+ assert(CodeCache_lock->owned_by_self(), "Lock must be held");
- while (_iter_table != NULL) {
- MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- os::naked_short_sleep(1);
+ while (_iteration.in_progress()) {
+ CodeCache_lock->wait(Monitor::_no_safepoint_check_flag);
}
}
void ZNMethodTable::unregister_nmethod(nmethod* nm) {
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
- ResourceMark rm;
-
- sweeper_wait_for_iteration();
-
- log_unregister(nm);
// Remove entry
unregister_entry(_table, _size, nm);
@@ -467,248 +216,29 @@
_nregistered--;
}
-void ZNMethodTable::disarm_nmethod(nmethod* nm) {
- BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
- if (bs != NULL) {
- bs->disarm(nm);
- }
-}
+void ZNMethodTable::nmethods_do_begin() {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-void ZNMethodTable::nmethod_entries_do_begin() {
- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- ZLocker locker(&_iter_lock);
+ // Make sure we don't free data while iterating
+ ZNMethodAllocator::activate_deferred_frees();
// Prepare iteration
- _iter_table = _table;
- _iter_table_size = _size;
- _claimed = 0;
- assert(_iter_deferred_deletes.is_empty(), "Should be emtpy");
-}
-
-void ZNMethodTable::nmethod_entries_do_end() {
- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- ZLocker locker(&_iter_lock);
-
- // Finish iteration
- if (_iter_table != _table) {
- delete [] _iter_table;
- }
- _iter_table = NULL;
- assert(_claimed >= _iter_table_size, "Failed to claim all table entries");
-
- // Process deferred deletes
- ZArrayIterator iter(&_iter_deferred_deletes);
- for (void* data; iter.next(&data);) {
- FREE_C_HEAP_ARRAY(uint8_t, data);
- }
- _iter_deferred_deletes.clear();
-}
-
-void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
- nmethod* const nm = entry.method();
-
- // Process oops table
- oop* const begin = nm->oops_begin();
- oop* const end = nm->oops_end();
- for (oop* p = begin; p < end; p++) {
- if (*p != Universe::non_oop_word()) {
- cl->do_oop(p);
- }
- }
-
- // Process immediate oops
- if (entry.immediate_oops()) {
- const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
- if (nmi != NULL) {
- oop** const begin = nmi->immediate_oops_begin();
- oop** const end = nmi->immediate_oops_end();
- for (oop** p = begin; p < end; p++) {
- if (**p != Universe::non_oop_word()) {
- cl->do_oop(*p);
- }
- }
- }
- }
-
- // Process non-immediate oops
- if (entry.non_immediate_oops()) {
- nmethod* const nm = entry.method();
- nm->fix_oop_relocations();
- }
-}
-
-class ZNMethodTableEntryToOopsDo : public ZNMethodTableEntryClosure {
-private:
- OopClosure* _cl;
-
-public:
- ZNMethodTableEntryToOopsDo(OopClosure* cl) :
- _cl(cl) {}
-
- void do_nmethod_entry(ZNMethodTableEntry entry) {
- ZNMethodTable::entry_oops_do(entry, _cl);
- }
-};
-
-void ZNMethodTable::oops_do(OopClosure* cl) {
- ZNMethodTableEntryToOopsDo entry_cl(cl);
- nmethod_entries_do(&entry_cl);
-}
-
-void ZNMethodTable::nmethod_entries_do(ZNMethodTableEntryClosure* cl) {
- for (;;) {
- // Claim table partition. Each partition is currently sized to span
- // two cache lines. This number is just a guess, but seems to work well.
- const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
- const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size);
- const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size);
- if (partition_start == partition_end) {
- // End of table
- break;
- }
-
- // Process table partition
- for (size_t i = partition_start; i < partition_end; i++) {
- const ZNMethodTableEntry entry = _iter_table[i];
- if (entry.registered()) {
- cl->do_nmethod_entry(entry);
- }
- }
- }
+ _iteration.nmethods_do_begin(_table, _size);
}
-class ZNMethodTableUnlinkClosure : public ZNMethodTableEntryClosure {
-private:
- bool _unloading_occurred;
- volatile bool _failed;
-
- void set_failed() {
- Atomic::store(true, &_failed);
- }
-
-public:
- ZNMethodTableUnlinkClosure(bool unloading_occurred) :
- _unloading_occurred(unloading_occurred),
- _failed(false) {}
-
- virtual void do_nmethod_entry(ZNMethodTableEntry entry) {
- if (failed()) {
- return;
- }
-
- nmethod* const nm = entry.method();
- if (!nm->is_alive()) {
- return;
- }
+void ZNMethodTable::nmethods_do_end() {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- ZLocker locker(ZNMethodTable::lock_for_nmethod(nm));
-
- if (nm->is_unloading()) {
- // Unlinking of the dependencies must happen before the
- // handshake separating unlink and purge.
- nm->flush_dependencies(false /* delete_immediately */);
-
- // We don't need to take the lock when unlinking nmethods from
- // the Method, because it is only concurrently unlinked by
- // the entry barrier, which acquires the per nmethod lock.
- nm->unlink_from_method(false /* acquire_lock */);
- return;
- }
-
- // Heal oops and disarm
- ZNMethodOopClosure cl;
- ZNMethodTable::entry_oops_do(entry, &cl);
- ZNMethodTable::disarm_nmethod(nm);
-
- // Clear compiled ICs and exception caches
- if (!nm->unload_nmethod_caches(_unloading_occurred)) {
- set_failed();
- }
- }
+ // Finish iteration
+ _iteration.nmethods_do_end();
- bool failed() const {
- return Atomic::load(&_failed);
- }
-};
-
-class ZNMethodTableUnlinkTask : public ZTask {
-private:
- ZNMethodTableUnlinkClosure _cl;
- ICRefillVerifier* _verifier;
-
-public:
- ZNMethodTableUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
- ZTask("ZNMethodTableUnlinkTask"),
- _cl(unloading_occurred),
- _verifier(verifier) {
- ZNMethodTable::nmethod_entries_do_begin();
- }
-
- ~ZNMethodTableUnlinkTask() {
- ZNMethodTable::nmethod_entries_do_end();
- }
+ // Process deferred frees
+ ZNMethodAllocator::deactivate_and_process_deferred_frees();
- virtual void work() {
- ICRefillVerifierMark mark(_verifier);
- ZNMethodTable::nmethod_entries_do(&_cl);
- }
-
- bool success() const {
- return !_cl.failed();
- }
-};
-
-void ZNMethodTable::unlink(ZWorkers* workers, bool unloading_occurred) {
- for (;;) {
- ICRefillVerifier verifier;
-
- {
- ZNMethodTableUnlinkTask task(unloading_occurred, &verifier);
- workers->run_concurrent(&task);
- if (task.success()) {
- return;
- }
- }
-
- // Cleaning failed because we ran out of transitional IC stubs,
- // so we have to refill and try again. Refilling requires taking
- // a safepoint, so we temporarily leave the suspendible thread set.
- SuspendibleThreadSetLeaver sts;
- InlineCacheBuffer::refill_ic_stubs();
- }
+ // Notify iteration done
+ CodeCache_lock->notify_all();
}
-class ZNMethodTablePurgeClosure : public ZNMethodTableEntryClosure {
-public:
- virtual void do_nmethod_entry(ZNMethodTableEntry entry) {
- nmethod* const nm = entry.method();
- if (nm->is_alive() && nm->is_unloading()) {
- nm->make_unloaded();
- }
- }
-};
-
-class ZNMethodTablePurgeTask : public ZTask {
-private:
- ZNMethodTablePurgeClosure _cl;
-
-public:
- ZNMethodTablePurgeTask() :
- ZTask("ZNMethodTablePurgeTask"),
- _cl() {
- ZNMethodTable::nmethod_entries_do_begin();
- }
-
- ~ZNMethodTablePurgeTask() {
- ZNMethodTable::nmethod_entries_do_end();
- }
-
- virtual void work() {
- ZNMethodTable::nmethod_entries_do(&_cl);
- }
-};
-
-void ZNMethodTable::purge(ZWorkers* workers) {
- ZNMethodTablePurgeTask task;
- workers->run_concurrent(&task);
+void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
+ _iteration.nmethods_do(cl);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodTable.hpp
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTable.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,66 +24,46 @@
#ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP
#define SHARE_GC_Z_ZNMETHODTABLE_HPP
-#include "gc/z/zArray.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zLock.hpp"
-#include "gc/z/zNMethodTableEntry.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
#include "memory/allocation.hpp"
+class nmethod;
+class NMethodClosure;
+class ZNMethodTableEntry;
class ZWorkers;
-class ZNMethodTableEntryClosure {
-public:
- virtual void do_nmethod_entry(ZNMethodTableEntry entry) = 0;
-};
-
class ZNMethodTable : public AllStatic {
private:
- static ZNMethodTableEntry* _table;
- static size_t _size;
- static ZLock _iter_lock;
- static ZNMethodTableEntry* _iter_table;
- static size_t _iter_table_size;
- static ZArray _iter_deferred_deletes;
- static size_t _nregistered;
- static size_t _nunregistered;
- static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
+ static ZNMethodTableEntry* _table;
+ static size_t _size;
+ static size_t _nregistered;
+ static size_t _nunregistered;
+ static ZNMethodTableIteration _iteration;
- static ZNMethodTableEntry create_entry(nmethod* nm);
+ static ZNMethodTableEntry* create(size_t size);
+ static void destroy(ZNMethodTableEntry* table);
static size_t first_index(const nmethod* nm, size_t size);
static size_t next_index(size_t prev_index, size_t size);
- static void sweeper_wait_for_iteration();
-
- static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry);
+ static bool register_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm);
static void unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm);
static void rebuild(size_t new_size);
static void rebuild_if_needed();
- static void log_register(const nmethod* nm, ZNMethodTableEntry entry);
- static void log_unregister(const nmethod* nm);
-
public:
- static void safe_delete(void* data);
-
static size_t registered_nmethods();
static size_t unregistered_nmethods();
static void register_nmethod(nmethod* nm);
static void unregister_nmethod(nmethod* nm);
- static void disarm_nmethod(nmethod* nm);
- static ZReentrantLock* lock_for_nmethod(nmethod* nm);
-
- static void oops_do(OopClosure* cl);
+ static void wait_until_iteration_done();
- static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl);
-
- static void nmethod_entries_do_begin();
- static void nmethod_entries_do_end();
- static void nmethod_entries_do(ZNMethodTableEntryClosure* cl);
+ static void nmethods_do_begin();
+ static void nmethods_do_end();
+ static void nmethods_do(NMethodClosure* cl);
static void unlink(ZWorkers* workers, bool unloading_occurred);
static void purge(ZWorkers* workers);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodTableEntry.hpp
--- a/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -32,16 +32,16 @@
// --------------------------
//
// 6
-// 3 3 2 1 0
-// +--------------------------------------------------------------------+-+-+-+
-// |11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111|1|1|1|
-// +--------------------------------------------------------------------+-+-+-+
-// | | | |
-// | 2-2 Non-immediate Oops Flag (1-bits) * | |
-// | | |
-// | 1-1 Immediate Oops/Unregistered Flag (1-bits) * |
-// | |
-// | 0-0 Registered Flag (1-bits) *
+// 3 2 1 0
+// +---------------------------------------------------------------------+-+-+
+// |11111111 11111111 11111111 11111111 11111111 11111111 11111111 111111|1|1|
+// +---------------------------------------------------------------------+-+-+
+// | | |
+// | | |
+// | | |
+// | 1-1 Unregistered Flag (1-bits) * |
+// | |
+// | 0-0 Registered Flag (1-bits) *
// |
// * 63-3 NMethod Address (61-bits)
//
@@ -52,22 +52,20 @@
private:
typedef ZBitField field_registered;
typedef ZBitField field_unregistered;
- typedef ZBitField field_immediate_oops;
- typedef ZBitField field_non_immediate_oops;
- typedef ZBitField field_method;
+ typedef ZBitField field_method;
uint64_t _entry;
public:
explicit ZNMethodTableEntry(bool unregistered = false) :
- _entry(field_unregistered::encode(unregistered) |
- field_registered::encode(false)) {}
+ _entry(field_registered::encode(false) |
+ field_unregistered::encode(unregistered) |
+ field_method::encode(NULL)) {}
- ZNMethodTableEntry(nmethod* method, bool non_immediate_oops, bool immediate_oops) :
- _entry(field_method::encode(method) |
- field_non_immediate_oops::encode(non_immediate_oops) |
- field_immediate_oops::encode(immediate_oops) |
- field_registered::encode(true)) {}
+ explicit ZNMethodTableEntry(nmethod* method) :
+ _entry(field_registered::encode(true) |
+ field_unregistered::encode(false) |
+ field_method::encode(method)) {}
bool registered() const {
return field_registered::decode(_entry);
@@ -77,14 +75,6 @@
return field_unregistered::decode(_entry);
}
- bool immediate_oops() const {
- return field_immediate_oops::decode(_entry);
- }
-
- bool non_immediate_oops() const {
- return field_non_immediate_oops::decode(_entry);
- }
-
nmethod* method() const {
return field_method::decode(_entry);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodTableIteration.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableIteration.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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/z/zNMethodTableEntry.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
+#include "memory/iterator.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+ZNMethodTableIteration::ZNMethodTableIteration() :
+ _table(NULL),
+ _size(0),
+ _claimed(0) {}
+
+bool ZNMethodTableIteration::in_progress() const {
+ return _table != NULL;
+}
+
+void ZNMethodTableIteration::nmethods_do_begin(ZNMethodTableEntry* table, size_t size) {
+ assert(!in_progress(), "precondition");
+
+ _table = table;
+ _size = size;
+ _claimed = 0;
+}
+
+void ZNMethodTableIteration::nmethods_do_end() {
+ assert(_claimed >= _size, "Failed to claim all table entries");
+
+ // Finish iteration
+ _table = NULL;
+}
+
+void ZNMethodTableIteration::nmethods_do(NMethodClosure* cl) {
+ for (;;) {
+ // Claim table partition. Each partition is currently sized to span
+ // two cache lines. This number is just a guess, but seems to work well.
+ const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
+ const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
+ const size_t partition_end = MIN2(partition_start + partition_size, _size);
+ if (partition_start == partition_end) {
+ // End of table
+ break;
+ }
+
+ // Process table partition
+ for (size_t i = partition_start; i < partition_end; i++) {
+ const ZNMethodTableEntry entry = _table[i];
+ if (entry.registered()) {
+ cl->do_nmethod(entry.method());
+ }
+ }
+ }
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zNMethodTableIteration.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableIteration.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
+#define SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
+
+#include "gc/z/zGlobals.hpp"
+
+class NMethodClosure;
+class ZNMethodTableEntry;
+
+class ZNMethodTableIteration {
+private:
+ ZNMethodTableEntry* _table;
+ size_t _size;
+ volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
+
+public:
+ ZNMethodTableIteration();
+
+ bool in_progress() const;
+
+ void nmethods_do_begin(ZNMethodTableEntry* table, size_t size);
+ void nmethods_do_end();
+ void nmethods_do(NMethodClosure* cl);
+};
+
+#endif // SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zRelocate.cpp
--- a/src/hotspot/share/gc/z/zRelocate.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zRelocate.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,28 +31,20 @@
#include "gc/z/zRelocationSet.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
#include "gc/z/zTask.hpp"
+#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zWorkers.hpp"
ZRelocate::ZRelocate(ZWorkers* workers) :
_workers(workers) {}
class ZRelocateRootsIteratorClosure : public ZRootsIteratorClosure {
-private:
- static void remap_address(HeapWord** p) {
- *p = (HeapWord*)ZAddress::good_or_null((uintptr_t)*p);
- }
-
public:
virtual void do_thread(Thread* thread) {
- ZRootsIteratorClosure::do_thread(thread);
-
// Update thread local address bad mask
ZThreadLocalData::set_address_bad_mask(thread, ZAddressBadMask);
// Remap TLAB
- if (UseTLAB && thread->is_Java_thread()) {
- thread->tlab().addresses_do(remap_address);
- }
+ ZThreadLocalAllocBuffer::remap(thread);
}
virtual void do_oop(oop* p) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zRootsIterator.cpp
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -33,7 +33,7 @@
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zBarrierSetNMethod.hpp"
#include "gc/z/zGlobals.hpp"
-#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethod.hpp"
#include "gc/z/zOopClosures.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
#include "gc/z/zStat.hpp"
@@ -135,29 +135,38 @@
}
}
-class ZCodeBlobClosure : public CodeBlobToOopClosure {
+class ZRootsIteratorCodeBlobClosure : public CodeBlobToOopClosure {
private:
BarrierSetNMethod* _bs;
public:
- ZCodeBlobClosure(OopClosure* cl) :
+ ZRootsIteratorCodeBlobClosure(OopClosure* cl) :
CodeBlobToOopClosure(cl, true /* fix_relocations */),
_bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {}
virtual void do_code_blob(CodeBlob* cb) {
nmethod* const nm = cb->as_nmethod_or_null();
- if (nm == NULL || nm->test_set_oops_do_mark()) {
- return;
+ if (nm != NULL && !nm->test_set_oops_do_mark()) {
+ CodeBlobToOopClosure::do_code_blob(cb);
+ _bs->disarm(nm);
}
- CodeBlobToOopClosure::do_code_blob(cb);
- _bs->disarm(nm);
}
};
-void ZRootsIteratorClosure::do_thread(Thread* thread) {
- ZCodeBlobClosure code_cl(this);
- thread->oops_do(this, ClassUnloading ? &code_cl : NULL);
-}
+class ZRootsIteratorThreadClosure : public ThreadClosure {
+private:
+ ZRootsIteratorClosure* _cl;
+
+public:
+ ZRootsIteratorThreadClosure(ZRootsIteratorClosure* cl) :
+ _cl(cl) {}
+
+ virtual void do_thread(Thread* thread) {
+ ZRootsIteratorCodeBlobClosure code_cl(_cl);
+ thread->oops_do(_cl, ClassUnloading ? &code_cl : NULL);
+ _cl->do_thread(thread);
+ }
+};
ZRootsIterator::ZRootsIterator() :
_universe(this),
@@ -175,7 +184,7 @@
if (ClassUnloading) {
nmethod::oops_do_marking_prologue();
} else {
- ZNMethodTable::nmethod_entries_do_begin();
+ ZNMethod::oops_do_begin();
}
}
@@ -185,7 +194,7 @@
if (ClassUnloading) {
nmethod::oops_do_marking_epilogue();
} else {
- ZNMethodTable::nmethod_entries_do_end();
+ ZNMethod::oops_do_end();
}
JvmtiExport::gc_epilogue();
@@ -227,12 +236,13 @@
void ZRootsIterator::do_threads(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhasePauseRootsThreads);
ResourceMark rm;
- Threads::possibly_parallel_threads_do(true, cl);
+ ZRootsIteratorThreadClosure thread_cl(cl);
+ Threads::possibly_parallel_threads_do(true, &thread_cl);
}
void ZRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhasePauseRootsCodeCache);
- ZNMethodTable::oops_do(cl);
+ ZNMethod::oops_do(cl);
}
void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_export) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zRootsIterator.hpp
--- a/src/hotspot/share/gc/z/zRootsIterator.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zRootsIterator.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -31,9 +31,9 @@
#include "runtime/thread.hpp"
#include "utilities/globalDefinitions.hpp"
-class ZRootsIteratorClosure : public OopClosure, public ThreadClosure {
+class ZRootsIteratorClosure : public OopClosure {
public:
- virtual void do_thread(Thread* thread);
+ virtual void do_thread(Thread* thread) {}
};
typedef OopStorage::ParState ZOopStorageIterator;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zStatTLAB.cpp
--- a/src/hotspot/share/gc/z/zStatTLAB.cpp Fri Feb 22 17:03:09 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "gc/z/zStatTLAB.hpp"
-
-ZPerWorker* ZStatTLAB::_stats = NULL;
-
-void ZStatTLAB::initialize() {
- if (UseTLAB) {
- assert(_stats == NULL, "Already initialized");
- _stats = new ZPerWorker();
- reset();
- }
-}
-
-void ZStatTLAB::reset() {
- if (UseTLAB) {
- ZPerWorkerIterator iter(_stats);
- for (ThreadLocalAllocStats* stats; iter.next(&stats);) {
- stats->reset();
- }
- }
-}
-
-ThreadLocalAllocStats* ZStatTLAB::get() {
- if (UseTLAB) {
- return _stats->addr();
- }
-
- return NULL;
-}
-
-void ZStatTLAB::publish() {
- if (UseTLAB) {
- ThreadLocalAllocStats total;
-
- ZPerWorkerIterator iter(_stats);
- for (ThreadLocalAllocStats* stats; iter.next(&stats);) {
- total.update(*stats);
- }
-
- total.publish();
- }
-}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zStatTLAB.hpp
--- a/src/hotspot/share/gc/z/zStatTLAB.hpp Fri Feb 22 17:03:09 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZSTATTLAB_HPP
-#define SHARE_GC_Z_ZSTATTLAB_HPP
-
-#include "gc/shared/threadLocalAllocBuffer.hpp"
-#include "gc/z/zValue.hpp"
-#include "memory/allocation.hpp"
-
-class ZStatTLAB : public AllStatic {
-private:
- static ZPerWorker* _stats;
-
-public:
- static void initialize();
- static void reset();
- static ThreadLocalAllocStats* get();
- static void publish();
-};
-
-#endif // SHARE_GC_Z_ZSTATTLAB_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zThreadLocalAllocBuffer.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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/z/zAddress.inline.hpp"
+#include "gc/z/zThreadLocalAllocBuffer.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/thread.hpp"
+
+ZPerWorker* ZThreadLocalAllocBuffer::_stats = NULL;
+
+void ZThreadLocalAllocBuffer::initialize() {
+ if (UseTLAB) {
+ assert(_stats == NULL, "Already initialized");
+ _stats = new ZPerWorker();
+ reset_statistics();
+ }
+}
+
+void ZThreadLocalAllocBuffer::reset_statistics() {
+ if (UseTLAB) {
+ ZPerWorkerIterator iter(_stats);
+ for (ThreadLocalAllocStats* stats; iter.next(&stats);) {
+ stats->reset();
+ }
+ }
+}
+
+void ZThreadLocalAllocBuffer::publish_statistics() {
+ if (UseTLAB) {
+ ThreadLocalAllocStats total;
+
+ ZPerWorkerIterator iter(_stats);
+ for (ThreadLocalAllocStats* stats; iter.next(&stats);) {
+ total.update(*stats);
+ }
+
+ total.publish();
+ }
+}
+
+static void fixup_address(HeapWord** p) {
+ *p = (HeapWord*)ZAddress::good_or_null((uintptr_t)*p);
+}
+
+void ZThreadLocalAllocBuffer::retire(Thread* thread) {
+ if (UseTLAB && thread->is_Java_thread()) {
+ ThreadLocalAllocStats* const stats = _stats->addr();
+ thread->tlab().addresses_do(fixup_address);
+ thread->tlab().retire(stats);
+ thread->tlab().resize();
+ }
+}
+
+void ZThreadLocalAllocBuffer::remap(Thread* thread) {
+ if (UseTLAB && thread->is_Java_thread()) {
+ thread->tlab().addresses_do(fixup_address);
+ }
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zThreadLocalAllocBuffer.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_GC_Z_ZTHREADLOCALALLOCBUFFER_HPP
+#define SHARE_GC_Z_ZTHREADLOCALALLOCBUFFER_HPP
+
+#include "gc/shared/threadLocalAllocBuffer.hpp"
+#include "gc/z/zValue.hpp"
+#include "memory/allocation.hpp"
+
+class ZThreadLocalAllocBuffer : public AllStatic {
+private:
+ static ZPerWorker* _stats;
+
+public:
+ static void initialize();
+
+ static void reset_statistics();
+ static void publish_statistics();
+
+ static void retire(Thread* thread);
+ static void remap(Thread* thread);
+};
+
+#endif // SHARE_GC_Z_ZTHREADLOCALALLOCBUFFER_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/gc/z/zUnload.cpp
--- a/src/hotspot/share/gc/z/zUnload.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/gc/z/zUnload.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -30,7 +30,7 @@
#include "gc/shared/gcBehaviours.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zLock.inline.hpp"
-#include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethod.hpp"
#include "gc/z/zOopClosures.hpp"
#include "gc/z/zStat.hpp"
#include "gc/z/zUnload.hpp"
@@ -75,7 +75,7 @@
public:
virtual bool is_unloading(CompiledMethod* method) const {
nmethod* const nm = method->as_nmethod();
- ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm);
+ ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
if (lock == NULL) {
return is_unloading(nm);
} else {
@@ -89,7 +89,7 @@
public:
virtual bool lock(CompiledMethod* method) {
nmethod* const nm = method->as_nmethod();
- ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm);
+ ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
if (lock != NULL) {
lock->lock();
}
@@ -98,7 +98,7 @@
virtual void unlock(CompiledMethod* method) {
nmethod* const nm = method->as_nmethod();
- ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm);
+ ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
if (lock != NULL) {
lock->unlock();
}
@@ -110,7 +110,7 @@
}
nmethod* const nm = method->as_nmethod();
- ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm);
+ ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
return lock == NULL || lock->is_owned();
}
};
@@ -149,7 +149,7 @@
Klass::clean_weak_klass_links(unloading_occurred);
- ZNMethodTable::unlink(_workers, unloading_occurred);
+ ZNMethod::unlink(_workers, unloading_occurred);
DependencyContext::cleaning_end();
}
@@ -157,7 +157,7 @@
void ZUnload::purge() {
{
SuspendibleThreadSetJoiner sts;
- ZNMethodTable::purge(_workers);
+ ZNMethod::purge(_workers);
}
ClassLoaderDataGraph::purge();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/interpreter/linkResolver.cpp
--- a/src/hotspot/share/interpreter/linkResolver.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -39,6 +39,7 @@
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
+#include "oops/constantPool.hpp"
#include "oops/cpCache.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/interpreter/rewriter.cpp
--- a/src/hotspot/share/interpreter/rewriter.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/interpreter/rewriter.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -28,6 +28,7 @@
#include "interpreter/rewriter.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/constantPool.hpp"
#include "oops/generateOopMap.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -43,6 +43,7 @@
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/array.hpp"
+#include "oops/constantPool.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/jni/jfrJniMethod.cpp
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -114,7 +114,7 @@
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong threshold))
- JfrChunkRotation::set_threshold((intptr_t)threshold);
+ JfrChunkRotation::set_threshold(threshold);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads))
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/metadata/metadata.xml
--- a/src/hotspot/share/jfr/metadata/metadata.xml Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/metadata/metadata.xml Fri Feb 22 20:36:42 2019 +0000
@@ -533,12 +533,6 @@
-
-
-
-
-
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -44,13 +44,13 @@
}
}
-static void write_checkpoint_header(u1* pos, jlong size, jlong time, bool flushpoint, juint type_count) {
+static void write_checkpoint_header(u1* pos, int64_t size, jlong time, bool flushpoint, u4 type_count) {
assert(pos != NULL, "invariant");
JfrBigEndianWriter be_writer(pos, sizeof(JfrCheckpointEntry));
be_writer.write(size);
be_writer.write(time);
be_writer.write(JfrTicks::now().value() - time);
- be_writer.write(flushpoint ? (juint)1 : (juint)0);
+ be_writer.write(flushpoint ? (u4)1 : (u4)0);
be_writer.write(type_count);
assert(be_writer.is_valid(), "invariant");
}
@@ -71,7 +71,7 @@
assert(this->is_valid(), "invariant");
assert(count() > 0, "invariant");
assert(this->used_size() > sizeof(JfrCheckpointEntry), "invariant");
- const jlong size = this->current_offset();
+ const int64_t size = this->current_offset();
assert(size + this->start_pos() == this->current_pos(), "invariant");
write_checkpoint_header(const_cast(this->start_pos()), size, _time, is_flushpoint(), count());
release();
@@ -85,11 +85,11 @@
return _flushpoint;
}
-juint JfrCheckpointWriter::count() const {
+u4 JfrCheckpointWriter::count() const {
return _count;
}
-void JfrCheckpointWriter::set_count(juint count) {
+void JfrCheckpointWriter::set_count(u4 count) {
_count = count;
}
@@ -111,7 +111,7 @@
}
void JfrCheckpointWriter::write_key(u8 key) {
- write(key);
+ write(key);
}
void JfrCheckpointWriter::increment() {
@@ -119,10 +119,10 @@
}
void JfrCheckpointWriter::write_count(u4 nof_entries) {
- write((u4)nof_entries);
+ write(nof_entries);
}
-void JfrCheckpointWriter::write_count(u4 nof_entries, jlong offset) {
+void JfrCheckpointWriter::write_count(u4 nof_entries, int64_t offset) {
write_padded_at_offset(nof_entries, offset);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -49,21 +49,21 @@
typedef EventWriterHost JfrCheckpointWriterBase;
struct JfrCheckpointContext {
- jlong offset;
- juint count;
+ int64_t offset;
+ u4 count;
};
class JfrCheckpointWriter : public JfrCheckpointWriterBase {
friend class JfrSerializerRegistration;
private:
JfrTicks _time;
- jlong _offset;
- juint _count;
+ int64_t _offset;
+ u4 _count;
bool _flushpoint;
bool _header;
- juint count() const;
- void set_count(juint count);
+ u4 count() const;
+ void set_count(u4 count);
void increment();
void set_flushpoint(bool flushpoint);
bool is_flushpoint() const;
@@ -75,7 +75,7 @@
~JfrCheckpointWriter();
void write_type(JfrTypeId type_id);
void write_count(u4 nof_entries);
- void write_count(u4 nof_entries, jlong offset);
+ void write_count(u4 nof_entries, int64_t offset);
void write_key(u8 key);
const JfrCheckpointContext context() const;
void set_context(const JfrCheckpointContext ctx);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -65,7 +65,7 @@
private:
JfrCheckpointWriter& _writer;
JfrCheckpointContext _ctx;
- const intptr_t _count_position;
+ const int64_t _count_position;
Thread* const _curthread;
u4 _count;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -35,7 +35,7 @@
WriterImpl _impl;
JfrCheckpointWriter* _writer;
JfrCheckpointContext _ctx;
- jlong _count_offset;
+ int64_t _count_offset;
int _count;
bool _skip_header;
public:
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -29,7 +29,7 @@
#include "runtime/handles.inline.hpp"
static jobject chunk_monitor = NULL;
-static intptr_t threshold = 0;
+static int64_t threshold = 0;
static bool rotate = false;
static jobject install_chunk_monitor(Thread* thread) {
@@ -62,7 +62,6 @@
// already in progress
return;
}
- assert(!rotate, "invariant");
if (writer.size_written() > threshold) {
rotate = true;
notify();
@@ -77,6 +76,6 @@
rotate = false;
}
-void JfrChunkRotation::set_threshold(intptr_t bytes) {
+void JfrChunkRotation::set_threshold(int64_t bytes) {
threshold = bytes;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -36,7 +36,7 @@
class JfrChunkRotation : AllStatic {
public:
static void evaluate(const JfrChunkWriter& writer);
- static void set_threshold(intptr_t bytes);
+ static void set_threshold(int64_t bytes);
static bool should_rotate();
static void on_rotation();
};
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -53,19 +53,19 @@
set_previous_checkpoint_offset(0);
}
-void JfrChunkState::set_previous_checkpoint_offset(jlong offset) {
+void JfrChunkState::set_previous_checkpoint_offset(int64_t offset) {
_previous_checkpoint_offset = offset;
}
-jlong JfrChunkState::previous_checkpoint_offset() const {
+int64_t JfrChunkState::previous_checkpoint_offset() const {
return _previous_checkpoint_offset;
}
-jlong JfrChunkState::previous_start_ticks() const {
+int64_t JfrChunkState::previous_start_ticks() const {
return _previous_start_ticks;
}
-jlong JfrChunkState::previous_start_nanos() const {
+int64_t JfrChunkState::previous_start_nanos() const {
return _previous_start_nanos;
}
@@ -92,7 +92,7 @@
save_current_and_update_start_ticks();
}
-jlong JfrChunkState::last_chunk_duration() const {
+int64_t JfrChunkState::last_chunk_duration() const {
return _start_nanos - _previous_start_nanos;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -25,7 +25,6 @@
#ifndef SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKSTATE_HPP
#define SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKSTATE_HPP
-#include "jni.h"
#include "jfr/utilities/jfrAllocation.hpp"
#include "jfr/utilities/jfrTypes.hpp"
@@ -33,11 +32,11 @@
friend class JfrChunkWriter;
private:
char* _path;
- jlong _start_ticks;
- jlong _start_nanos;
- jlong _previous_start_ticks;
- jlong _previous_start_nanos;
- jlong _previous_checkpoint_offset;
+ int64_t _start_ticks;
+ int64_t _start_nanos;
+ int64_t _previous_start_ticks;
+ int64_t _previous_start_nanos;
+ int64_t _previous_checkpoint_offset;
void update_start_ticks();
void update_start_nanos();
@@ -47,11 +46,11 @@
JfrChunkState();
~JfrChunkState();
void reset();
- jlong previous_checkpoint_offset() const;
- void set_previous_checkpoint_offset(jlong offset);
- jlong previous_start_ticks() const;
- jlong previous_start_nanos() const;
- jlong last_chunk_duration() const;
+ int64_t previous_checkpoint_offset() const;
+ void set_previous_checkpoint_offset(int64_t offset);
+ int64_t previous_start_ticks() const;
+ int64_t previous_start_nanos() const;
+ int64_t last_chunk_duration() const;
void update_time_to_now();
void set_path(const char* path);
const char* path() const;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -32,9 +32,8 @@
#include "runtime/os.hpp"
#include "runtime/os.inline.hpp"
-const u2 JFR_VERSION_MAJOR = 2;
-const u2 JFR_VERSION_MINOR = 0;
-
+static const u2 JFR_VERSION_MAJOR = 2;
+static const u2 JFR_VERSION_MINOR = 0;
static const size_t MAGIC_LEN = 4;
static const size_t FILEHEADER_SLOT_SIZE = 8;
static const size_t CHUNK_SIZE_OFFSET = 8;
@@ -79,14 +78,14 @@
return is_open;
}
-size_t JfrChunkWriter::close(intptr_t metadata_offset) {
+size_t JfrChunkWriter::close(int64_t metadata_offset) {
write_header(metadata_offset);
this->flush();
this->close_fd();
- return size_written();
+ return (size_t)size_written();
}
-void JfrChunkWriter::write_header(intptr_t metadata_offset) {
+void JfrChunkWriter::write_header(int64_t metadata_offset) {
assert(this->is_valid(), "invariant");
// Chunk size
this->write_be_at_offset(size_written(), CHUNK_SIZE_OFFSET);
@@ -106,15 +105,15 @@
_chunkstate->set_path(chunk_path);
}
-intptr_t JfrChunkWriter::size_written() const {
+int64_t JfrChunkWriter::size_written() const {
return this->is_valid() ? this->current_offset() : 0;
}
-intptr_t JfrChunkWriter::previous_checkpoint_offset() const {
+int64_t JfrChunkWriter::previous_checkpoint_offset() const {
return _chunkstate->previous_checkpoint_offset();
}
-void JfrChunkWriter::set_previous_checkpoint_offset(intptr_t offset) {
+void JfrChunkWriter::set_previous_checkpoint_offset(int64_t offset) {
_chunkstate->set_previous_checkpoint_offset(offset);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -41,16 +41,16 @@
JfrChunkState* _chunkstate;
bool open();
- size_t close(intptr_t metadata_offset);
- void write_header(intptr_t metadata_offset);
+ size_t close(int64_t metadata_offset);
+ void write_header(int64_t metadata_offset);
void set_chunk_path(const char* chunk_path);
public:
JfrChunkWriter();
bool initialize();
- intptr_t size_written() const;
- intptr_t previous_checkpoint_offset() const;
- void set_previous_checkpoint_offset(intptr_t offset);
+ int64_t size_written() const;
+ int64_t previous_checkpoint_offset() const;
+ void set_previous_checkpoint_offset(int64_t offset);
void time_stamp_chunk_now();
};
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -147,10 +147,10 @@
iso8601_to_date_time(buffer);
}
-static jlong file_size(fio_fd fd) {
+static int64_t file_size(fio_fd fd) {
assert(fd != invalid_fd, "invariant");
- const jlong current_offset = os::current_file_offset(fd);
- const jlong size = os::lseek(fd, 0, SEEK_END);
+ const int64_t current_offset = os::current_file_offset(fd);
+ const int64_t size = os::lseek(fd, 0, SEEK_END);
os::seek_to_file_offset(fd, current_offset);
return size;
}
@@ -218,7 +218,7 @@
if (invalid_fd == entry_fd) {
return NULL;
}
- const jlong entry_size = file_size(entry_fd);
+ const int64_t entry_size = file_size(entry_fd);
os::close(entry_fd);
if (0 == entry_size) {
return NULL;
@@ -260,6 +260,7 @@
}
}
#endif
+
bool RepositoryIterator::has_next() const {
return (_files != NULL && _iterator < _files->length());
}
@@ -275,21 +276,27 @@
if (file_copy_block == NULL) {
return;
}
- jlong bytes_written_total = 0;
+ int64_t bytes_written_total = 0;
while (iterator.has_next()) {
fio_fd current_fd = invalid_fd;
const char* const fqn = iterator.next();
if (fqn != NULL) {
current_fd = open_existing(fqn);
if (current_fd != invalid_fd) {
- const jlong current_filesize = file_size(current_fd);
+ const int64_t current_filesize = file_size(current_fd);
assert(current_filesize > 0, "invariant");
- jlong bytes_read = 0;
- jlong bytes_written = 0;
+ int64_t bytes_read = 0;
+ int64_t bytes_written = 0;
while (bytes_read < current_filesize) {
- bytes_read += (jlong)os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
- assert(bytes_read - bytes_written <= (jlong)size_of_file_copy_block, "invariant");
- bytes_written += (jlong)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
+ const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
+ if (-1 == read_result) {
+ log_info(jfr) ( // For user, should not be "jfr, system"
+ "Unable to recover JFR data");
+ break;
+ }
+ bytes_read += (int64_t)read_result;
+ assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
+ bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
assert(bytes_read == bytes_written, "invariant");
}
os::close(current_fd);
@@ -468,6 +475,6 @@
return _chunkwriter->open();
}
-size_t JfrRepository::close_chunk(jlong metadata_offset) {
+size_t JfrRepository::close_chunk(int64_t metadata_offset) {
return _chunkwriter->close(metadata_offset);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -55,7 +55,7 @@
bool set_path(const char* path);
void set_chunk_path(const char* path);
bool open_chunk(bool vm_error = false);
- size_t close_chunk(jlong metadata_offset);
+ size_t close_chunk(int64_t metadata_offset);
void on_vm_error();
static void notify_on_new_chunk_path();
static JfrChunkWriter& chunkwriter();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -130,18 +130,18 @@
bool not_acquired() const { return !_acquired; }
};
-static intptr_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
- const intptr_t prev_cp_offset = cw.previous_checkpoint_offset();
- const intptr_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
+static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
+ const int64_t prev_cp_offset = cw.previous_checkpoint_offset();
+ const int64_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
cw.reserve(sizeof(u4));
cw.write(EVENT_CHECKPOINT);
cw.write(JfrTicks::now());
- cw.write((jlong)0);
+ cw.write((int64_t)0);
cw.write(prev_cp_relative_offset); // write previous checkpoint offset delta
cw.write(false); // flushpoint
- cw.write((u4)1); // nof types in this checkpoint
- cw.write(type_id);
- const intptr_t number_of_elements_offset = cw.current_offset();
+ cw.write((u4)1); // nof types in this checkpoint
+ cw.write(type_id);
+ const int64_t number_of_elements_offset = cw.current_offset();
cw.reserve(sizeof(u4));
return number_of_elements_offset;
}
@@ -161,8 +161,8 @@
}
bool process() {
// current_cp_offset is also offset for the event size header field
- const intptr_t current_cp_offset = _cw.current_offset();
- const intptr_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id);
+ const int64_t current_cp_offset = _cw.current_offset();
+ const int64_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id);
// invocation
_content_functor.process();
const u4 number_of_elements = (u4)_content_functor.processed();
@@ -468,9 +468,9 @@
JfrMetadataEvent::lock();
}
-static jlong write_metadata_event(JfrChunkWriter& chunkwriter) {
+static int64_t write_metadata_event(JfrChunkWriter& chunkwriter) {
assert(chunkwriter.is_valid(), "invariant");
- const jlong metadata_offset = chunkwriter.current_offset();
+ const int64_t metadata_offset = chunkwriter.current_offset();
JfrMetadataEvent::write(chunkwriter, metadata_offset);
return metadata_offset;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrEventWriterHost.inline.hpp
--- a/src/hotspot/share/jfr/writers/jfrEventWriterHost.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrEventWriterHost.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -49,7 +49,7 @@
inline intptr_t EventWriterHost::end_write(void) {
assert(this->is_acquired(),
"state corruption, calling end with writer with non-acquired state!");
- return this->is_valid() ? this->used_offset() : 0;
+ return this->is_valid() ? (intptr_t)this->used_offset() : 0;
}
template
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrPosition.hpp
--- a/src/hotspot/share/jfr/writers/jfrPosition.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrPosition.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -48,8 +48,8 @@
public:
size_t available_size() const;
- intptr_t used_offset() const;
- intptr_t current_offset() const;
+ int64_t used_offset() const;
+ int64_t current_offset() const;
size_t used_size() const;
void reset();
};
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrPosition.inline.hpp
--- a/src/hotspot/share/jfr/writers/jfrPosition.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrPosition.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -80,12 +80,12 @@
}
template
-inline intptr_t Position::used_offset() const {
+inline int64_t Position::used_offset() const {
return _current_pos - _start_pos;
}
template
-inline intptr_t Position::current_offset() const {
+inline int64_t Position::current_offset() const {
return this->used_offset();
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp
--- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -33,9 +33,9 @@
public:
typedef typename Adapter::StorageType StorageType;
private:
- intptr_t _stream_pos;
+ int64_t _stream_pos;
fio_fd _fd;
- intptr_t current_stream_position() const;
+ int64_t current_stream_position() const;
protected:
StreamWriterHost(StorageType* storage, Thread* thread);
@@ -47,8 +47,8 @@
bool has_valid_fd() const;
public:
- intptr_t current_offset() const;
- void seek(intptr_t offset);
+ int64_t current_offset() const;
+ void seek(int64_t offset);
void flush();
void write_unbuffered(const void* src, size_t len);
bool is_valid() const;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp
--- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -44,7 +44,7 @@
}
template
-inline intptr_t StreamWriterHost::current_stream_position() const {
+inline int64_t StreamWriterHost::current_stream_position() const {
return this->used_offset() + _stream_pos;
}
@@ -73,7 +73,7 @@
inline void StreamWriterHost::flush(size_t size) {
assert(size > 0, "invariant");
assert(this->is_valid(), "invariant");
- _stream_pos += os::write(_fd, this->start_pos(), (int)size);
+ _stream_pos += os::write(_fd, this->start_pos(), (unsigned int)size);
StorageHost::reset();
assert(0 == this->used_offset(), "invariant");
}
@@ -84,12 +84,12 @@
}
template
-inline intptr_t StreamWriterHost::current_offset() const {
+inline int64_t StreamWriterHost::current_offset() const {
return current_stream_position();
}
template
-void StreamWriterHost::seek(intptr_t offset) {
+void StreamWriterHost::seek(int64_t offset) {
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
_stream_pos = os::seek_to_file_offset(_fd, offset);
@@ -110,7 +110,7 @@
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
while (len > 0) {
- const int n = MIN2((int)len, INT_MAX);
+ const unsigned int n = MIN2((unsigned int)len, (unsigned int)INT_MAX);
_stream_pos += os::write(_fd, buf, n);
len -= n;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrWriterHost.hpp
--- a/src/hotspot/share/jfr/writers/jfrWriterHost.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrWriterHost.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -91,12 +91,12 @@
void bytes(const void* buf, size_t len);
void write_utf8_u2_len(const char* value);
template
- void write_padded_at_offset(T value, intptr_t offset);
+ void write_padded_at_offset(T value, int64_t offset);
template
- void write_at_offset(T value, intptr_t offset);
+ void write_at_offset(T value, int64_t offset);
template
- void write_be_at_offset(T value, intptr_t offset);
- intptr_t reserve(size_t size);
+ void write_be_at_offset(T value, int64_t offset);
+ int64_t reserve(size_t size);
};
#endif // SHARE_JFR_WRITERS_JFRWRITERHOST_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp
--- a/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -196,7 +196,7 @@
template
inline void WriterHost::write(double value) {
- be_write(*(uintptr_t*)&(value));
+ be_write(*(u8*)&(value));
}
template
@@ -317,9 +317,9 @@
}
template
-inline intptr_t WriterHost::reserve(size_t size) {
+inline int64_t WriterHost::reserve(size_t size) {
if (ensure_size(size) != NULL) {
- intptr_t reserved_offset = this->current_offset();
+ const int64_t reserved_offset = this->current_offset();
this->set_current_pos(size);
return reserved_offset;
}
@@ -329,9 +329,9 @@
template
template
-inline void WriterHost::write_padded_at_offset(T value, intptr_t offset) {
+inline void WriterHost::write_padded_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
- const intptr_t current = this->current_offset();
+ const int64_t current = this->current_offset();
this->seek(offset);
write_padded(value);
this->seek(current); // restore
@@ -340,9 +340,9 @@
template
template
-inline void WriterHost::write_at_offset(T value, intptr_t offset) {
+inline void WriterHost::write_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
- const intptr_t current = this->current_offset();
+ const int64_t current = this->current_offset();
this->seek(offset);
write(value);
this->seek(current); // restore
@@ -351,9 +351,9 @@
template
template
-inline void WriterHost::write_be_at_offset(T value, intptr_t offset) {
+inline void WriterHost::write_be_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
- const intptr_t current = this->current_offset();
+ const int64_t current = this->current_offset();
this->seek(offset);
be_write(value);
this->seek(current); // restore
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/logging/logFileOutput.cpp
--- a/src/hotspot/share/logging/logFileOutput.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/logging/logFileOutput.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -51,6 +51,14 @@
_file_name = make_file_name(name + strlen(Prefix), _pid_str, _vm_start_time_str);
}
+const char* LogFileOutput::cur_log_file_name() {
+ if (strlen(_archive_name) == 0) {
+ return _file_name;
+ } else {
+ return _archive_name;
+ }
+}
+
void LogFileOutput::set_file_name_parameters(jlong vm_start_time) {
int res = jio_snprintf(_pid_str, sizeof(_pid_str), "%d", os::current_process_id());
assert(res > 0, "PID buffer too small");
@@ -234,6 +242,7 @@
_file_count_max_digits = number_of_digits(_file_count - 1);
_archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits;
_archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging);
+ _archive_name[0] = 0;
}
log_trace(logging)("Initializing logging to file '%s' (filecount: %u"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/logging/logFileOutput.hpp
--- a/src/hotspot/share/logging/logFileOutput.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/logging/logFileOutput.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -92,6 +92,7 @@
return _name;
}
+ const char* cur_log_file_name();
static const char* const Prefix;
static void set_file_name_parameters(jlong start_time);
};
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/allocation.hpp
--- a/src/hotspot/share/memory/allocation.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/allocation.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -132,6 +132,7 @@
f(mtArguments, "Arguments") \
f(mtModule, "Module") \
f(mtSafepoint, "Safepoint") \
+ f(mtSynchronizer, "Synchronization") \
f(mtNone, "Unknown") \
//end
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/filemap.cpp
--- a/src/hotspot/share/memory/filemap.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/filemap.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
+#include "runtime/mutexLocker.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/vm_version.hpp"
#include "services/memTracker.hpp"
@@ -501,6 +502,16 @@
}
_validating_shared_path_table = false;
+
+#if INCLUDE_JVMTI
+ if (_classpath_entries_for_jvmti != NULL) {
+ os::free(_classpath_entries_for_jvmti);
+ }
+ size_t sz = sizeof(ClassPathEntry*) * _shared_path_table_size;
+ _classpath_entries_for_jvmti = (ClassPathEntry**)os::malloc(sz, mtClass);
+ memset(_classpath_entries_for_jvmti, 0, sz);
+#endif
+
return true;
}
@@ -1440,3 +1451,57 @@
fail_stop("%s", msg);
}
}
+
+#if INCLUDE_JVMTI
+ClassPathEntry** FileMapInfo::_classpath_entries_for_jvmti = NULL;
+
+ClassPathEntry* FileMapInfo::get_classpath_entry_for_jvmti(int i, TRAPS) {
+ ClassPathEntry* ent = _classpath_entries_for_jvmti[i];
+ if (ent == NULL) {
+ if (i == 0) {
+ ent = ClassLoader:: get_jrt_entry();
+ assert(ent != NULL, "must be");
+ } else {
+ SharedClassPathEntry* scpe = shared_path(i);
+ assert(scpe->is_jar(), "must be"); // other types of scpe will not produce archived classes
+
+ const char* path = scpe->name();
+ struct stat st;
+ if (os::stat(path, &st) != 0) {
+ char *msg = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(path) + 128); ;
+ jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
+ THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL);
+ } else {
+ ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, CHECK_NULL);
+ }
+ }
+
+ MutexLocker mu(CDSClassFileStream_lock, THREAD);
+ if (_classpath_entries_for_jvmti[i] == NULL) {
+ _classpath_entries_for_jvmti[i] = ent;
+ } else {
+ // Another thread has beat me to creating this entry
+ delete ent;
+ ent = _classpath_entries_for_jvmti[i];
+ }
+ }
+
+ return ent;
+}
+
+ClassFileStream* FileMapInfo::open_stream_for_jvmti(InstanceKlass* ik, TRAPS) {
+ int path_index = ik->shared_classpath_index();
+ assert(path_index >= 0, "should be called for shared built-in classes only");
+ assert(path_index < (int)_shared_path_table_size, "sanity");
+
+ ClassPathEntry* cpe = get_classpath_entry_for_jvmti(path_index, CHECK_NULL);
+ assert(cpe != NULL, "must be");
+
+ Symbol* name = ik->name();
+ const char* const class_name = name->as_C_string();
+ const char* const file_name = ClassLoader::file_name_for_class_name(class_name,
+ name->utf8_length());
+ return cpe->open_stream(file_name, THREAD);
+}
+
+#endif
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/filemap.hpp
--- a/src/hotspot/share/memory/filemap.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/filemap.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -302,6 +302,10 @@
bool validate_shared_path_table();
static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
+#if INCLUDE_JVMTI
+ static ClassFileStream* open_stream_for_jvmti(InstanceKlass* ik, TRAPS);
+#endif
+
static SharedClassPathEntry* shared_path(int index) {
if (index < 0) {
return NULL;
@@ -348,6 +352,11 @@
}
address decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode);
+
+#if INCLUDE_JVMTI
+ static ClassPathEntry** _classpath_entries_for_jvmti;
+ static ClassPathEntry* get_classpath_entry_for_jvmti(int i, TRAPS);
+#endif
};
#endif // SHARE_MEMORY_FILEMAP_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/iterator.hpp
--- a/src/hotspot/share/memory/iterator.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/iterator.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -263,6 +263,11 @@
virtual void do_code_blob(CodeBlob* cb);
};
+class NMethodClosure : public Closure {
+ public:
+ virtual void do_nmethod(nmethod* n) = 0;
+};
+
// MonitorClosure is used for iterating over monitors in the monitors cache
class ObjectMonitor;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/memRegion.hpp
--- a/src/hotspot/share/memory/memRegion.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/memRegion.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -40,8 +40,6 @@
// create MemRegions (in CardTableBarrierSet) in heap so operator
// new and operator new [] added for this special case.
-class MetaWord;
-
class MemRegion {
friend class VMStructs;
private:
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/metaspace.hpp
--- a/src/hotspot/share/memory/metaspace.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/metaspace.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -57,7 +57,6 @@
class ClassLoaderData;
class MetaspaceTracer;
-class MetaWord;
class Mutex;
class outputStream;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/metaspaceShared.cpp
--- a/src/hotspot/share/memory/metaspaceShared.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -207,7 +207,7 @@
};
-DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md"), _od_region("od");
+DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md");
size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0;
char* MetaspaceShared::misc_code_space_alloc(size_t num_bytes) {
@@ -598,23 +598,6 @@
}
}
-static void relocate_cached_class_file() {
- for (int i = 0; i < _global_klass_objects->length(); i++) {
- Klass* k = _global_klass_objects->at(i);
- if (k->is_instance_klass()) {
- InstanceKlass* ik = InstanceKlass::cast(k);
- JvmtiCachedClassFileData* p = ik->get_archived_class_data();
- if (p != NULL) {
- int size = offset_of(JvmtiCachedClassFileData, data) + p->length;
- JvmtiCachedClassFileData* q = (JvmtiCachedClassFileData*)_od_region.allocate(size);
- q->length = p->length;
- memcpy(q->data, p->data, p->length);
- ik->set_archived_class_data(q);
- }
- }
- }
-}
-
// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables.
// (In GCC this is the field ::_vptr, i.e., first word in the object.)
//
@@ -1438,15 +1421,11 @@
char* vtbl_list = _md_region.top();
MetaspaceShared::allocate_cpp_vtable_clones();
- _md_region.pack(&_od_region);
+ _md_region.pack();
- // Relocate the archived class file data into the od region
- relocate_cached_class_file();
- _od_region.pack();
-
- // The 5 core spaces are allocated consecutively mc->rw->ro->md->od, so there total size
+ // The 4 core spaces are allocated consecutively mc->rw->ro->md, so there total size
// is just the spaces between the two ends.
- size_t core_spaces_size = _od_region.end() - _mc_region.base();
+ size_t core_spaces_size = _md_region.end() - _mc_region.base();
assert(core_spaces_size == (size_t)align_up(core_spaces_size, Metaspace::reserve_alignment()),
"should already be aligned");
@@ -1488,7 +1467,6 @@
write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::md, &_md_region, /*read_only=*/false,/*allow_exec=*/false);
- write_region(mapinfo, MetaspaceShared::od, &_od_region, /*read_only=*/true, /*allow_exec=*/false);
_total_closed_archive_region_size = mapinfo->write_archive_heap_regions(
_closed_archive_heap_regions,
@@ -1535,12 +1513,10 @@
// Print statistics of all the regions
const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
_mc_region.reserved() + _md_region.reserved() +
- _od_region.reserved() +
_total_closed_archive_region_size +
_total_open_archive_region_size;
const size_t total_bytes = _ro_region.used() + _rw_region.used() +
_mc_region.used() + _md_region.used() +
- _od_region.used() +
_total_closed_archive_region_size +
_total_open_archive_region_size;
const double total_u_perc = percent_of(total_bytes, total_reserved);
@@ -1549,7 +1525,6 @@
_rw_region.print(total_reserved);
_ro_region.print(total_reserved);
_md_region.print(total_reserved);
- _od_region.print(total_reserved);
print_heap_region_stats(_closed_archive_heap_regions, "ca", total_reserved);
print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved);
@@ -1931,33 +1906,30 @@
char* rw_base = NULL; char* rw_top;
char* mc_base = NULL; char* mc_top;
char* md_base = NULL; char* md_top;
- char* od_base = NULL; char* od_top;
// Map each shared region
if ((mc_base = mapinfo->map_region(mc, &mc_top)) != NULL &&
(rw_base = mapinfo->map_region(rw, &rw_top)) != NULL &&
(ro_base = mapinfo->map_region(ro, &ro_top)) != NULL &&
(md_base = mapinfo->map_region(md, &md_top)) != NULL &&
- (od_base = mapinfo->map_region(od, &od_top)) != NULL &&
(image_alignment == (size_t)os::vm_allocation_granularity()) &&
mapinfo->validate_shared_path_table()) {
// Success -- set up MetaspaceObj::_shared_metaspace_{base,top} for
// fast checking in MetaspaceShared::is_in_shared_metaspace() and
// MetaspaceObj::is_shared().
//
- // We require that mc->rw->ro->md->od to be laid out consecutively, with no
+ // We require that mc->rw->ro->md to be laid out consecutively, with no
// gaps between them. That way, we can ensure that the OS won't be able to
// allocate any new memory spaces inside _shared_metaspace_{base,top}, which
// would mess up the simple comparision in MetaspaceShared::is_in_shared_metaspace().
- assert(mc_base < ro_base && mc_base < rw_base && mc_base < md_base && mc_base < od_base, "must be");
- assert(od_top > ro_top && od_top > rw_top && od_top > md_top && od_top > mc_top , "must be");
+ assert(mc_base < ro_base && mc_base < rw_base && mc_base < md_base, "must be");
+ assert(md_top > ro_top && md_top > rw_top && md_top > mc_top , "must be");
assert(mc_top == rw_base, "must be");
assert(rw_top == ro_base, "must be");
assert(ro_top == md_base, "must be");
- assert(md_top == od_base, "must be");
_core_spaces_size = mapinfo->core_spaces_size();
- MetaspaceObj::set_shared_metaspace_range((void*)mc_base, (void*)od_top);
+ MetaspaceObj::set_shared_metaspace_range((void*)mc_base, (void*)md_top);
return true;
} else {
// If there was a failure in mapping any of the spaces, unmap the ones
@@ -1966,7 +1938,6 @@
if (rw_base != NULL) mapinfo->unmap_region(rw);
if (mc_base != NULL) mapinfo->unmap_region(mc);
if (md_base != NULL) mapinfo->unmap_region(md);
- if (od_base != NULL) mapinfo->unmap_region(od);
#ifndef _WINDOWS
// Release the entire mapped region
shared_rs.release();
@@ -2049,7 +2020,6 @@
_rw_region.print_out_of_space_msg(name, needed_bytes);
_ro_region.print_out_of_space_msg(name, needed_bytes);
_md_region.print_out_of_space_msg(name, needed_bytes);
- _od_region.print_out_of_space_msg(name, needed_bytes);
vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name),
"Please reduce the number of shared classes.");
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/memory/metaspaceShared.hpp
--- a/src/hotspot/share/memory/metaspaceShared.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/memory/metaspaceShared.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -69,14 +69,10 @@
ro = 2, // read-only shared space in the heap
md = 3, // miscellaneous data for initializing tables, etc.
num_core_spaces = 4, // number of non-string regions
-
- // optional mapped spaces
- // Currently it only contains class file data.
- od = num_core_spaces,
- num_non_heap_spaces = od + 1,
+ num_non_heap_spaces = 4,
// mapped java heap regions
- first_closed_archive_heap_region = od + 1,
+ first_closed_archive_heap_region = md + 1,
max_closed_archive_heap_region = 2,
last_closed_archive_heap_region = first_closed_archive_heap_region + max_closed_archive_heap_region - 1,
first_open_archive_heap_region = last_closed_archive_heap_region + 1,
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/array.hpp
--- a/src/hotspot/share/oops/array.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/array.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -27,6 +27,7 @@
#include "memory/allocation.hpp"
#include "memory/metaspace.hpp"
+#include "runtime/orderAccess.hpp"
#include "utilities/align.hpp"
// Array for metadata allocation
@@ -121,8 +122,8 @@
T* adr_at(const int i) { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return &_data[i]; }
int find(const T& x) { return index_of(x); }
- T at_acquire(const int which);
- void release_at_put(int which, T contents);
+ T at_acquire(const int i) { return OrderAccess::load_acquire(adr_at(i)); }
+ void release_at_put(int i, T x) { OrderAccess::release_store(adr_at(i), x); }
static int size(int length) {
size_t bytes = align_up(byte_sizeof(length), BytesPerWord);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/array.inline.hpp
--- a/src/hotspot/share/oops/array.inline.hpp Fri Feb 22 17:03:09 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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_OOPS_ARRAY_INLINE_HPP
-#define SHARE_OOPS_ARRAY_INLINE_HPP
-
-#include "oops/array.hpp"
-#include "runtime/orderAccess.hpp"
-
-template
-inline T Array::at_acquire(const int which) { return OrderAccess::load_acquire(adr_at(which)); }
-
-template
-inline void Array::release_at_put(int which, T contents) { OrderAccess::release_store(adr_at(which), contents); }
-
-#endif // SHARE_OOPS_ARRAY_INLINE_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/constantPool.cpp
--- a/src/hotspot/share/oops/constantPool.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/constantPool.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -39,7 +39,7 @@
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/array.inline.hpp"
+#include "oops/array.hpp"
#include "oops/constantPool.inline.hpp"
#include "oops/cpCache.inline.hpp"
#include "oops/instanceKlass.hpp"
@@ -56,10 +56,6 @@
#include "runtime/vframe.inline.hpp"
#include "utilities/copy.hpp"
-constantTag ConstantPool::tag_at(int which) const { return (constantTag)tags()->at_acquire(which); }
-
-void ConstantPool::release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); }
-
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
Array* tags = MetadataFactory::new_array(loader_data, length, 0, CHECK_NULL);
int size = ConstantPool::size(length);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/constantPool.hpp
--- a/src/hotspot/share/oops/constantPool.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/constantPool.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -131,7 +131,7 @@
void set_tags(Array* tags) { _tags = tags; }
void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); }
- void release_tag_at_put(int which, jbyte t);
+ void release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); }
u1* tag_addr_at(int which) const { return tags()->adr_at(which); }
@@ -379,7 +379,7 @@
// Tag query
- constantTag tag_at(int which) const;
+ constantTag tag_at(int which) const { return (constantTag)tags()->at_acquire(which); }
// Fetching constants
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/generateOopMap.cpp
--- a/src/hotspot/share/oops/generateOopMap.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/generateOopMap.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -27,6 +27,7 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
+#include "oops/constantPool.hpp"
#include "oops/generateOopMap.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/instanceKlass.cpp
--- a/src/hotspot/share/oops/instanceKlass.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -53,6 +53,7 @@
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/fieldStreams.hpp"
+#include "oops/constantPool.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/instanceMirrorKlass.hpp"
@@ -182,8 +183,14 @@
if (name == k->name()) {
log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index);
- // names match so check actual klass - this may trigger class loading if
- // it doesn't match (but that should be impossible)
+ // Names match so check actual klass - this may trigger class loading if
+ // it doesn't match (though that should be impossible). But to be safe we
+ // have to check for a compiler thread executing here.
+ if (!THREAD->can_call_java() && !_constants->tag_at(cp_index).is_klass()) {
+ log_trace(class, nestmates)("- validation required resolution in an unsuitable thread");
+ return false;
+ }
+
Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
if (k2 == k) {
log_trace(class, nestmates)("- class is listed as a nest member");
@@ -295,7 +302,7 @@
error);
}
- if (validationException != NULL) {
+ if (validationException != NULL && THREAD->can_call_java()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(THREAD_AND_LOCATION,
validationException,
@@ -2346,6 +2353,7 @@
#if INCLUDE_JVMTI
guarantee(_breakpoints == NULL, "must be");
guarantee(_previous_versions == NULL, "must be");
+ _cached_class_file = NULL;
#endif
_init_thread = NULL;
@@ -2502,7 +2510,7 @@
}
// deallocate the cached class file
- if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
+ if (_cached_class_file != NULL) {
os::free(_cached_class_file);
_cached_class_file = NULL;
}
@@ -3963,12 +3971,7 @@
#if INCLUDE_JVMTI
JvmtiCachedClassFileData* InstanceKlass::get_cached_class_file() {
- if (MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
- // Ignore the archived class stream data
- return NULL;
- } else {
- return _cached_class_file;
- }
+ return _cached_class_file;
}
jint InstanceKlass::get_cached_class_file_len() {
@@ -3978,19 +3981,4 @@
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
-
-#if INCLUDE_CDS
-JvmtiCachedClassFileData* InstanceKlass::get_archived_class_data() {
- if (DumpSharedSpaces) {
- return _cached_class_file;
- } else {
- assert(this->is_shared(), "class should be shared");
- if (MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
- return _cached_class_file;
- } else {
- return NULL;
- }
- }
-}
#endif
-#endif
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/instanceKlass.hpp
--- a/src/hotspot/share/oops/instanceKlass.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -847,14 +847,6 @@
JvmtiCachedClassFieldMap* jvmti_cached_class_field_map() const {
return _jvmti_cached_class_field_map;
}
-
-#if INCLUDE_CDS
- void set_archived_class_data(JvmtiCachedClassFileData* data) {
- _cached_class_file = data;
- }
-
- JvmtiCachedClassFileData * get_archived_class_data();
-#endif // INCLUDE_CDS
#else // INCLUDE_JVMTI
static void purge_previous_versions(InstanceKlass* ik) { return; };
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/method.cpp
--- a/src/hotspot/share/oops/method.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/method.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -42,6 +42,7 @@
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/constMethod.hpp"
+#include "oops/constantPool.hpp"
#include "oops/method.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayOop.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/oopHandle.hpp
--- a/src/hotspot/share/oops/oopHandle.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/oopHandle.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -36,6 +36,7 @@
// future uses for read barriers.
class OopHandle {
+ friend class VMStructs;
private:
oop* _obj;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/oops/reflectionAccessorImplKlassHelper.cpp
--- a/src/hotspot/share/oops/reflectionAccessorImplKlassHelper.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/oops/reflectionAccessorImplKlassHelper.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/constantPool.hpp"
#include "oops/reflectionAccessorImplKlassHelper.hpp"
#include "utilities/constantTag.hpp"
#include "utilities/debug.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/opto/escape.cpp
--- a/src/hotspot/share/opto/escape.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/opto/escape.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1726,6 +1726,18 @@
// access its field since the field value is unknown after it.
//
Node* n = field->ideal_node();
+
+ // Test for an unsafe access that was parsed as maybe off heap
+ // (with a CheckCastPP to raw memory).
+ assert(n->is_AddP(), "expect an address computation");
+ if (n->in(AddPNode::Base)->is_top() &&
+ n->in(AddPNode::Address)->Opcode() == Op_CheckCastPP) {
+ assert(n->in(AddPNode::Address)->bottom_type()->isa_rawptr(), "raw address so raw cast expected");
+ assert(_igvn->type(n->in(AddPNode::Address)->in(1))->isa_oopptr(), "cast pattern at unsafe access expected");
+ jobj->set_scalar_replaceable(false);
+ return;
+ }
+
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* u = n->fast_out(i);
if (u->is_LoadStore() || (u->is_Mem() && u->as_Mem()->is_mismatched_access())) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/prims/jni.cpp
--- a/src/hotspot/share/prims/jni.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/prims/jni.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -3953,9 +3953,6 @@
}
#endif
- // Tracks the time application was running before GC
- RuntimeService::record_application_start();
-
// Notify JVMTI
if (JvmtiExport::should_post_thread_life()) {
JvmtiExport::post_thread_start(thread);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/prims/jvm.cpp
--- a/src/hotspot/share/prims/jvm.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/prims/jvm.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -45,6 +45,7 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
+#include "oops/constantPool.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/prims/jvmtiRedefineClasses.cpp
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -39,6 +39,7 @@
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
+#include "oops/constantPool.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/klassVtable.hpp"
#include "oops/oop.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/arguments.cpp
--- a/src/hotspot/share/runtime/arguments.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/arguments.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -529,6 +529,7 @@
{ "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
{ "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(12), JDK_Version::undefined() },
{ "CompilationPolicyChoice", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
+ { "FailOverToOldVerifier", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
{ "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
@@ -555,13 +556,13 @@
{ "UseImplicitStableValues", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) },
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
+ // These entries will generate build errors. Their purpose is to test the macros.
{ "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "dep > exp ", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::jdk(8) },
{ "obs > exp ", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(8) },
{ "not deprecated or obsolete", JDK_Version::undefined(), JDK_Version::undefined(), JDK_Version::jdk(9) },
{ "dup option", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() },
{ "dup option", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() },
- { "BytecodeVerificationRemote", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::undefined() },
#endif
{ NULL, JDK_Version(0), JDK_Version(0) }
@@ -2453,9 +2454,15 @@
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
if(tail != NULL) {
const char* pos = strchr(tail, '=');
- size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
- char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len);
- name[len] = '\0';
+ char* name;
+ if (pos == NULL) {
+ name = os::strdup_check_oom(tail, mtArguments);
+ } else {
+ size_t len = pos - tail;
+ name = NEW_C_HEAP_ARRAY(char, len + 1, mtArguments);
+ memcpy(name, tail, len);
+ name[len] = '\0';
+ }
char *options = NULL;
if(pos != NULL) {
@@ -2749,6 +2756,7 @@
if (FLAG_SET_CMDLINE(bool, BytecodeVerificationRemote, false) != JVMFlag::SUCCESS) {
return JNI_EINVAL;
}
+ warning("Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.");
} else if (is_bad_option(option, args->ignoreUnrecognized, "verification")) {
return JNI_EINVAL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/deoptimization.cpp
--- a/src/hotspot/share/runtime/deoptimization.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/deoptimization.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -36,6 +36,7 @@
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/constantPool.hpp"
#include "oops/method.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/fieldDescriptor.cpp
--- a/src/hotspot/share/runtime/fieldDescriptor.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/fieldDescriptor.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -28,6 +28,7 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/annotations.hpp"
+#include "oops/constantPool.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/init.cpp
--- a/src/hotspot/share/runtime/init.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/init.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -174,10 +174,7 @@
ObjectSynchronizer::audit_and_print_stats(true /* on_exit */);
}
perfMemory_exit();
- if (log_is_enabled(Debug, safepoint, stats)) {
- // Print the collected safepoint statistics.
- SafepointSynchronize::print_stat_on_exit();
- }
+ SafepointTracing::statistics_exit_log();
if (PrintStringTableStatistics) {
SymbolTable::dump(tty);
StringTable::dump(tty);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/monitorChunk.cpp
--- a/src/hotspot/share/runtime/monitorChunk.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/monitorChunk.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
MonitorChunk::MonitorChunk(int number_on_monitors) {
_number_of_monitors = number_on_monitors;
- _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors, mtInternal);
+ _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors, mtSynchronizer);
_next = NULL;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/monitorChunk.hpp
--- a/src/hotspot/share/runtime/monitorChunk.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/monitorChunk.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -30,7 +30,7 @@
// Data structure for holding monitors for one activation during
// deoptimization.
-class MonitorChunk: public CHeapObj {
+class MonitorChunk: public CHeapObj {
private:
int _number_of_monitors;
BasicObjectLock* _monitors;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/mutex.hpp
--- a/src/hotspot/share/runtime/mutex.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/mutex.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -39,7 +39,7 @@
// TODO: Check if _name[MONITOR_NAME_LEN] should better get replaced by const char*.
static const int MONITOR_NAME_LEN = 64;
-class Monitor : public CHeapObj {
+class Monitor : public CHeapObj {
public:
// A special lock: Is a lock where you are guaranteed not to block while you are
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/mutexLocker.cpp
--- a/src/hotspot/share/runtime/mutexLocker.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -150,6 +150,9 @@
#if INCLUDE_NMT
Mutex* NMTQuery_lock = NULL;
#endif
+#if INCLUDE_CDS && INCLUDE_JVMTI
+Mutex* CDSClassFileStream_lock = NULL;
+#endif
#define MAX_NUM_MUTEX 128
static Monitor * _mutex_array[MAX_NUM_MUTEX];
@@ -339,6 +342,9 @@
#if INCLUDE_NMT
def(NMTQuery_lock , PaddedMutex , max_nonleaf, false, Monitor::_safepoint_check_always);
#endif
+#if INCLUDE_CDS && INCLUDE_JVMTI
+ def(CDSClassFileStream_lock , PaddedMutex , max_nonleaf, false, Monitor::_safepoint_check_always);
+#endif
}
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/mutexLocker.hpp
--- a/src/hotspot/share/runtime/mutexLocker.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -133,6 +133,9 @@
#if INCLUDE_NMT
extern Mutex* NMTQuery_lock; // serialize NMT Dcmd queries
#endif
+#if INCLUDE_CDS && INCLUDE_JVMTI
+extern Mutex* CDSClassFileStream_lock; // FileMapInfo::open_stream_for_jvmti
+#endif
#if INCLUDE_JFR
extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table
extern Monitor* JfrMsg_lock; // protects JFR messaging
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/safepoint.cpp
--- a/src/hotspot/share/runtime/safepoint.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/safepoint.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -103,16 +103,6 @@
}
}
-static void post_safepoint_wait_blocked_event(EventSafepointWaitBlocked& event,
- uint64_t safepoint_id,
- int initial_threads_waiting_to_block) {
- if (event.should_commit()) {
- event.set_safepointId(safepoint_id);
- event.set_runningThreadCount(initial_threads_waiting_to_block);
- event.commit();
- }
-}
-
static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask& event,
uint64_t safepoint_id,
const char* name) {
@@ -138,27 +128,21 @@
volatile uint64_t SafepointSynchronize::_safepoint_counter = 0;
const uint64_t SafepointSynchronize::InactiveSafepointCounter = 0;
int SafepointSynchronize::_current_jni_active_count = 0;
-long SafepointSynchronize::_end_of_last_safepoint = 0;
WaitBarrier* SafepointSynchronize::_wait_barrier;
-// We need a place to save the desc since it is released before we need it.
-static char stopped_description[64] = "";
-static bool _vm_is_waiting = false;
-
static volatile bool PageArmed = false; // safepoint polling page is RO|RW vs PROT_NONE
static bool timeout_error_printed = false;
// Statistic related
-julong SafepointSynchronize::_coalesced_vmop_count = 0;
static jlong _safepoint_begin_time = 0;
-static float _ts_of_current_safepoint = 0.0f;
static volatile int _nof_threads_hit_polling_page = 0;
void SafepointSynchronize::init(Thread* vmthread) {
// WaitBarrier should never be destroyed since we will have
// threads waiting on it while exiting.
_wait_barrier = new WaitBarrier(vmthread);
+ SafepointTracing::init();
}
void SafepointSynchronize::increment_jni_active_count() {
@@ -244,16 +228,13 @@
DEBUG_ONLY(assert_list_is_valid(tss_head, still_running);)
*initial_running = still_running;
- if (log_is_enabled(Debug, safepoint, stats)) {
- begin_statistics(nof_threads, still_running);
- }
int iterations = 1; // The first iteration is above.
while (still_running > 0) {
// Check if this has taken too long:
if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
- print_safepoint_timeout(_spinning_timeout);
+ print_safepoint_timeout();
}
if (int(iterations) == -1) { // overflow - something is wrong.
// We can only overflow here when we are using global
@@ -291,9 +272,6 @@
assert(tss_head == NULL, "Must be empty");
- if (log_is_enabled(Debug, safepoint, stats)) {
- update_statistics_on_spin_end();
- }
return iterations;
}
@@ -303,8 +281,11 @@
// stopped by different mechanisms:
//
// 1. Running interpreted
- // The interpreter dispatch table is changed to force it to
- // check for a safepoint condition between bytecodes.
+ // When executing branching/returning byte codes interpreter
+ // checks if the poll is armed, if so blocks in SS::block().
+ // When using global polling the interpreter dispatch table
+ // is changed to force it to check for a safepoint condition
+ // between bytecodes.
// 2. Running in native code
// When returning from the native code, a Java thread must check
// the safepoint _state to see if we must block. If the
@@ -322,9 +303,9 @@
// block condition until the safepoint operation is complete.
// 5. In VM or Transitioning between states
// If a Java thread is currently running in the VM or transitioning
- // between states, the safepointing code will wait for the thread to
- // block itself when it attempts transitions to a new state.
- //
+ // between states, the safepointing code will poll the thread state
+ // until the thread blocks itself when it attempts transitions to a
+ // new state or locking a safepoint checked monitor.
// We must never miss a thread with correct safepoint id, so we must make sure we arm
// the wait barrier for the next safepoint id/counter.
@@ -363,17 +344,10 @@
// Roll all threads forward to a safepoint and suspend them all
void SafepointSynchronize::begin() {
- EventSafepointBegin begin_event;
assert(Thread::current()->is_VM_thread(), "Only VM thread may execute a safepoint");
- strncpy(stopped_description, VMThread::vm_safepoint_description(), sizeof(stopped_description) - 1);
- stopped_description[sizeof(stopped_description) - 1] = '\0';
-
- if (log_is_enabled(Debug, safepoint, stats)) {
- _safepoint_begin_time = os::javaTimeNanos();
- _ts_of_current_safepoint = tty->time_stamp().seconds();
- _nof_threads_hit_polling_page = 0;
- }
+ EventSafepointBegin begin_event;
+ SafepointTracing::begin(VMThread::vm_op_type());
Universe::heap()->safepoint_synchronize_begin();
@@ -385,9 +359,9 @@
int nof_threads = Threads::number_of_threads();
- log_debug(safepoint)("Safepoint synchronization initiated using %s wait barrier. (%d threads)", _wait_barrier->description(), nof_threads);
+ _nof_threads_hit_polling_page = 0;
- RuntimeService::record_safepoint_begin();
+ log_debug(safepoint)("Safepoint synchronization initiated using %s wait barrier. (%d threads)", _wait_barrier->description(), nof_threads);
// Reset the count of active JNI critical threads
_current_jni_active_count = 0;
@@ -399,9 +373,9 @@
if (SafepointTimeout) {
// Set the limit time, so that it can be compared to see if this has taken
// too long to complete.
- safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
+ safepoint_limit_time = SafepointTracing::start_of_safepoint() + (jlong)SafepointTimeoutDelay * (NANOUNITS / MILLIUNITS);
+ timeout_error_printed = false;
}
- timeout_error_printed = false;
EventSafepointStateSynchronization sync_event;
int initial_running = 0;
@@ -413,20 +387,13 @@
int iterations = synchronize_threads(safepoint_limit_time, nof_threads, &initial_running);
assert(_waiting_to_block == 0, "No thread should be running");
- post_safepoint_synchronize_event(sync_event, _safepoint_counter, initial_running,
- _waiting_to_block, iterations);
-
- // Keep event from now.
- EventSafepointWaitBlocked wait_blocked_event;
-
#ifndef PRODUCT
- if (SafepointTimeout) {
+ if (safepoint_limit_time != 0) {
jlong current_time = os::javaTimeNanos();
if (safepoint_limit_time < current_time) {
log_warning(safepoint)("# SafepointSynchronize: Finished after "
INT64_FORMAT_W(6) " ms",
- (int64_t)((current_time - safepoint_limit_time) / MICROUNITS +
- (jlong)SafepointTimeoutDelay));
+ (int64_t)(current_time - SafepointTracing::start_of_safepoint()) / (NANOUNITS / MILLIUNITS));
}
}
#endif
@@ -438,8 +405,6 @@
OrderAccess::fence();
- post_safepoint_wait_blocked_event(wait_blocked_event, _safepoint_counter, 0);
-
#ifdef ASSERT
// Make sure all the threads were visited.
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) {
@@ -450,12 +415,12 @@
// Update the count of active JNI critical regions
GCLocker::set_jni_lock_count(_current_jni_active_count);
- log_info(safepoint)("Entering safepoint region: %s", stopped_description);
+ post_safepoint_synchronize_event(sync_event,
+ _safepoint_counter,
+ initial_running,
+ _waiting_to_block, iterations);
- RuntimeService::record_safepoint_synchronized();
- if (log_is_enabled(Debug, safepoint, stats)) {
- update_statistics_on_sync_end(os::javaTimeNanos());
- }
+ SafepointTracing::synchronized(nof_threads, initial_running, _nof_threads_hit_polling_page);
// We do the safepoint cleanup first since a GC related safepoint
// needs cleanup to be completed before running the GC op.
@@ -463,12 +428,8 @@
do_cleanup_tasks();
post_safepoint_cleanup_event(cleanup_event, _safepoint_counter);
- if (log_is_enabled(Debug, safepoint, stats)) {
- // Record how much time spend on the above cleanup tasks
- update_statistics_on_cleanup_end(os::javaTimeNanos());
- }
-
post_safepoint_begin_event(begin_event, _safepoint_counter, nof_threads, _current_jni_active_count);
+ SafepointTracing::cleanup();
}
void SafepointSynchronize::disarm_safepoint() {
@@ -520,10 +481,6 @@
}
} // ~JavaThreadIteratorWithHandle
- log_info(safepoint)("Leaving safepoint region");
-
- RuntimeService::record_safepoint_end();
-
// Release threads lock, so threads can be created/destroyed again.
Threads_lock->unlock();
@@ -539,19 +496,11 @@
uint64_t safepoint_id = _safepoint_counter;
assert(Thread::current()->is_VM_thread(), "Only VM thread can execute a safepoint");
- if (log_is_enabled(Debug, safepoint, stats)) {
- end_statistics(os::javaTimeNanos());
- }
-
disarm_safepoint();
- RuntimeService::record_safepoint_epilog(stopped_description);
-
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();
+ SafepointTracing::end();
post_safepoint_end_event(event, safepoint_id);
}
@@ -915,7 +864,7 @@
assert(SafepointSynchronize::is_synchronizing(), "polling encountered outside safepoint synchronization");
}
- if (log_is_enabled(Debug, safepoint, stats)) {
+ if (log_is_enabled(Info, safepoint, stats)) {
Atomic::inc(&_nof_threads_hit_polling_page);
}
@@ -925,7 +874,7 @@
}
-void SafepointSynchronize::print_safepoint_timeout(SafepointTimeoutReason reason) {
+void SafepointSynchronize::print_safepoint_timeout() {
if (!timeout_error_printed) {
timeout_error_printed = true;
// Print out the thread info which didn't reach the safepoint for debugging
@@ -937,20 +886,10 @@
ls.cr();
ls.print_cr("# SafepointSynchronize::begin: Timeout detected:");
- if (reason == _spinning_timeout) {
- ls.print_cr("# SafepointSynchronize::begin: Timed out while spinning to reach a safepoint.");
- } else if (reason == _blocking_timeout) {
- ls.print_cr("# SafepointSynchronize::begin: Timed out while waiting for threads to stop.");
- }
-
+ ls.print_cr("# SafepointSynchronize::begin: Timed out while spinning to reach a safepoint.");
ls.print_cr("# SafepointSynchronize::begin: Threads which did not reach the safepoint:");
- ThreadSafepointState *cur_state;
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur_thread = jtiwh.next(); ) {
- cur_state = cur_thread->safepoint_state();
-
- if (cur_thread->thread_state() != _thread_blocked &&
- ((reason == _spinning_timeout && cur_state->is_running()) ||
- (reason == _blocking_timeout))) {
+ if (cur_thread->safepoint_state()->is_running()) {
ls.print("# ");
cur_thread->print_on(&ls);
ls.cr();
@@ -964,11 +903,10 @@
// ShowMessageBoxOnError.
if (AbortVMOnSafepointTimeout) {
fatal("Safepoint sync time longer than " INTX_FORMAT "ms detected when executing %s.",
- SafepointTimeoutDelay, VMThread::vm_safepoint_description());
+ SafepointTimeoutDelay, VMThread::vm_operation()->name());
}
}
-
// -------------------------------------------------------------------------------------------------------
// Implementation of ThreadSafepointState
@@ -1176,108 +1114,25 @@
}
-//
-// Statistics & Instrumentations
-//
-struct SafepointStats {
- float _time_stamp; // record when the current safepoint occurs in seconds
- int _vmop_type; // tyep of VM operation triggers the safepoint
- int _nof_total_threads; // total number of Java threads
- int _nof_initial_running_threads; // total number of initially seen running threads
- int _nof_threads_wait_to_block; // total number of threads waiting for to block
- bool _page_armed; // true if polling page is armed, false otherwise
- int _nof_threads_hit_page_trap; // total number of threads hitting the page trap
- jlong _time_to_spin; // total time in millis spent in spinning
- jlong _time_to_wait_to_block; // total time in millis spent in waiting for to block
- jlong _time_to_do_cleanups; // total time in millis spent in performing cleanups
- jlong _time_to_sync; // total time in millis spent in getting to _synchronized
- jlong _time_to_exec_vmop; // total time in millis spent in vm operation itself
-};
-
-static const int _statistics_header_count = 30;
-static int _cur_stat_index = 0;
-static SafepointStats safepoint_stats = {0}; // zero initialize
-static SafepointStats* spstat = &safepoint_stats;
-
-static julong _safepoint_reasons[VM_Operation::VMOp_Terminating];
-static jlong _max_sync_time = 0;
-static jlong _max_vmop_time = 0;
-
-static jlong cleanup_end_time = 0;
-
-void SafepointSynchronize::begin_statistics(int nof_threads, int nof_running) {
-
- spstat->_time_stamp = _ts_of_current_safepoint;
-
- VM_Operation *op = VMThread::vm_operation();
- spstat->_vmop_type = op != NULL ? op->type() : VM_Operation::VMOp_None;
- _safepoint_reasons[spstat->_vmop_type]++;
-
- spstat->_nof_total_threads = nof_threads;
- spstat->_nof_initial_running_threads = nof_running;
-
- // Records the start time of spinning. The real time spent on spinning
- // will be adjusted when spin is done. Same trick is applied for time
- // spent on waiting for threads to block.
- if (nof_running != 0) {
- spstat->_time_to_spin = os::javaTimeNanos();
- } else {
- spstat->_time_to_spin = 0;
- }
-}
+// -------------------------------------------------------------------------------------------------------
+// Implementation of SafepointTracing
-void SafepointSynchronize::update_statistics_on_spin_end() {
- jlong cur_time = os::javaTimeNanos();
-
- spstat->_nof_threads_wait_to_block = _waiting_to_block;
- if (spstat->_nof_initial_running_threads != 0) {
- spstat->_time_to_spin = cur_time - spstat->_time_to_spin;
- }
-
- // Records the start time of waiting for to block. Updated when block is done.
- if (_waiting_to_block != 0) {
- spstat->_time_to_wait_to_block = cur_time;
- } else {
- spstat->_time_to_wait_to_block = 0;
- }
-}
-
-void SafepointSynchronize::update_statistics_on_sync_end(jlong end_time) {
-
- if (spstat->_nof_threads_wait_to_block != 0) {
- spstat->_time_to_wait_to_block = end_time -
- spstat->_time_to_wait_to_block;
- }
+jlong SafepointTracing::_last_safepoint_begin_time_ns = 0;
+jlong SafepointTracing::_last_safepoint_sync_time_ns = 0;
+jlong SafepointTracing::_last_safepoint_cleanup_time_ns = 0;
+jlong SafepointTracing::_last_safepoint_end_time_ns = 0;
+jlong SafepointTracing::_last_app_time_ns = 0;
+int SafepointTracing::_nof_threads = 0;
+int SafepointTracing::_nof_running = 0;
+int SafepointTracing::_page_trap = 0;
+VM_Operation::VMOp_Type SafepointTracing::_current_type;
+jlong SafepointTracing::_max_sync_time = 0;
+jlong SafepointTracing::_max_vmop_time = 0;
+uint64_t SafepointTracing::_op_count[VM_Operation::VMOp_Terminating] = {0};
- // Records the end time of sync which will be used to calculate the total
- // vm operation time. Again, the real time spending in syncing will be deducted
- // from the start of the sync time later when end_statistics is called.
- spstat->_time_to_sync = end_time - _safepoint_begin_time;
- if (spstat->_time_to_sync > _max_sync_time) {
- _max_sync_time = spstat->_time_to_sync;
- }
-
- spstat->_time_to_do_cleanups = end_time;
-}
-
-void SafepointSynchronize::update_statistics_on_cleanup_end(jlong end_time) {
-
- // Record how long spent in cleanup tasks.
- spstat->_time_to_do_cleanups = end_time - spstat->_time_to_do_cleanups;
- cleanup_end_time = end_time;
-}
-
-void SafepointSynchronize::end_statistics(jlong vmop_end_time) {
-
- // Update the vm operation time.
- spstat->_time_to_exec_vmop = vmop_end_time - cleanup_end_time;
- if (spstat->_time_to_exec_vmop > _max_vmop_time) {
- _max_vmop_time = spstat->_time_to_exec_vmop;
- }
-
- spstat->_nof_threads_hit_page_trap = _nof_threads_hit_polling_page;
-
- print_statistics();
+void SafepointTracing::init() {
+ // Application start
+ _last_safepoint_end_time_ns = os::javaTimeNanos();
}
// Helper method to print the header.
@@ -1285,66 +1140,121 @@
// The number of spaces is significant here, and should match the format
// specifiers in print_statistics().
- st->print(" vmop "
- "[ threads: total initially_running wait_to_block ]"
- "[ time: spin block sync cleanup vmop ] ");
+ st->print("VM Operation "
+ "[ threads: total initial_running ]"
+ "[ time: sync cleanup vmop total ]");
- st->print_cr("page_trap_count");
+ st->print_cr(" page_trap_count");
}
// This prints a nice table. To get the statistics to not shift due to the logging uptime
-// decorator, use the option as: -Xlog:safepoint+stats=debug:[outputfile]:none
-void SafepointSynchronize::print_statistics() {
- LogTarget(Debug, safepoint, stats) lt;
+// decorator, use the option as: -Xlog:safepoint+stats:[outputfile]:none
+void SafepointTracing::statistics_log() {
+ LogTarget(Info, safepoint, stats) lt;
assert (lt.is_enabled(), "should only be called when printing statistics is enabled");
LogStream ls(lt);
+ static int _cur_stat_index = 0;
+
// Print header every 30 entries
- if ((_cur_stat_index % _statistics_header_count) == 0) {
+ if ((_cur_stat_index % 30) == 0) {
print_header(&ls);
_cur_stat_index = 1; // wrap
} else {
_cur_stat_index++;
}
- ls.print("%8.3f: ", spstat->_time_stamp);
- ls.print("%-28s [ "
- INT32_FORMAT_W(8) " " INT32_FORMAT_W(17) " " INT32_FORMAT_W(13) " "
+ ls.print("%-28s [ "
+ INT32_FORMAT_W(8) " " INT32_FORMAT_W(8) " "
"]",
- VM_Operation::name(spstat->_vmop_type),
- spstat->_nof_total_threads,
- spstat->_nof_initial_running_threads,
- spstat->_nof_threads_wait_to_block);
- // "/ MICROUNITS " is to convert the unit from nanos to millis.
+ VM_Operation::name(_current_type),
+ _nof_threads,
+ _nof_running);
ls.print("[ "
- INT64_FORMAT_W(7) " " INT64_FORMAT_W(7) " "
- INT64_FORMAT_W(7) " " INT64_FORMAT_W(7) " "
- INT64_FORMAT_W(7) " ] ",
- (int64_t)(spstat->_time_to_spin / MICROUNITS),
- (int64_t)(spstat->_time_to_wait_to_block / MICROUNITS),
- (int64_t)(spstat->_time_to_sync / MICROUNITS),
- (int64_t)(spstat->_time_to_do_cleanups / MICROUNITS),
- (int64_t)(spstat->_time_to_exec_vmop / MICROUNITS));
+ INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " "
+ INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " ]",
+ (int64_t)(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns),
+ (int64_t)(_last_safepoint_cleanup_time_ns - _last_safepoint_sync_time_ns),
+ (int64_t)(_last_safepoint_end_time_ns - _last_safepoint_cleanup_time_ns),
+ (int64_t)(_last_safepoint_end_time_ns - _last_safepoint_begin_time_ns));
- ls.print_cr(INT32_FORMAT_W(15) " ", spstat->_nof_threads_hit_page_trap);
+ ls.print_cr(INT32_FORMAT_W(16), _page_trap);
}
// This method will be called when VM exits. This tries to summarize the sampling.
// Current thread may already be deleted, so don't use ResourceMark.
-void SafepointSynchronize::print_stat_on_exit() {
-
+void SafepointTracing::statistics_exit_log() {
+ if (!log_is_enabled(Info, safepoint, stats)) {
+ return;
+ }
for (int index = 0; index < VM_Operation::VMOp_Terminating; index++) {
- if (_safepoint_reasons[index] != 0) {
- log_debug(safepoint, stats)("%-28s" UINT64_FORMAT_W(10), VM_Operation::name(index),
- _safepoint_reasons[index]);
+ if (_op_count[index] != 0) {
+ log_info(safepoint, stats)("%-28s" UINT64_FORMAT_W(10), VM_Operation::name(index),
+ _op_count[index]);
}
}
- log_debug(safepoint, stats)("VM operations coalesced during safepoint " INT64_FORMAT,
- _coalesced_vmop_count);
- log_debug(safepoint, stats)("Maximum sync time " INT64_FORMAT" ms",
- (int64_t)(_max_sync_time / MICROUNITS));
- log_debug(safepoint, stats)("Maximum vm operation time (except for Exit VM operation) "
- INT64_FORMAT " ms",
- (int64_t)(_max_vmop_time / MICROUNITS));
+ log_info(safepoint, stats)("VM operations coalesced during safepoint " INT64_FORMAT,
+ VMThread::get_coalesced_count());
+ log_info(safepoint, stats)("Maximum sync time " INT64_FORMAT" ns",
+ (int64_t)(_max_sync_time));
+ log_info(safepoint, stats)("Maximum vm operation time (except for Exit VM operation) "
+ INT64_FORMAT " ns",
+ (int64_t)(_max_vmop_time));
+}
+
+void SafepointTracing::begin(VM_Operation::VMOp_Type type) {
+ _op_count[type]++;
+ _current_type = type;
+
+ // update the time stamp to begin recording safepoint time
+ _last_safepoint_begin_time_ns = os::javaTimeNanos();
+ _last_safepoint_sync_time_ns = 0;
+ _last_safepoint_cleanup_time_ns = 0;
+
+ _last_app_time_ns = _last_safepoint_begin_time_ns - _last_safepoint_end_time_ns;
+ _last_safepoint_end_time_ns = 0;
+
+ RuntimeService::record_safepoint_begin(_last_app_time_ns);
+}
+
+void SafepointTracing::synchronized(int nof_threads, int nof_running, int traps) {
+ _last_safepoint_sync_time_ns = os::javaTimeNanos();
+ _nof_threads = nof_threads;
+ _nof_running = nof_running;
+ _page_trap = traps;
+ RuntimeService::record_safepoint_synchronized(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns);
}
+
+void SafepointTracing::cleanup() {
+ _last_safepoint_cleanup_time_ns = os::javaTimeNanos();
+}
+
+void SafepointTracing::end() {
+ _last_safepoint_end_time_ns = os::javaTimeNanos();
+
+ if (_max_sync_time < (_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns)) {
+ _max_sync_time = _last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns;
+ }
+ if (_max_vmop_time < (_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns)) {
+ _max_vmop_time = _last_safepoint_end_time_ns - _last_safepoint_sync_time_ns;
+ }
+ if (log_is_enabled(Info, safepoint, stats)) {
+ statistics_log();
+ }
+
+ log_info(safepoint)(
+ "Safepoint \"%s\", "
+ "Time since last: " JLONG_FORMAT " ns, "
+ "Reaching safepoint: " JLONG_FORMAT " ns, "
+ "At safepoint: " JLONG_FORMAT " ns, "
+ "Total: " JLONG_FORMAT " ns",
+ VM_Operation::name(_current_type),
+ _last_app_time_ns,
+ _last_safepoint_cleanup_time_ns - _last_safepoint_begin_time_ns,
+ _last_safepoint_end_time_ns - _last_safepoint_cleanup_time_ns,
+ _last_safepoint_end_time_ns - _last_safepoint_begin_time_ns
+ );
+
+ RuntimeService::record_safepoint_end(_last_safepoint_end_time_ns - _last_safepoint_cleanup_time_ns);
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/safepoint.hpp
--- a/src/hotspot/share/runtime/safepoint.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/safepoint.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
+#include "runtime/vmOperations.hpp"
#include "utilities/ostream.hpp"
#include "utilities/waitBarrier.hpp"
@@ -77,11 +78,6 @@
friend class ThreadSafepointState;
friend class HandshakeState;
- enum SafepointTimeoutReason {
- _spinning_timeout = 0,
- _blocking_timeout = 1
- };
-
// Threads might read this flag directly, without acquiring the Threads_lock:
static volatile SynchronizeState _state;
// Number of threads we are waiting for to block:
@@ -110,7 +106,7 @@
static void print_statistics();
// For debug long safepoint
- static void print_safepoint_timeout(SafepointTimeoutReason timeout_reason);
+ static void print_safepoint_timeout();
// Helper methods for safepoint procedure:
static void arm_safepoint();
@@ -150,19 +146,9 @@
// Exception handling for page polling
static void handle_polling_page_exception(JavaThread *thread);
- // VM Thread interface for determining safepoint rate
- static long last_non_safepoint_interval() {
- return os::javaTimeMillis() - _end_of_last_safepoint;
- }
- static long end_of_last_safepoint() {
- return _end_of_last_safepoint;
- }
static bool is_cleanup_needed();
static void do_cleanup_tasks();
- static void print_stat_on_exit();
- static void inc_vmop_coalesced_count() { _coalesced_vmop_count++; }
-
static void set_is_at_safepoint() { _state = _synchronized; }
static void set_is_not_at_safepoint() { _state = _not_synchronized; }
@@ -197,7 +183,7 @@
assert(!SafepointSynchronize::is_at_safepoint(), __VA_ARGS__)
// State class for a thread suspended at a safepoint
-class ThreadSafepointState: public CHeapObj {
+class ThreadSafepointState: public CHeapObj {
private:
// At polling page safepoint (NOT a poll return safepoint):
volatile bool _at_poll_safepoint;
@@ -247,6 +233,48 @@
static void destroy(JavaThread *thread);
};
+class SafepointTracing : public AllStatic {
+private:
+ // Absolute
+ static jlong _last_safepoint_begin_time_ns;
+ static jlong _last_safepoint_sync_time_ns;
+ static jlong _last_safepoint_cleanup_time_ns;
+ static jlong _last_safepoint_end_time_ns;
+ // Relative
+ static jlong _last_app_time_ns;
+ static int _nof_threads;
+ static int _nof_running;
+ static int _page_trap;
+
+ static VM_Operation::VMOp_Type _current_type;
+ static jlong _max_sync_time;
+ static jlong _max_vmop_time;
+ static uint64_t _op_count[VM_Operation::VMOp_Terminating];
+
+ static void statistics_log();
+
+public:
+ static void init();
+
+ static void begin(VM_Operation::VMOp_Type type);
+ static void synchronized(int nof_threads, int nof_running, int traps);
+ static void cleanup();
+ static void end();
+
+ static void statistics_exit_log();
+
+ static jlong time_since_last_safepoint_ms() {
+ return (os::javaTimeNanos() - _last_safepoint_end_time_ns) / (NANOUNITS / MILLIUNITS);
+ }
+
+ static jlong end_of_last_safepoint_ms() {
+ return _last_safepoint_end_time_ns / (NANOUNITS / MILLIUNITS);
+ }
+
+ static jlong start_of_safepoint() {
+ return _last_safepoint_begin_time_ns;
+ }
+};
#endif // SHARE_RUNTIME_SAFEPOINT_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/semaphore.hpp
--- a/src/hotspot/share/runtime/semaphore.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/semaphore.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -40,7 +40,7 @@
class JavaThread;
// Implements the limited, platform independent Semaphore API.
-class Semaphore : public CHeapObj {
+class Semaphore : public CHeapObj {
SemaphoreImpl _impl;
// Prevent copying and assignment of Semaphore instances.
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/tieredThresholdPolicy.cpp
--- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -479,7 +479,7 @@
// We don't update the rate if we've just came out of a safepoint.
// delta_s is the time since last safepoint in milliseconds.
- jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint();
+ jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement
// How many events were there since the last time?
int event_count = m->invocation_count() + m->backedge_count();
@@ -504,7 +504,7 @@
// Check if this method has been stale from a given number of milliseconds.
// See select_task().
bool TieredThresholdPolicy::is_stale(jlong t, jlong timeout, Method* m) {
- jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint();
+ jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
jlong delta_t = t - m->prev_time();
if (delta_t > timeout && delta_s > timeout) {
int event_count = m->invocation_count() + m->backedge_count();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/vmOperations.hpp
--- a/src/hotspot/share/runtime/vmOperations.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/vmOperations.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -41,6 +41,7 @@
// Note: When new VM_XXX comes up, add 'XXX' to the template table.
#define VM_OPS_DO(template) \
template(None) \
+ template(Cleanup) \
template(ThreadStop) \
template(ThreadDump) \
template(PrintThreads) \
@@ -213,7 +214,7 @@
// Debugging
virtual void print_on_error(outputStream* st) const;
- const char* name() const { return _names[type()]; }
+ virtual const char* name() const { return _names[type()]; }
static const char* name(int type) {
assert(type >= 0 && type < VMOp_Terminating, "invalid VM operation type");
return _names[type];
@@ -223,6 +224,21 @@
#endif
};
+class VM_None: public VM_Operation {
+ const char* _reason;
+ public:
+ VM_None(const char* reason) : _reason(reason) {}
+ const char* name() const { return _reason; }
+ VMOp_Type type() const { return VMOp_None; }
+ void doit() {};
+};
+
+class VM_Cleanup: public VM_Operation {
+ public:
+ VMOp_Type type() const { return VMOp_Cleanup; }
+ void doit() {};
+};
+
class VM_ThreadStop: public VM_Operation {
private:
oop _thread; // The Thread that the Throwable is thrown against
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/vmStructs.cpp
--- a/src/hotspot/share/runtime/vmStructs.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/vmStructs.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -332,6 +332,7 @@
unchecked_nonstatic_field(Symbol, _body, sizeof(u1)) /* NOTE: no type */ \
nonstatic_field(Symbol, _body[0], u1) \
nonstatic_field(TypeArrayKlass, _max_length, jint) \
+ nonstatic_field(OopHandle, _obj, oop*) \
\
/***********************/ \
/* Constant Pool Cache */ \
@@ -1299,7 +1300,8 @@
declare_oop_type(oop) \
declare_oop_type(narrowOop) \
declare_oop_type(typeArrayOop) \
- declare_oop_type(OopHandle) \
+ \
+ declare_toplevel_type(OopHandle) \
\
/*************************************/ \
/* MethodOop-related data structures */ \
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/vmThread.cpp
--- a/src/hotspot/share/runtime/vmThread.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/vmThread.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -48,19 +48,13 @@
#include "utilities/vmError.hpp"
#include "utilities/xmlstream.hpp"
-// Dummy VM operation to act as first element in our circular double-linked list
-class VM_None: public VM_Operation {
- VMOp_Type type() const { return VMOp_None; }
- void doit() {};
-};
-
VMOperationQueue::VMOperationQueue() {
// The queue is a circular doubled-linked list, which always contains
// one element (i.e., one element means empty).
for(int i = 0; i < nof_priorities; i++) {
_queue_length[i] = 0;
_queue_counter = 0;
- _queue[i] = new VM_None();
+ _queue[i] = new VM_None("QueueHead");
_queue[i]->set_next(_queue[i]);
_queue[i]->set_prev(_queue[i]);
}
@@ -229,14 +223,14 @@
//------------------------------------------------------------------------------------------------------------------
// Implementation of VMThread stuff
-bool VMThread::_should_terminate = false;
+bool VMThread::_should_terminate = false;
bool VMThread::_terminated = false;
Monitor* VMThread::_terminate_lock = NULL;
VMThread* VMThread::_vm_thread = NULL;
VM_Operation* VMThread::_cur_vm_operation = NULL;
VMOperationQueue* VMThread::_vm_queue = NULL;
PerfCounter* VMThread::_perf_accumulated_vm_operation_time = NULL;
-const char* VMThread::_no_op_reason = NULL;
+uint64_t VMThread::_coalesced_count = 0;
VMOperationTimeoutTask* VMThread::_timeout_task = NULL;
@@ -283,6 +277,8 @@
_vm_thread = NULL; // VM thread is gone
}
+static VM_None halt_op("Halt");
+
void VMThread::run() {
assert(this == vm_thread(), "check");
@@ -320,7 +316,7 @@
}
// 4526887 let VM thread exit at Safepoint
- _no_op_reason = "Halt";
+ _cur_vm_operation = &halt_op;
SafepointSynchronize::begin();
if (VerifyBeforeExit) {
@@ -435,24 +431,25 @@
}
}
-bool VMThread::no_op_safepoint_needed(bool check_time) {
+static VM_None safepointALot_op("SafepointALot");
+static VM_Cleanup cleanup_op;
+
+VM_Operation* VMThread::no_op_safepoint(bool check_time) {
if (SafepointALot) {
- _no_op_reason = "SafepointALot";
- return true;
+ return &safepointALot_op;
}
if (!SafepointSynchronize::is_cleanup_needed()) {
- return false;
+ return NULL;
}
if (check_time) {
- long interval = SafepointSynchronize::last_non_safepoint_interval();
+ long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
- (interval > GuaranteedSafepointInterval);
+ (interval_ms > GuaranteedSafepointInterval);
if (!max_time_exceeded) {
- return false;
+ return NULL;
}
}
- _no_op_reason = "Cleanup";
- return true;
+ return &cleanup_op;
}
void VMThread::loop() {
@@ -494,7 +491,7 @@
exit(-1);
}
- if (timedout && VMThread::no_op_safepoint_needed(false)) {
+ if (timedout && (_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
MutexUnlockerEx mul(VMOperationQueue_lock,
Mutex::_no_safepoint_check_flag);
// Force a safepoint since we have not had one for at least
@@ -506,6 +503,7 @@
if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
#endif
SafepointSynchronize::end();
+ _cur_vm_operation = NULL;
}
_cur_vm_operation = _vm_queue->remove_next();
@@ -555,9 +553,7 @@
_vm_queue->set_drain_list(next);
evaluate_operation(_cur_vm_operation);
_cur_vm_operation = next;
- if (log_is_enabled(Debug, safepoint, stats)) {
- SafepointSynchronize::inc_vmop_coalesced_count();
- }
+ _coalesced_count++;
} while (_cur_vm_operation != NULL);
}
// There is a chance that a thread enqueued a safepoint op
@@ -622,10 +618,11 @@
//
// We want to make sure that we get to a safepoint regularly.
//
- if (VMThread::no_op_safepoint_needed(true)) {
+ if ((_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
HandleMark hm(VMThread::vm_thread());
SafepointSynchronize::begin();
SafepointSynchronize::end();
+ _cur_vm_operation = NULL;
}
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/runtime/vmThread.hpp
--- a/src/hotspot/share/runtime/vmThread.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/runtime/vmThread.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -119,12 +119,11 @@
static bool _terminated;
static Monitor * _terminate_lock;
static PerfCounter* _perf_accumulated_vm_operation_time;
-
- static const char* _no_op_reason;
+ static uint64_t _coalesced_count;
static VMOperationTimeoutTask* _timeout_task;
- static bool no_op_safepoint_needed(bool check_time);
+ static VM_Operation* no_op_safepoint(bool check_time);
void evaluate_operation(VM_Operation* op);
@@ -155,9 +154,8 @@
// Returns the current vm operation if any.
static VM_Operation* vm_operation() { return _cur_vm_operation; }
-
- // Returns the current vm operation name or set reason
- static const char* vm_safepoint_description() { return _cur_vm_operation != NULL ? _cur_vm_operation->name() : _no_op_reason; };
+ static VM_Operation::VMOp_Type vm_op_type() { return _cur_vm_operation->type(); }
+ static uint64_t get_coalesced_count() { return _coalesced_count; }
// Returns the single instance of VMThread.
static VMThread* vm_thread() { return _vm_thread; }
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/services/attachListener.cpp
--- a/src/hotspot/share/services/attachListener.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/services/attachListener.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -257,19 +257,40 @@
// See also: ClassHistogramDCmd class
//
// Input arguments :-
-// arg0: "-live" or "-all"
+// arg0: Name of the dump file or NULL
+// arg1: "-live" or "-all"
static jint heap_inspection(AttachOperation* op, outputStream* out) {
bool live_objects_only = true; // default is true to retain the behavior before this change is made
- const char* arg0 = op->arg(0);
- if (arg0 != NULL && (strlen(arg0) > 0)) {
- if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) {
- out->print_cr("Invalid argument to inspectheap operation: %s", arg0);
+ outputStream* os = out; // if path not specified or path is NULL, use out
+ fileStream* fs = NULL;
+ const char* path = op->arg(0);
+ if (path != NULL) {
+ if (path[0] == '\0') {
+ out->print_cr("No dump file specified");
+ } else {
+ // create file
+ fs = new (ResourceObj::C_HEAP, mtInternal) fileStream(path);
+ if (fs == NULL) {
+ out->print_cr("Failed to allocate space for file: %s", path);
+ return JNI_ERR;
+ }
+ os = fs;
+ }
+ }
+ const char* arg1 = op->arg(1);
+ if (arg1 != NULL && (strlen(arg1) > 0)) {
+ if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
+ out->print_cr("Invalid argument to inspectheap operation: %s", arg1);
return JNI_ERR;
}
- live_objects_only = strcmp(arg0, "-live") == 0;
+ live_objects_only = strcmp(arg1, "-live") == 0;
}
- VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */);
+ VM_GC_HeapInspection heapop(os, live_objects_only /* request full gc */);
VMThread::execute(&heapop);
+ if (os != NULL && os != out) {
+ out->print_cr("Heap inspection file created: %s", path);
+ delete fs;
+ }
return JNI_OK;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/services/attachListener.hpp
--- a/src/hotspot/share/services/attachListener.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/services/attachListener.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -106,7 +106,7 @@
enum {
name_length_max = 16, // maximum length of name
arg_length_max = 1024, // maximum length of argument
- arg_count_max = 3 // maximum number of arguments
+ arg_count_max = 4 // maximum number of arguments
};
// name of special operation that can be enqueued when all
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/services/diagnosticArgument.cpp
--- a/src/hotspot/share/services/diagnosticArgument.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/services/diagnosticArgument.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -179,9 +179,9 @@
if (str == NULL) {
_value = NULL;
} else {
- _value = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
- strncpy(_value, str, len);
- _value[len] = 0;
+ _value = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
+ int n = snprintf(_value, len + 1, "%.*s", (int)len, str);
+ assert((size_t)n <= len, "Unexpected number of characters in string");
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/services/runtimeService.cpp
--- a/src/hotspot/share/services/runtimeService.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/services/runtimeService.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
#include "logging/log.hpp"
-#include "runtime/timer.hpp"
+#include "logging/logStream.hpp"
#include "runtime/vm_version.hpp"
#include "services/attachListener.hpp"
#include "services/management.hpp"
@@ -35,18 +35,12 @@
#include "utilities/macros.hpp"
#if INCLUDE_MANAGEMENT
-TimeStamp RuntimeService::_app_timer;
-TimeStamp RuntimeService::_safepoint_timer;
PerfCounter* RuntimeService::_sync_time_ticks = NULL;
PerfCounter* RuntimeService::_total_safepoints = NULL;
PerfCounter* RuntimeService::_safepoint_time_ticks = NULL;
PerfCounter* RuntimeService::_application_time_ticks = NULL;
-jlong RuntimeService::_last_safepoint_sync_time_ns = 0;
-jlong RuntimeService::_last_safepoint_end_time_ns = 0;
-jlong RuntimeService::_last_app_time_ns = 0;
void RuntimeService::init() {
-
if (UsePerfData) {
EXCEPTION_MARK;
@@ -87,85 +81,27 @@
}
}
-void RuntimeService::record_safepoint_begin() {
+void RuntimeService::record_safepoint_begin(jlong app_ticks) {
HS_PRIVATE_SAFEPOINT_BEGIN();
-
- // Print the time interval in which the app was executing
- if (_app_timer.is_updated()) {
- _last_app_time_ns = _app_timer.ticks_since_update();
- log_info(safepoint)("Application time: %3.7f seconds", TimeHelper::counter_to_seconds(_last_app_time_ns));
- }
-
- // update the time stamp to begin recording safepoint time
- _last_safepoint_sync_time_ns = 0;
- _last_safepoint_end_time_ns = 0;
- _safepoint_timer.update();
if (UsePerfData) {
_total_safepoints->inc();
- if (_app_timer.is_updated()) {
- _application_time_ticks->inc(_app_timer.ticks_since_update());
- }
- }
-}
-
-void RuntimeService::record_safepoint_synchronized() {
- if (UsePerfData) {
- _sync_time_ticks->inc(_safepoint_timer.ticks_since_update());
- }
- if (log_is_enabled(Info, safepoint) || log_is_enabled(Info, safepoint, stats)) {
- _last_safepoint_sync_time_ns = _safepoint_timer.ticks_since_update();
+ _application_time_ticks->inc(app_ticks);
}
}
-void RuntimeService::record_safepoint_end() {
- HS_PRIVATE_SAFEPOINT_END();
-
- // Logging of safepoint+stats=info needs _last_safepoint_end_time_ns to be set.
- // Logging of safepoint=info needs _last_safepoint_end_time_ns for following log.
- if (log_is_enabled(Info, safepoint) || log_is_enabled(Info, safepoint, stats)) {
- _last_safepoint_end_time_ns = _safepoint_timer.ticks_since_update();
- log_info(safepoint)(
- "Total time for which application threads were stopped: %3.7f seconds, "
- "Stopping threads took: %3.7f seconds",
- TimeHelper::counter_to_seconds(_last_safepoint_end_time_ns),
- TimeHelper::counter_to_seconds(_last_safepoint_sync_time_ns));
- }
-
- // update the time stamp to begin recording app time
- _app_timer.update();
+void RuntimeService::record_safepoint_synchronized(jlong sync_ticks) {
if (UsePerfData) {
- _safepoint_time_ticks->inc(_safepoint_timer.ticks_since_update());
+ _sync_time_ticks->inc(sync_ticks);
}
}
-void RuntimeService::record_safepoint_epilog(const char* operation_name) {
- if (!log_is_enabled(Info, safepoint, stats)) {
- return;
+void RuntimeService::record_safepoint_end(jlong safepoint_ticks) {
+ HS_PRIVATE_SAFEPOINT_END();
+ if (UsePerfData) {
+ _safepoint_time_ticks->inc(safepoint_ticks);
}
-
- log_info(safepoint, stats)(
- "Safepoint \"%s\", "
- "Time since last: " JLONG_FORMAT " ns; "
- "Reaching safepoint: " JLONG_FORMAT " ns; "
- "At safepoint: " JLONG_FORMAT " ns; "
- "Total: " JLONG_FORMAT " ns",
- operation_name,
- _last_app_time_ns,
- _last_safepoint_sync_time_ns,
- _last_safepoint_end_time_ns - _last_safepoint_sync_time_ns,
- _last_safepoint_end_time_ns
- );
}
-void RuntimeService::record_application_start() {
- // update the time stamp to begin recording app time
- _app_timer.update();
-}
-
-// Don't need to record application end because we currently
-// exit at a safepoint and record_safepoint_begin() handles updating
-// the application time counter at VM exit.
-
jlong RuntimeService::safepoint_sync_time_ms() {
return UsePerfData ?
Management::ticks_to_ms(_sync_time_ticks->get_value()) : -1;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/services/runtimeService.hpp
--- a/src/hotspot/share/services/runtimeService.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/services/runtimeService.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -35,12 +35,6 @@
static PerfCounter* _safepoint_time_ticks; // Accumulated time at safepoints
static PerfCounter* _application_time_ticks; // Accumulated time not at safepoints
- static TimeStamp _safepoint_timer;
- static TimeStamp _app_timer;
- static jlong _last_safepoint_sync_time_ns;
- static jlong _last_safepoint_end_time_ns;
- static jlong _last_app_time_ns;
-
public:
static void init();
@@ -50,12 +44,9 @@
static jlong application_time_ms();
// callbacks
- static void record_safepoint_begin() NOT_MANAGEMENT_RETURN;
- static void record_safepoint_synchronized() NOT_MANAGEMENT_RETURN;
- static void record_safepoint_end() NOT_MANAGEMENT_RETURN;
- static void record_safepoint_epilog(const char* operation_name) NOT_MANAGEMENT_RETURN;
- static void record_application_start() NOT_MANAGEMENT_RETURN;
-
+ static void record_safepoint_begin(jlong app_ticks) NOT_MANAGEMENT_RETURN;
+ static void record_safepoint_synchronized(jlong sync_ticks) NOT_MANAGEMENT_RETURN;
+ static void record_safepoint_end(jlong safepoint_ticks) NOT_MANAGEMENT_RETURN;
};
#endif // SHARE_SERVICES_RUNTIMESERVICE_HPP
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/utilities/events.cpp
--- a/src/hotspot/share/utilities/events.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/utilities/events.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -36,7 +36,7 @@
EventLog* Events::_logs = NULL;
StringEventLog* Events::_messages = NULL;
-ExtendedStringEventLog* Events::_exceptions = NULL;
+ExceptionsEventLog* Events::_exceptions = NULL;
StringEventLog* Events::_redefinitions = NULL;
UnloadingEventLog* Events::_class_unloading = NULL;
StringEventLog* Events::_deopt_messages = NULL;
@@ -67,7 +67,7 @@
void Events::init() {
if (LogEvents) {
_messages = new StringEventLog("Events");
- _exceptions = new ExtendedStringEventLog("Internal exceptions");
+ _exceptions = new ExceptionsEventLog("Internal exceptions");
_redefinitions = new StringEventLog("Classes redefined");
_class_unloading = new UnloadingEventLog("Classes unloaded");
_deopt_messages = new StringEventLog("Deoptimization events");
@@ -112,3 +112,20 @@
st.print("Unloading class " INTPTR_FORMAT " ", p2i(ik));
ik->name()->print_value_on(&st);
}
+
+void ExceptionsEventLog::log(Thread* thread, Handle h_exception, const char* message, const char* file, int line) {
+ if (!should_log()) return;
+
+ double timestamp = fetch_timestamp();
+ MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
+ int index = compute_log_index();
+ _records[index].thread = thread;
+ _records[index].timestamp = timestamp;
+ stringStream st = _records[index].data.stream();
+ st.print("Exception <");
+ h_exception->print_value_on(&st);
+ st.print("%s%s> (" INTPTR_FORMAT ") \n"
+ "thrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
+ message ? ": " : "", message ? message : "",
+ p2i(h_exception()), file, line, p2i(thread));
+}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/utilities/events.hpp
--- a/src/hotspot/share/utilities/events.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/utilities/events.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -183,6 +183,14 @@
void log(Thread* thread, InstanceKlass* ik);
};
+// Event log for exceptions
+class ExceptionsEventLog : public ExtendedStringEventLog {
+ public:
+ ExceptionsEventLog(const char* name, int count = LogEventsBufferEntries) : ExtendedStringEventLog(name, count) {}
+
+ void log(Thread* thread, Handle h_exception, const char* message, const char* file, int line);
+};
+
class Events : AllStatic {
friend class EventLog;
@@ -195,7 +203,7 @@
// A log for internal exception related messages, like internal
// throws and implicit exceptions.
- static ExtendedStringEventLog* _exceptions;
+ static ExceptionsEventLog* _exceptions;
// Deoptization related messages
static StringEventLog* _deopt_messages;
@@ -216,6 +224,7 @@
// Log exception related message
static void log_exception(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
+ static void log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line);
static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
@@ -245,6 +254,12 @@
}
}
+inline void Events::log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line) {
+ if (LogEvents) {
+ _exceptions->log(thread, h_exception, message, file, line);
+ }
+}
+
inline void Events::log_redefinition(Thread* thread, const char* format, ...) {
if (LogEvents) {
va_list ap;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/utilities/exceptions.cpp
--- a/src/hotspot/share/utilities/exceptions.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/utilities/exceptions.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -131,15 +131,17 @@
}
void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception, const char* message) {
- ResourceMark rm;
+ ResourceMark rm(thread);
assert(h_exception() != NULL, "exception should not be NULL");
// tracing (do this up front - so it works during boot strapping)
+ // Note, the print_value_string() argument is not called unless logging is enabled!
log_info(exceptions)("Exception <%s%s%s> (" INTPTR_FORMAT ") \n"
"thrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
h_exception->print_value_string(),
message ? ": " : "", message ? message : "",
p2i(h_exception()), file, line, p2i(thread));
+
// for AbortVMOnException flag
Exceptions::debug_check_abort(h_exception, message);
@@ -162,11 +164,7 @@
thread->set_pending_exception(h_exception(), file, line);
// vm log
- if (LogEvents){
- Events::log_exception(thread, "Exception <%s%s%s> (" INTPTR_FORMAT ") thrown at [%s, line %d]",
- h_exception->print_value_string(), message ? ": " : "", message ? message : "",
- p2i(h_exception()), file, line);
- }
+ Events::log_exception(thread, h_exception, message, file, line);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/utilities/globalDefinitions.hpp
--- a/src/hotspot/share/utilities/globalDefinitions.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -165,29 +165,18 @@
// Size of a char[] needed to represent a jint as a string in decimal.
const int jintAsStringSize = 12;
-// An opaque struct of heap-word width, so that HeapWord* can be a generic
-// pointer into the heap. We require that object sizes be measured in
-// units of heap words, so that that
-// HeapWord* hw;
+// An opaque type, so that HeapWord* can be a generic pointer into the heap.
+// We require that object sizes be measured in units of heap words (e.g.
+// pointer-sized values), so that given HeapWord* hw,
// hw += oop(hw)->foo();
// works, where foo is a method (like size or scavenge) that returns the
// object size.
-class HeapWord {
- friend class VMStructs;
- private:
- char* i;
-#ifndef PRODUCT
- public:
- char* value() { return i; }
-#endif
-};
+class HeapWordImpl; // Opaque, never defined.
+typedef HeapWordImpl* HeapWord;
-// Analogous opaque struct for metadata allocated from
-// metaspaces.
-class MetaWord {
- private:
- char* i;
-};
+// Analogous opaque struct for metadata allocated from metaspaces.
+class MetaWordImpl; // Opaque, never defined.
+typedef MetaWordImpl* MetaWord;
// HeapWordSize must be 2^LogHeapWordSize.
const int HeapWordSize = sizeof(HeapWord);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/hotspot/share/utilities/xmlstream.cpp
--- a/src/hotspot/share/utilities/xmlstream.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/hotspot/share/utilities/xmlstream.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -353,11 +353,15 @@
guarantee(format_len + 10 < sizeof(buffer), "bigger format buffer");
const char* kind = format;
const char* kind_end = strchr(kind, ' ');
- size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : format_len;
- strncpy(buffer, kind, kind_len);
- strcpy(buffer + kind_len, "_done");
+ size_t kind_len;
if (kind_end != NULL) {
- strncat(buffer, format + kind_len, sizeof(buffer) - (kind_len + 5 /* _done */) - 1);
+ kind_len = kind_end - kind;
+ int n = snprintf(buffer, sizeof(buffer), "%.*s_done", (int)kind_len, kind);
+ assert((size_t)n < sizeof(buffer), "Unexpected number of characters in string");
+ } else {
+ kind_len = format_len;
+ int n = snprintf(buffer, sizeof(buffer), "%s_done%s", kind, kind + kind_len);
+ assert((size_t)n < sizeof(buffer), "Unexpected number of characters in string");
}
// Output the trailing event with the timestamp.
va_begin_elem(buffer, ap);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/java/nio/Bits.java
--- a/src/java.base/share/classes/java/nio/Bits.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/java/nio/Bits.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -172,7 +172,10 @@
}
// no luck
- throw new OutOfMemoryError("Direct buffer memory");
+ throw new OutOfMemoryError
+ ("Cannot reserve "
+ + size + " bytes of direct buffer memory (allocated: "
+ + RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")");
} finally {
if (interrupted) {
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
import java.io.FileDescriptor;
import java.lang.ref.Reference;
+import java.util.Objects;
import jdk.internal.misc.VM;
import jdk.internal.ref.Cleaner;
import sun.nio.ch.DirectBuffer;
@@ -325,6 +326,40 @@
#end[rw]
}
+ public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
+#if[rw]
+ if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, dst.length);
+
+ long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+ try {
+#if[!byte]
+ if (order() != ByteOrder.nativeOrder())
+ UNSAFE.copySwapMemory(null,
+ ix(index),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
+ else
+#end[!byte]
+ UNSAFE.copyMemory(null,
+ ix(index),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$);
+ } finally {
+ Reference.reachabilityFence(this);
+ }
+ } else {
+ super.get(index, dst, offset, length);
+ }
+ return this;
+#else[rw]
+ throw new ReadOnlyBufferException();
+#end[rw]
+ }
#end[rw]
public $Type$Buffer put($type$ x) {
@@ -440,6 +475,42 @@
#end[rw]
}
+ public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
+#if[rw]
+ if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, src.length);
+
+
+ long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+ try {
+#if[!byte]
+ if (order() != ByteOrder.nativeOrder())
+ UNSAFE.copySwapMemory(src,
+ srcOffset,
+ null,
+ ix(index),
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
+ else
+#end[!byte]
+ UNSAFE.copyMemory(src,
+ srcOffset,
+ null,
+ ix(index),
+ (long)length << $LG_BYTES_PER_VALUE$);
+ } finally {
+ Reference.reachabilityFence(this);
+ }
+ } else {
+ super.put(index, src, offset, length);
+ }
+ return this;
+#else[rw]
+ throw new ReadOnlyBufferException();
+#end[rw]
+ }
+
public $Type$Buffer compact() {
#if[rw]
int pos = position();
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template
--- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,8 @@
#end[rw]
*/
+import java.util.Objects;
+
class Heap$Type$Buffer$RW$
extends {#if[ro]?Heap}$Type$Buffer
{
@@ -181,6 +183,13 @@
return this;
}
+ public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, dst.length);
+ System.arraycopy(hb, ix(index), dst, offset, length);
+ return this;
+ }
+
public boolean isDirect() {
return false;
}
@@ -250,6 +259,36 @@
#end[rw]
}
+ public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
+#if[rw]
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, src.length);
+ System.arraycopy(src, offset, hb, ix(index), length);
+ return this;
+#else[rw]
+ throw new ReadOnlyBufferException();
+#end[rw]
+ }
+
+#if[char]
+
+ public $Type$Buffer put(String src, int start, int end) {
+ int length = end - start;
+ checkBounds(start, length, src.length());
+ if (isReadOnly())
+ throw new ReadOnlyBufferException();
+ int pos = position();
+ int lim = limit();
+ int rem = (pos <= lim) ? lim - pos : 0;
+ if (length > rem)
+ throw new BufferOverflowException();
+ src.getChars(start, end, hb, ix(pos));
+ position(pos + length);
+ return this;
+ }
+
+#end[char]
+
public $Type$Buffer compact() {
#if[rw]
System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/java/nio/X-Buffer.java.template
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
import java.util.stream.$Streamtype$Stream;
#end[streamableType]
+import java.util.Objects;
import jdk.internal.util.ArraysSupport;
/**
@@ -50,11 +51,11 @@
* {@link #put($type$) put} methods that read and write
* single $type$s;
*
- *
Relative {@link #get($type$[]) bulk get}
+ *
Absolute and relative {@link #get($type$[]) bulk get}
* methods that transfer contiguous sequences of $type$s from this buffer
* into an array; {#if[!byte]?and}
*
- *
Relative {@link #put($type$[]) bulk put}
+ *
Absolute and relative {@link #put($type$[]) bulk put}
* methods that transfer contiguous sequences of $type$s from $a$
* $type$ array{#if[char]?, a string,} or some other $type$
* buffer into this buffer;{#if[!byte]? and}
@@ -209,6 +210,8 @@
*
This class implements the {@link CharSequence} interface so that
* character buffers may be used wherever character sequences are accepted, for
* example in the regular-expression package {@link java.util.regex}.
+ * The methods defined by {@code CharSequence} operate relative to the current
+ * position of the buffer when they are invoked.
*
*
#end[char]
@@ -434,7 +437,6 @@
* @return The number of characters added to the buffer, or
* -1 if this source of characters is at its end
* @throws IOException if an I/O error occurs
- * @throws NullPointerException if target is null
* @throws ReadOnlyBufferException if target is a read only buffer
* @since 1.5
*/
@@ -762,6 +764,89 @@
return get(dst, 0, dst.length);
}
+ /**
+ * Absolute bulk get method.
+ *
+ *
This method transfers {@code length} $type$s from this
+ * buffer into the given array, starting at the given index in this
+ * buffer and at the given offset in the array. The position of this
+ * buffer is unchanged.
+ *
+ *
An invocation of this method of the form
+ * src.get(index, dst, offset, length)
+ * has exactly the same effect as the following loop except that it first
+ * checks the consistency of the supplied parameters and it is potentially
+ * much more efficient:
+ *
+ *
{@code
+ * for (int i = offset, j = index; i < offset + length; i++, j++)
+ * dst[i] = src.get(j);
+ * }
+ *
+ * @param index
+ * The index in this buffer from which the first $type$ will be
+ * read; must be non-negative and less than {@code limit()}
+ *
+ * @param dst
+ * The destination array
+ *
+ * @param offset
+ * The offset within the array of the first $type$ to be
+ * written; must be non-negative and less than
+ * {@code dst.length}
+ *
+ * @param length
+ * The number of $type$s to be written to the given array;
+ * must be non-negative and no larger than the smaller of
+ * {@code limit() - index} and {@code dst.length - offset}
+ *
+ * @return This buffer
+ *
+ * @throws IndexOutOfBoundsException
+ * If the preconditions on the {@code index}, {@code offset}, and
+ * {@code length} parameters do not hold
+ *
+ * @since 13
+ */
+ public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, dst.length);
+ int end = offset + length;
+ for (int i = offset, j = index; i < end; i++, j++)
+ dst[i] = get(j);
+ return this;
+ }
+
+ /**
+ * Absolute bulk get method.
+ *
+ *
This method transfers $type$s from this buffer into the given
+ * destination array. The position of this buffer is unchanged. An
+ * invocation of this method of the form
+ * src.get(index, dst) behaves in exactly the same
+ * way as the invocation:
+ *
+ *
+ * src.get(index, dst, 0, dst.length)
+ *
+ * @param index
+ * The index in this buffer from which the first $type$ will be
+ * read; must be non-negative and less than {@code limit()}
+ *
+ * @param dst
+ * The destination array
+ *
+ * @return This buffer
+ *
+ * @throws IndexOutOfBoundsException
+ * If {@code index} is negative, not smaller than {@code limit()},
+ * or {@code limit() - index < dst.length}
+ *
+ * @since 13
+ */
+ public $Type$Buffer get(int index, $type$[] dst) {
+ return get(index, dst, 0, dst.length);
+ }
// -- Bulk put operations --
@@ -840,7 +925,7 @@
*
*
{@code
* for (int i = off; i < off + len; i++)
- * dst.put(a[i]);
+ * dst.put(src[i]);
* }
*
* except that it first checks that there is sufficient space in this
@@ -851,12 +936,12 @@
*
* @param offset
* The offset within the array of the first $type$ to be read;
- * must be non-negative and no larger than {@code array.length}
+ * must be non-negative and no larger than {@code src.length}
*
* @param length
* The number of $type$s to be read from the given array;
* must be non-negative and no larger than
- * {@code array.length - offset}
+ * {@code src.length - offset}
*
* @return This buffer
*
@@ -906,6 +991,95 @@
return put(src, 0, src.length);
}
+ /**
+ * Absolute bulk put method (optional operation).
+ *
+ *
This method transfers {@code length} $type$s from the given
+ * array, starting at the given offset in the array and at the given index
+ * in this buffer. The position of this buffer is unchanged.
+ *
+ *
An invocation of this method of the form
+ * dst.put(index, src, offset, length)
+ * has exactly the same effect as the following loop except that it first
+ * checks the consistency of the supplied parameters and it is potentially
+ * much more efficient:
+ *
+ *
{@code
+ * for (int i = offset, j = index; i < offset + length; i++, j++)
+ * dst.put(j, src[i]);
+ * }
+ *
+ * @param index
+ * The index in this buffer at which the first $type$ will be
+ * written; must be non-negative and less than {@code limit()}
+ *
+ * @param src
+ * The array from which $type$s are to be read
+ *
+ * @param offset
+ * The offset within the array of the first $type$ to be read;
+ * must be non-negative and less than {@code src.length}
+ *
+ * @param length
+ * The number of $type$s to be read from the given array;
+ * must be non-negative and no larger than the smaller of
+ * {@code limit() - index} and {@code src.length - offset}
+ *
+ * @return This buffer
+ *
+ * @throws IndexOutOfBoundsException
+ * If the preconditions on the {@code index}, {@code offset}, and
+ * {@code length} parameters do not hold
+ *
+ * @throws ReadOnlyBufferException
+ * If this buffer is read-only
+ *
+ * @since 13
+ */
+ public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
+ if (isReadOnly())
+ throw new ReadOnlyBufferException();
+ Objects.checkFromIndexSize(index, length, limit());
+ Objects.checkFromIndexSize(offset, length, src.length);
+ int end = offset + length;
+ for (int i = offset, j = index; i < end; i++, j++)
+ this.put(j, src[i]);
+ return this;
+ }
+
+ /**
+ * Absolute bulk put method (optional operation).
+ *
+ *
This method copies $type$s into this buffer from the given source
+ * array. The position of this buffer is unchanged. An invocation of this
+ * method of the form dst.put(index, src)
+ * behaves in exactly the same way as the invocation:
+ *
+ *
+ * dst.put(index, src, 0, src.length);
+ *
+ * @param index
+ * The index in this buffer at which the first $type$ will be
+ * written; must be non-negative and less than {@code limit()}
+ *
+ * @param src
+ * The array from which $type$s are to be read
+ *
+ * @return This buffer
+ *
+ * @throws IndexOutOfBoundsException
+ * If {@code index} is negative, not smaller than {@code limit()},
+ * or {@code limit() - index < src.length}
+ *
+ * @throws ReadOnlyBufferException
+ * If this buffer is read-only
+ *
+ * @since 13
+ */
+ public $Type$Buffer put(int index, $type$[] src) {
+ return put(index, src, 0, src.length);
+ }
+
#if[char]
/**
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/security/ssl/ClientHello.java
--- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java Fri Feb 22 20:36:42 2019 +0000
@@ -803,13 +803,8 @@
shc.sslConfig.getEnabledExtensions(
SSLHandshake.CLIENT_HELLO);
- ClientHelloMessage chm;
- try {
- chm = new ClientHelloMessage(shc, message, enabledExtensions);
- } catch (Exception e) {
- throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
- "ClientHelloMessage failure", e);
- }
+ ClientHelloMessage chm =
+ new ClientHelloMessage(shc, message, enabledExtensions);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine("Consuming ClientHello handshake message", chm);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/security/ssl/HandshakeContext.java
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
package sun.security.ssl;
import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
@@ -443,6 +445,10 @@
throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
"Unsupported handshake message: " +
SSLHandshake.nameOf(handshakeType), unsoe);
+ } catch (BufferUnderflowException | BufferOverflowException be) {
+ throw conContext.fatal(Alert.DECODE_ERROR,
+ "Illegal handshake message: " +
+ SSLHandshake.nameOf(handshakeType), be);
}
// update handshake hash after handshake message consumption.
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java
--- a/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
package sun.security.ssl;
import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -74,6 +76,10 @@
throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
"Unsupported post-handshake message: " +
SSLHandshake.nameOf(handshakeType), unsoe);
+ } catch (BufferUnderflowException | BufferOverflowException be) {
+ throw conContext.fatal(Alert.DECODE_ERROR,
+ "Illegal handshake message: " +
+ SSLHandshake.nameOf(handshakeType), be);
}
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
--- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Fri Feb 22 20:36:42 2019 +0000
@@ -921,29 +921,45 @@
static {
Exception reserved = null;
- TrustManager[] tmMediator;
+ TrustManager[] tmMediator = null;
try {
tmMediator = getTrustManagers();
} catch (Exception e) {
reserved = e;
- tmMediator = new TrustManager[0];
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+ SSLLogger.warning(
+ "Failed to load default trust managers", e);
+ }
}
- trustManagers = tmMediator;
+ KeyManager[] kmMediator = null;
if (reserved == null) {
- KeyManager[] kmMediator;
try {
kmMediator = getKeyManagers();
} catch (Exception e) {
reserved = e;
- kmMediator = new KeyManager[0];
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+ SSLLogger.warning(
+ "Failed to load default key managers", e);
+ }
}
- keyManagers = kmMediator;
- } else {
- keyManagers = new KeyManager[0];
}
- reservedException = reserved;
+ if (reserved != null) {
+ trustManagers = new TrustManager[0];
+ keyManagers = new KeyManager[0];
+
+ // Important note: please don't reserve the original exception
+ // object, which may be not garbage collection friendly as
+ // 'reservedException' is a static filed.
+ reservedException =
+ new KeyManagementException(reserved.getMessage());
+ } else {
+ trustManagers = tmMediator;
+ keyManagers = kmMediator;
+
+ reservedException = null;
+ }
}
private static TrustManager[] getTrustManagers() throws Exception {
@@ -1071,21 +1087,30 @@
private static final class DefaultSSLContextHolder {
private static final SSLContextImpl sslContext;
- static Exception reservedException = null;
+ private static final Exception reservedException;
static {
+ Exception reserved = null;
SSLContextImpl mediator = null;
if (DefaultManagersHolder.reservedException != null) {
- reservedException = DefaultManagersHolder.reservedException;
+ reserved = DefaultManagersHolder.reservedException;
} else {
try {
mediator = new DefaultSSLContext();
} catch (Exception e) {
- reservedException = e;
+ // Important note: please don't reserve the original
+ // exception object, which may be not garbage collection
+ // friendly as 'reservedException' is a static filed.
+ reserved = new KeyManagementException(e.getMessage());
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
+ SSLLogger.warning(
+ "Failed to load default SSLContext", e);
+ }
}
}
sslContext = mediator;
+ reservedException = reserved;
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/security/x509/CertificateExtensions.java
--- a/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -355,7 +355,7 @@
class UnparseableExtension extends Extension {
private String name;
- private Throwable why;
+ private String exceptionDescription;
public UnparseableExtension(Extension ext, Throwable why) {
super(ext);
@@ -371,12 +371,13 @@
// If we cannot find the name, just ignore it
}
- this.why = why;
+ this.exceptionDescription = why.toString();
}
@Override public String toString() {
return super.toString() +
- "Unparseable " + name + "extension due to\n" + why + "\n\n" +
+ "Unparseable " + name + "extension due to\n" +
+ exceptionDescription + "\n\n" +
new HexDumpEncoder().encodeBuffer(getExtensionValue());
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/util/cldr/CLDRCalendarDataProviderImpl.java
--- a/src/java.base/share/classes/sun/util/cldr/CLDRCalendarDataProviderImpl.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/util/cldr/CLDRCalendarDataProviderImpl.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,8 @@
String region = locale.getCountry();
if (region.isEmpty()) {
- return 0;
+ // Use "US" as default
+ region = "US";
}
Integer val = map.get(region);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java
--- a/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -256,7 +256,9 @@
default:
throw new InternalError("invalid requestID: " + requestID);
}
- return (value != 0) ? value : null;
+
+ assert value != 0;
+ return value;
}
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -283,8 +283,8 @@
return providersObj;
} else if (isObjectProvider) {
config(LocaleServiceProviderPool.class,
- "A locale sensitive service provider returned null for a localized objects, which should not happen. provider: "
- + lsp + " locale: " + locale);
+ "A locale sensitive service object provider returned null, " +
+ "which should not happen. Provider: " + lsp + " Locale: " + locale);
}
}
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/native/libjimage/imageFile.cpp
--- a/src/java.base/share/native/libjimage/imageFile.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/native/libjimage/imageFile.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -481,65 +481,6 @@
return 0; // not found
}
-// Assemble the location path from the string fragments indicated in the location attributes.
-void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const {
- // Manage the image string table.
- ImageStrings strings(_string_bytes, _header.strings_size(_endian));
- // Position to first character of the path buffer.
- char* next = path;
- // Temp for string length.
- size_t length;
- // Get module string.
- const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
- // If module string is not empty string.
- if (*module != '\0') {
- // Get length of module name.
- length = strlen(module);
- // Make sure there is no buffer overflow.
- assert(next - path + length + 2 < max && "buffer overflow");
- // Append '/module/'.
- *next++ = '/';
- strncpy(next, module, length); next += length;
- *next++ = '/';
- }
- // Get parent (package) string.
- const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
- // If parent string is not empty string.
- if (*parent != '\0') {
- // Get length of module string.
- length = strlen(parent);
- // Make sure there is no buffer overflow.
- assert(next - path + length + 1 < max && "buffer overflow");
- // Append 'patent/' .
- strncpy(next, parent, length); next += length;
- *next++ = '/';
- }
- // Get base name string.
- const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
- // Get length of base name.
- length = strlen(base);
- // Make sure there is no buffer overflow.
- assert(next - path + length < max && "buffer overflow");
- // Append base name.
- strncpy(next, base, length); next += length;
- // Get extension string.
- const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
- // If extension string is not empty string.
- if (*extension != '\0') {
- // Get length of extension string.
- length = strlen(extension);
- // Make sure there is no buffer overflow.
- assert(next - path + length + 1 < max && "buffer overflow");
- // Append '.extension' .
- *next++ = '.';
- strncpy(next, extension, length); next += length;
- }
- // Make sure there is no buffer overflow.
- assert((size_t)(next - path) < max && "buffer overflow");
- // Terminate string.
- *next = '\0';
-}
-
// Verify that a found location matches the supplied path (without copying.)
bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const {
// Manage the image string table.
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/native/libjimage/imageFile.hpp
--- a/src/java.base/share/native/libjimage/imageFile.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/native/libjimage/imageFile.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -564,9 +564,6 @@
// ImageFileReader::NOT_FOUND otherwise.
u4 find_location_index(const char* path, u8 *size) const;
- // Assemble the location path.
- void location_path(ImageLocation& location, char* path, size_t max) const;
-
// Verify that a found location matches the supplied path.
bool verify_location(ImageLocation& location, const char* path) const;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/native/libjimage/jimage.cpp
--- a/src/java.base/share/native/libjimage/jimage.cpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/native/libjimage/jimage.cpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -215,29 +215,3 @@
}
}
}
-
-/*
- * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer
- * and a maximum buffer size, copy the path of the resource into the buffer.
- * Returns false if not a valid location reference.
- *
- * Ex.
- * JImageLocationRef location = ...
- * char path[JIMAGE_MAX_PATH];
- * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
- */
-extern "C" JNIEXPORT bool
-JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
- char* path, size_t max) {
- ImageFileReader* imageFile = (ImageFileReader*) image;
-
- u4 offset = (u4) locationRef;
- if (offset >= imageFile->locations_size()) {
- return false;
- }
-
- ImageLocation location(imageFile->get_location_offset_data(offset));
- imageFile->location_path(location, path, max);
-
- return true;
-}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.base/share/native/libjimage/jimage.hpp
--- a/src/java.base/share/native/libjimage/jimage.hpp Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.base/share/native/libjimage/jimage.hpp Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -191,20 +191,3 @@
typedef void (*JImageResourceIterator_t)(JImageFile* jimage,
JImageResourceVisitor_t visitor, void* arg);
-
-/*
- * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer
- * and a maximum buffer size, copy the path of the resource into the buffer.
- * Returns false if not a valid location reference.
- *
- * Ex.
- * JImageLocationRef location = ...
- * char path[JIMAGE_MAX_PATH];
- * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
- */
-extern "C" JNIEXPORT bool
-JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
- char* path, size_t max);
-
-typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location,
- char* buffer, jlong size);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri Feb 22 20:36:42 2019 +0000
@@ -208,11 +208,13 @@
CImage cimage = CImage.getCreator().createFromImage(image, observer);
boolean imageAutoSize = target.isImageAutoSize();
- cimage.execute(imagePtr -> {
- execute(ptr -> {
- setNativeImage(ptr, imagePtr, imageAutoSize);
+ if (cimage != null) {
+ cimage.execute(imagePtr -> {
+ execute(ptr -> {
+ setNativeImage(ptr, imagePtr, imageAutoSize);
+ });
});
- });
+ }
}
private native void setNativeImage(final long model, final long nsimage, final boolean autosize);
@@ -357,7 +359,7 @@
class IconObserver implements ImageObserver {
@Override
public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) {
- if (image != target.getImage()) // if the image has been changed
+ if (target == null || image != target.getImage()) //if the image has been changed
{
return false;
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Fri Feb 22 20:36:42 2019 +0000
@@ -739,7 +739,8 @@
region == Region.TOOL_BAR_DRAG_WINDOW ||
region == Region.TOOL_TIP ||
region == Region.TREE ||
- region == Region.VIEWPORT) {
+ region == Region.VIEWPORT ||
+ region == Region.TEXT_PANE) {
return true;
}
if (!GTKLookAndFeel.is3()) {
@@ -747,8 +748,7 @@
region == Region.FORMATTED_TEXT_FIELD ||
region == Region.PASSWORD_FIELD ||
region == Region.SPINNER ||
- region == Region.TEXT_FIELD ||
- region == Region.TEXT_PANE) {
+ region == Region.TEXT_FIELD) {
return true;
}
}
@@ -767,6 +767,14 @@
if (classKey != null) {
Object value = getClassSpecificValue(classKey);
if (value != null) {
+ //This is a workaround as the "slider-length" property has been
+ //deprecated for GtkScale from gtk 3.20, so default value of 31
+ //is used and makes redering of slider wrong. Value 14 is being
+ //used as default value for Slider.thumbHeight is 14 and making
+ //width 14 as well makes slider thumb render in proper shape
+ if ("Slider.thumbWidth".equals(key) && value.equals(31)) {
+ return 14;
+ }
return value;
}
}
@@ -779,8 +787,15 @@
return getColorForState(context, ColorType.FOREGROUND);
}
else if (key == "ScrollBar.minimumThumbSize") {
+ //This is a workaround as the "min-slider-length" property has been
+ //deprecated for GtkScrollBar from gtk 3.20, so default value of 21
+ //is used and makes ScrollBar thumb very small. Value 40 is being
+ //used as this is the value mentioned in css files
int len =
getClassSpecificIntValue(context, "min-slider-length", 21);
+ if (len == 21) {
+ len = 40;
+ }
JScrollBar sb = (JScrollBar)context.getComponent();
if (sb.getOrientation() == JScrollBar.HORIZONTAL) {
return new DimensionUIResource(len, 0);
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/java/awt/Font.java
--- a/src/java.desktop/share/classes/java/awt/Font.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/java/awt/Font.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -495,13 +495,7 @@
private Font2D getFont2D() {
FontManager fm = FontManagerFactory.getInstance();
- if (fm.usingPerAppContextComposites() &&
- font2DHandle != null &&
- font2DHandle.font2D instanceof CompositeFont &&
- ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
- return fm.findFont2D(name, style,
- FontManager.LOGICAL_FALLBACK);
- } else if (font2DHandle == null) {
+ if (font2DHandle == null) {
font2DHandle =
fm.findFont2D(name, style,
FontManager.LOGICAL_FALLBACK).handle;
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/sun/awt/AWTSecurityManager.java
--- a/src/java.desktop/share/classes/sun/awt/AWTSecurityManager.java Fri Feb 22 17:03:09 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.awt;
-
-/**
- * The AWTSecurityManager class provides the ability to secondarily
- * index AppContext objects through SecurityManager extensions.
- * As noted in AppContext.java, AppContexts are primarily indexed by
- * ThreadGroup. In the case where the ThreadGroup doesn't provide
- * enough information to determine AppContext (e.g. system threads),
- * if a SecurityManager is installed which derives from
- * AWTSecurityManager, the AWTSecurityManager's getAppContext()
- * method is called to determine the AppContext.
- *
- * A typical example of the use of this class is where an applet
- * is called by a system thread, yet the system AppContext is
- * inappropriate, because applet code is currently executing.
- * In this case, the getAppContext() method can walk the call stack
- * to determine the applet code being executed and return the applet's
- * AppContext object.
- *
- * @author Fred Ecks
- */
-public class AWTSecurityManager extends SecurityManager {
-
- /**
- * Get the AppContext corresponding to the current context.
- * The default implementation returns null, but this method
- * may be overridden by various SecurityManagers
- * (e.g. AppletSecurity) to index AppContext objects by the
- * calling context.
- *
- * @return the AppContext corresponding to the current context.
- * @see sun.awt.AppContext
- * @see java.lang.SecurityManager
- * @since 1.2.1
- */
- public AppContext getAppContext() {
- return null; // Default implementation returns null
- }
-
-} /* class AWTSecurityManager */
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/sun/awt/AppContext.java
--- a/src/java.desktop/share/classes/sun/awt/AppContext.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/sun/awt/AppContext.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -123,17 +123,6 @@
* therefore safely invoke any of its methods without worry of being
* blocked.
*
- * Note: If a SecurityManager is installed which derives from
- * sun.awt.AWTSecurityManager, it may override the
- * AWTSecurityManager.getAppContext() method to return the proper
- * AppContext based on the execution context, in the case where
- * the default ThreadGroup-based AppContext indexing would return
- * the main "system" AppContext. For example, in an applet situation,
- * if a system thread calls into an applet, rather than returning the
- * main "system" AppContext (the one corresponding to the system thread),
- * an installed AWTSecurityManager may return the applet's AppContext
- * based on the execution context.
- *
* @author Thomas Ball
* @author Fred Ecks
*/
@@ -287,10 +276,7 @@
/**
* Returns the appropriate AppContext for the caller,
- * as determined by its ThreadGroup. If the main "system" AppContext
- * would be returned and there's an AWTSecurityManager installed, it
- * is called to get the proper AppContext based on the execution
- * context.
+ * as determined by its ThreadGroup.
*
* @return the AppContext for the caller.
* @see java.lang.ThreadGroup
@@ -384,18 +370,6 @@
return (ctx != null && ctx == mainAppContext);
}
- private static AppContext getExecutionAppContext() {
- SecurityManager securityManager = System.getSecurityManager();
- if ((securityManager != null) &&
- (securityManager instanceof AWTSecurityManager))
- {
- AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
- AppContext secAppContext = awtSecMgr.getAppContext();
- return secAppContext; // Return what we're told
- }
- return null;
- }
-
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
// for disposal of all Frames
// (we wait for this time twice,
@@ -872,8 +846,7 @@
// context since we don't need it.
if (numAppContexts.get() == 0) return null;
- // Get the context from the security manager
- AppContext ecx = getExecutionAppContext();
+ AppContext ecx = null;
// Not sure we really need to re-check numAppContexts here.
// If all applets have gone away then we could have a
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/sun/font/FontDesignMetrics.java
--- a/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,22 +25,18 @@
package sun.font;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-
+import java.awt.Font;
import java.awt.FontMetrics;
-import java.awt.Font;
import java.awt.GraphicsEnvironment;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Rectangle2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
-
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
import java.util.concurrent.ConcurrentHashMap;
import sun.java2d.Disposer;
@@ -263,7 +259,7 @@
* by this code as they use the metrics of the physical anyway.
*/
SunFontManager fm = SunFontManager.getInstance();
- if (fm.maybeUsingAlternateCompositeFonts() &&
+ if (fm.usingAlternateCompositeFonts() &&
FontUtilities.getFont2D(font) instanceof CompositeFont) {
return new FontDesignMetrics(font, frc);
}
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/sun/font/FontManager.java
--- a/src/java.desktop/share/classes/sun/font/FontManager.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/sun/font/FontManager.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package sun.font;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
-import java.util.Locale;
-import java.util.TreeMap;
-
-import javax.swing.plaf.FontUIResource;
-
/**
* Interface between Java Fonts (java.awt.Font) and the underlying
@@ -93,13 +89,6 @@
throws FontFormatException;
/**
- * If usingPerAppContextComposites is true, we are in "applet"
- * (eg browser) environment and at least one context has selected
- * an alternate composite font behaviour.
- */
- public boolean usingPerAppContextComposites();
-
- /**
* Creates a derived composite font from the specified font (handle).
*
* @param family the font family of the derived font
diff -r 30695f27d7ea -r 7a45c67e73d0 src/java.desktop/share/classes/sun/font/SunFontManager.java
--- a/src/java.desktop/share/classes/sun/font/SunFontManager.java Fri Feb 22 17:03:09 2019 +0000
+++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java Fri Feb 22 20:36:42 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.plaf.FontUIResource;
-import sun.awt.AppContext;
+
import sun.awt.FontConfiguration;
import sun.awt.SunToolkit;
import sun.awt.util.ThreadGroupUtils;
@@ -256,11 +256,6 @@
return t1Filter;
}
- @Override
- public boolean usingPerAppContextComposites() {
- return _usingPerAppContextComposites;
- }
-
static {
java.security.AccessController.doPrivileged(
@@ -1936,7 +1931,6 @@
public Font2D findFont2D(String name, int style, int fallback) {
String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
String mapName = lowerCaseName + dotStyleStr(style);
- Font2D font;
/* If preferLocaleFonts() or preferProportionalFonts() has been
* called we may be using an alternate set of composite fonts in this
@@ -1944,19 +1938,7 @@
* this is so, and gives access to the alternate composite for the
* name.
*/
- if (_usingPerAppContextComposites) {
- @SuppressWarnings("unchecked")
- ConcurrentHashMap altNameCache =
- (ConcurrentHashMap)
- AppContext.getAppContext().get(CompositeFont.class);
- if (altNameCache != null) {
- font = altNameCache.get(mapName);
- } else {
- font = null;
- }
- } else {
- font = fontNameCache.get(mapName);
- }
+ Font2D font = fontNameCache.get(mapName);
if (font != null) {
return font;
}
@@ -2161,25 +2143,9 @@
* cache for these.
*/
- if (fontsAreRegistered || fontsAreRegisteredPerAppContext) {
- Hashtable familyTable = null;
- Hashtable nameTable;
-
- if (fontsAreRegistered) {
- familyTable = createdByFamilyName;
- nameTable = createdByFullName;
- } else {
- AppContext appContext = AppContext.getAppContext();
- @SuppressWarnings("unchecked")
- Hashtable tmp1 =
- (Hashtable)appContext.get(regFamilyKey);
- familyTable = tmp1;
-
- @SuppressWarnings("unchecked")
- Hashtable tmp2 =
- (Hashtable)appContext.get(regFullNameKey);
- nameTable = tmp2;
- }
+ if (fontsAreRegistered) {
+ Hashtable familyTable = createdByFamilyName;
+ Hashtable nameTable = createdByFullName;
family = familyTable.get(lowerCaseName);
if (family != null) {
@@ -2684,9 +2650,6 @@
* Calling the methods below is "heavyweight" but it is expected that
* these methods will be called very rarely.
*
- * If _usingPerAppContextComposites is true, we are in "applet"
- * (eg browser) environment and at least one context has selected
- * an alternate composite font behaviour.
* If _usingAlternateComposites is true, we are not in an "applet"
* environment and the (single) application has selected
* an alternate composite font behaviour.
@@ -2698,21 +2661,13 @@
* but that may have to wait. The results should be correct, just not
* optimal.
*/
- private static final Object altJAFontKey = new Object();
- private static final Object localeFontKey = new Object();
- private static final Object proportionalFontKey = new Object();
- private boolean _usingPerAppContextComposites = false;
private boolean _usingAlternateComposites = false;
- /* These values are used only if we are running as a standalone
- * application, as determined by maybeMultiAppContext();
- */
private static boolean gAltJAFont = false;
private boolean gLocalePref = false;
private boolean gPropPref = false;
- /* This method doesn't check if alternates are selected in this app
- * context. Its used by the FontMetrics caching code which in such
+ /* Its used by the FontMetrics caching code which in such
* a case cannot retrieve a cached metrics solely on the basis of
* the Font.equals() method since it needs to also check if the Font2D
* is the same.
@@ -2724,26 +2679,8 @@
* logical font definitions we may need to revisit this if GTK reports
* combined metrics instead. For now though this test can be simple.
*/
- public boolean maybeUsingAlternateCompositeFonts() {
- return _usingAlternateComposites || _usingPerAppContextComposites;
- }
-
public boolean usingAlternateCompositeFonts() {
- return (_usingAlternateComposites ||
- (_usingPerAppContextComposites &&
- AppContext.getAppContext().get(CompositeFont.class) != null));
- }
-
- private static boolean maybeMultiAppContext() {
- Boolean appletSM = (Boolean)
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction