Merge
This commit is contained in:
commit
7f9a1c0889
1
.hgtags
1
.hgtags
@ -554,3 +554,4 @@ b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga
|
||||
46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14
|
||||
f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15
|
||||
9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16
|
||||
93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17
|
||||
|
@ -180,15 +180,15 @@
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Linux</td>
|
||||
<td style="text-align: left;">Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13)</td>
|
||||
<td style="text-align: left;">Oracle Enterprise Linux 6.4 / 7.6</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">Solaris</td>
|
||||
<td style="text-align: left;">Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5</td>
|
||||
<td style="text-align: left;">Solaris 11.3</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">macOS</td>
|
||||
<td style="text-align: left;">Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite)</td>
|
||||
<td style="text-align: left;">Mac OS X 10.13 (High Sierra)</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">Windows</td>
|
||||
@ -196,7 +196,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The double version numbers for Linux, Solaris and macOS is due to the hybrid model used at Oracle, where header files and external libraries from an older version are used when building on a more modern version of the OS.</p>
|
||||
<p>The double version numbers for Linux and Solaris are due to the hybrid model used at Oracle, where header files and external libraries from an older version are used when building on a more modern version of the OS.</p>
|
||||
<p>The Build Group has a wiki page with <a href="https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms">Supported Build Platforms</a>. From time to time, this is updated by contributors to list successes or failures of building on different platforms.</p>
|
||||
<h3 id="windows">Windows</h3>
|
||||
<p>Windows XP is not a supported platform, but all newer Windows should be able to build the JDK.</p>
|
||||
@ -281,19 +281,19 @@
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Linux</td>
|
||||
<td style="text-align: left;">gcc 7.3.0</td>
|
||||
<td style="text-align: left;">gcc 8.2.0</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">macOS</td>
|
||||
<td style="text-align: left;">Apple Xcode 9.4 (using clang 9.1.0)</td>
|
||||
<td style="text-align: left;">Apple Xcode 10.1 (using clang 10.0.0)</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Solaris</td>
|
||||
<td style="text-align: left;">Oracle Solaris Studio 12.4 (with compiler version 5.13)</td>
|
||||
<td style="text-align: left;">Oracle Solaris Studio 12.6 (with compiler version 5.15)</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">Windows</td>
|
||||
<td style="text-align: left;">Microsoft Visual Studio 2017 update 15.5.5</td>
|
||||
<td style="text-align: left;">Microsoft Visual Studio 2017 update 15.9.6</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -150,14 +150,14 @@ time of writing.
|
||||
|
||||
Operating system Vendor/version used
|
||||
----------------- -------------------------------------------------------
|
||||
Linux Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13)
|
||||
Solaris Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5
|
||||
macOS Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite)
|
||||
Linux Oracle Enterprise Linux 6.4 / 7.6
|
||||
Solaris Solaris 11.3 SRU 20
|
||||
macOS Mac OS X 10.13 (High Sierra)
|
||||
Windows Windows Server 2012 R2
|
||||
|
||||
The double version numbers for Linux, Solaris and macOS is due to the hybrid
|
||||
model used at Oracle, where header files and external libraries from an older
|
||||
version are used when building on a more modern version of the OS.
|
||||
The double version numbers for Linux and Solaris are due to the hybrid model
|
||||
used at Oracle, where header files and external libraries from an older version
|
||||
are used when building on a more modern version of the OS.
|
||||
|
||||
The Build Group has a wiki page with [Supported Build Platforms](
|
||||
https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms). From
|
||||
@ -323,10 +323,10 @@ issues.
|
||||
|
||||
Operating system Toolchain version
|
||||
------------------ -------------------------------------------------------
|
||||
Linux gcc 7.3.0
|
||||
macOS Apple Xcode 9.4 (using clang 9.1.0)
|
||||
Solaris Oracle Solaris Studio 12.4 (with compiler version 5.13)
|
||||
Windows Microsoft Visual Studio 2017 update 15.5.5
|
||||
Linux gcc 8.2.0
|
||||
macOS Apple Xcode 10.1 (using clang 10.0.0)
|
||||
Solaris Oracle Solaris Studio 12.6 (with compiler version 5.15)
|
||||
Windows Microsoft Visual Studio 2017 update 15.9.6
|
||||
|
||||
### gcc
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
</ul></li>
|
||||
<li><a href="#notes-for-specific-tests">Notes for Specific Tests</a><ul>
|
||||
<li><a href="#docker-tests">Docker Tests</a></li>
|
||||
<li><a href="#non-us-locale">Non-US locale</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</nav>
|
||||
@ -191,8 +192,12 @@ TEST FAILURE</code></pre>
|
||||
<h2 id="notes-for-specific-tests">Notes for Specific Tests</h2>
|
||||
<h3 id="docker-tests">Docker Tests</h3>
|
||||
<p>Docker tests with default parameters may fail on systems with glibc versions not compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:</p>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker"</code></pre>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"</code></pre>
|
||||
<p>To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using <code>JAVA_OPTIONS</code>.</p>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"</code></pre>
|
||||
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"</code></pre>
|
||||
<h3 id="non-us-locale">Non-US locale</h3>
|
||||
<p>If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting <code>LANG="en_US"</code> in the environment before running tests should work. On Windows, setting <code>JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"</code> helps for most, but not all test cases. For example:</p>
|
||||
<pre><code>$ export LANG="en_US" && make test TEST=...
|
||||
$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...</code></pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -381,12 +381,23 @@ Docker tests with default parameters may fail on systems with glibc versions not
|
||||
compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86).
|
||||
For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:
|
||||
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker"
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"
|
||||
|
||||
To run these tests correctly, additional parameters for the correct docker image are
|
||||
required on Ubuntu 18.04 by using `JAVA_OPTIONS`.
|
||||
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
|
||||
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
|
||||
|
||||
### Non-US locale
|
||||
|
||||
If your locale is non-US, some tests are likely to fail. To work around this you can
|
||||
set the locale to US. On Unix platforms simply setting `LANG="en_US"` in the
|
||||
environment before running tests should work. On Windows, setting
|
||||
`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but not all test cases.
|
||||
For example:
|
||||
|
||||
$ export LANG="en_US" && make test TEST=...
|
||||
$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...
|
||||
|
||||
---
|
||||
# Override some definitions in the global css file that are not optimal for
|
||||
|
@ -49,6 +49,7 @@ $(JCOV_IMAGE_DIR)/release: $(JCOV_INPUT_IMAGE_DIR)/release
|
||||
-exclude 'java.lang.Object' \
|
||||
-exclude 'jdk.internal.org.objectweb.**' \
|
||||
-exclude jdk.test.Main -exclude '**\$Proxy*' \
|
||||
$(JCOV_FILTERS) \
|
||||
$(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR)
|
||||
$(MV) $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR) $(JCOV_IMAGE_DIR)
|
||||
$(RMDIR) $(JCOV_TEMP)
|
||||
|
@ -1194,10 +1194,18 @@ ifeq ($(TEST_OPTS_JCOV), true)
|
||||
$(call LogWarn, Stopping JCov Grabber...)
|
||||
$(JAVA) -jar $(JCOV_HOME)/lib/jcov.jar GrabberManager -stop -stoptimeout 3600
|
||||
|
||||
JCOV_REPORT_TITLE := JDK code coverage report<br/>
|
||||
ifneq ($(JCOV_FILTERS), )
|
||||
JCOV_REPORT_TITLE += Code filters: $(JCOV_FILTERS)<br>
|
||||
endif
|
||||
JCOV_REPORT_TITLE += Tests: $(TEST)
|
||||
|
||||
jcov-gen-report: jcov-stop-grabber
|
||||
$(call LogWarn, Generating JCov report ...)
|
||||
$(JAVA) -Xmx4g -jar $(JCOV_HOME)/lib/jcov.jar RepGen -sourcepath \
|
||||
`$(ECHO) $(TOPDIR)/src/*/share/classes/ | $(TR) ' ' ':'` -fmt html \
|
||||
$(JCOV_FILTERS) \
|
||||
-mainReportTitle "$(JCOV_REPORT_TITLE)" \
|
||||
-o $(JCOV_REPORT) $(JCOV_RESULT_FILE)
|
||||
|
||||
TARGETS += jcov-do-start-grabber jcov-start-grabber jcov-stop-grabber \
|
||||
|
@ -81,21 +81,21 @@ AC_DEFUN([FLAGS_SETUP_RCFLAGS],
|
||||
RC_FLAGS="$RC_FLAGS \
|
||||
-D\"JDK_VERSION_STRING=\$(VERSION_STRING)\" \
|
||||
-D\"JDK_COMPANY=\$(COMPANY_NAME)\" \
|
||||
-D\"JDK_COMPONENT=\$(JDK_RC_NAME) binary\" \
|
||||
-D\"JDK_FILEDESC=\$(JDK_RC_NAME) binary\" \
|
||||
-D\"JDK_VER=\$(VERSION_NUMBER)\" \
|
||||
-D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \
|
||||
-D\"JDK_NAME=\$(JDK_RC_NAME) \$(VERSION_FEATURE)\" \
|
||||
-D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\""
|
||||
|
||||
JVM_RCFLAGS="$JVM_RCFLAGS \
|
||||
-D\"HS_BUILD_ID=\$(VERSION_STRING)\" \
|
||||
-D\"HS_VERSION_STRING=\$(VERSION_STRING)\" \
|
||||
-D\"HS_COMPANY=\$(COMPANY_NAME)\" \
|
||||
-D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \
|
||||
-D\"HS_VER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \
|
||||
-D\"HS_INTERNAL_NAME=jvm\" \
|
||||
-D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \
|
||||
-D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \
|
||||
-D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \
|
||||
-D\"HS_FNAME=jvm.dll\" \
|
||||
-D\"HS_INTERNAL_NAME=jvm\""
|
||||
-D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \
|
||||
-D\"HS_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\""
|
||||
fi
|
||||
AC_SUBST(RC_FLAGS)
|
||||
AC_SUBST(JVM_RCFLAGS)
|
||||
|
@ -404,9 +404,12 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
|
||||
[jcov library location])])
|
||||
AC_ARG_WITH(jcov-input-jdk, [AS_HELP_STRING([--with-jcov-input-jdk],
|
||||
[jdk image to instrument])])
|
||||
AC_ARG_WITH(jcov-filters, [AS_HELP_STRING([--with-jcov-filters],
|
||||
[filters to limit code for jcov instrumentation and report generation])])
|
||||
JCOV_HOME=
|
||||
JCOV_INPUT_JDK=
|
||||
JCOV_ENABLED=
|
||||
JCOV_FILTERS=
|
||||
if test "x$with_jcov" = "x" ; then
|
||||
JCOV_ENABLED="false"
|
||||
else
|
||||
@ -425,10 +428,14 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
|
||||
fi
|
||||
BASIC_FIXUP_PATH(JCOV_INPUT_JDK)
|
||||
fi
|
||||
if test "x$with_jcov_filters" != "x" ; then
|
||||
JCOV_FILTERS="$with_jcov_filters"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(JCOV_ENABLED)
|
||||
AC_SUBST(JCOV_HOME)
|
||||
AC_SUBST(JCOV_INPUT_JDK)
|
||||
AC_SUBST(JCOV_FILTERS)
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
|
@ -66,7 +66,33 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
|
||||
AC_SUBST(PRODUCT_SUFFIX)
|
||||
AC_SUBST(JDK_RC_PLATFORM_NAME)
|
||||
AC_SUBST(HOTSPOT_VM_DISTRO)
|
||||
|
||||
# Set the MACOSX Bundle Name base
|
||||
AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base],
|
||||
[Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_name_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base])
|
||||
elif test "x$with_macosx_bundle_name_base" != x; then
|
||||
# Set MACOSX_BUNDLE_NAME_BASE to the configured value.
|
||||
MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base"
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
|
||||
|
||||
# Set the MACOSX Bundle ID base
|
||||
AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base],
|
||||
[Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_id_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base])
|
||||
elif test "x$with_macosx_bundle_id_base" != x; then
|
||||
# Set MACOSX_BUNDLE_ID_BASE to the configured value.
|
||||
MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base"
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_ID_BASE)
|
||||
|
||||
# Set the JDK RC name
|
||||
|
@ -130,6 +130,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread"
|
||||
fi
|
||||
|
||||
# perfstat lib
|
||||
if test "x$OPENJDK_TARGET_OS" = xaix; then
|
||||
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat"
|
||||
fi
|
||||
|
||||
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
|
||||
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -ldemangle -lnsl \
|
||||
-lrt -lkstat"
|
||||
|
@ -389,6 +389,7 @@ GCOV_ENABLED=@GCOV_ENABLED@
|
||||
JCOV_ENABLED=@JCOV_ENABLED@
|
||||
JCOV_HOME=@JCOV_HOME@
|
||||
JCOV_INPUT_JDK=@JCOV_INPUT_JDK@
|
||||
JCOV_FILTERS=@JCOV_FILTERS@
|
||||
|
||||
# AddressSanitizer
|
||||
export ASAN_ENABLED:=@ASAN_ENABLED@
|
||||
|
@ -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
|
||||
@ -67,13 +67,24 @@ public class HelloClasslist {
|
||||
.forEach(System.out::println);
|
||||
|
||||
// Common concatenation patterns
|
||||
String const_I = "string" + args.length;
|
||||
String const_S = "string" + String.valueOf(args.length);
|
||||
String S_const = String.valueOf(args.length) + "string";
|
||||
String S_S = String.valueOf(args.length) + String.valueOf(args.length);
|
||||
String const_J = "string" + System.currentTimeMillis();
|
||||
String I_const = args.length + "string";
|
||||
String J_const = System.currentTimeMillis() + "string";
|
||||
String SS = String.valueOf(args.length) + String.valueOf(args.length);
|
||||
String CS = "string" + String.valueOf(args.length);
|
||||
String SC = String.valueOf(args.length) + "string";
|
||||
String SCS = String.valueOf(args.length) + "string" + String.valueOf(args.length);
|
||||
String CSS = "string" + String.valueOf(args.length) + String.valueOf(args.length);
|
||||
String CSCS = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
|
||||
String SCSC = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
|
||||
String CSCSC = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
|
||||
String SCSCS = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
|
||||
String CI = "string" + args.length;
|
||||
String IC = args.length + "string";
|
||||
String CIC = "string" + args.length + "string";
|
||||
String CICI = "string" + args.length + "string" + args.length;
|
||||
String CJ = "string" + System.currentTimeMillis();
|
||||
String JC = System.currentTimeMillis() + "string";
|
||||
String CJC = "string" + System.currentTimeMillis() + "string";
|
||||
String CJCJ = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis();
|
||||
String CJCJC = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis() + "string";
|
||||
|
||||
String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
|
||||
LocalDateTime.now(ZoneId.of("GMT")));
|
||||
|
@ -39,7 +39,6 @@ JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/launcher/icons
|
||||
# overwritten.
|
||||
$(eval $(call SetupBuildLauncher, java, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \
|
||||
LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \
|
||||
EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \
|
||||
VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \
|
||||
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \
|
||||
|
@ -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
|
||||
@ -43,7 +43,7 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
DISABLED_WARNINGS_microsoft := 4267 4996, \
|
||||
LDFLAGS := $(LDFLAGS_JDKEXE), \
|
||||
LIBS := advapi32.lib version.lib user32.lib, \
|
||||
VERSIONINFO_RESOURCE := $(ACCESSBRIDGE_SRC)/AccessBridgeStatusWindow.RC, \
|
||||
VERSIONINFO_RESOURCE := $(ACCESSBRIDGE_SRC)/AccessBridgeStatusWindow.rc, \
|
||||
MANIFEST := $(JABSWITCH_SRC)/jabswitch.manifest, \
|
||||
MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \
|
||||
))
|
||||
|
@ -73,8 +73,7 @@ JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest
|
||||
# compile time defines exceeding Visual Studio 2013 limitations.
|
||||
# CFLAGS Additional CFLAGS
|
||||
# CFLAGS_windows Additional CFLAGS_windows
|
||||
# LDFLAGS_solaris Additional LDFLAGS_solaris
|
||||
# RC_FLAGS Additional RC_FLAGS
|
||||
# EXTRA_RC_FLAGS Additional EXTRA_RC_FLAGS
|
||||
# MACOSX_SIGNED On macosx, sign this binary
|
||||
# OPTIMIZATION Override default optimization level (LOW)
|
||||
# OUTPUT_DIR Override default output directory
|
||||
@ -139,7 +138,7 @@ define SetupBuildLauncherBody
|
||||
NAME := $1, \
|
||||
EXTRA_FILES := $(LAUNCHER_SRC)/main.c, \
|
||||
OPTIMIZATION := $$($1_OPTIMIZATION), \
|
||||
CFLAGS := $$(CFLAGS_JDKEXE) $$($1_CFLAGS) \
|
||||
CFLAGS := $$(CFLAGS_JDKEXE) \
|
||||
$(LAUNCHER_CFLAGS) \
|
||||
$(VERSION_CFLAGS) \
|
||||
-DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \
|
||||
|
@ -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.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -418,7 +418,7 @@ class SlowSignatureHandler
|
||||
};
|
||||
|
||||
|
||||
IRT_ENTRY(address,
|
||||
JRT_ENTRY(address,
|
||||
InterpreterRuntime::slow_signature_handler(JavaThread* thread,
|
||||
Method* method,
|
||||
intptr_t* from,
|
||||
@ -435,4 +435,4 @@ IRT_ENTRY(address,
|
||||
|
||||
// return result handler
|
||||
return Interpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -67,7 +67,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// The CPU implementer codes can be found in
|
||||
// ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
|
||||
// https://developer.arm.com/docs/ddi0487/latest
|
||||
enum Family {
|
||||
CPU_AMPERE = 0xC0,
|
||||
CPU_ARM = 'A',
|
||||
CPU_BROADCOM = 'B',
|
||||
CPU_CAVIUM = 'C',
|
||||
|
@ -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
|
||||
@ -369,9 +369,9 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
}
|
||||
};
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(JavaThread* thread, Method* method, intptr_t* from, intptr_t* to))
|
||||
JRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(JavaThread* thread, Method* method, intptr_t* from, intptr_t* to))
|
||||
methodHandle m(thread, (Method*)method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
SlowSignatureHandler(m, (address)from, to).iterate(UCONST64(-1));
|
||||
return Interpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -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.
|
||||
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -148,15 +148,15 @@ void SignatureHandlerLibrary::pd_set_handler(address handler) {
|
||||
|
||||
|
||||
// Access function to get the signature.
|
||||
IRT_ENTRY(address, InterpreterRuntime::get_signature(JavaThread* thread, Method* method))
|
||||
JRT_ENTRY(address, InterpreterRuntime::get_signature(JavaThread* thread, Method* method))
|
||||
methodHandle m(thread, method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
Symbol *s = m->signature();
|
||||
return (address) s->base();
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::get_result_handler(JavaThread* thread, Method* method))
|
||||
JRT_ENTRY(address, InterpreterRuntime::get_result_handler(JavaThread* thread, Method* method))
|
||||
methodHandle m(thread, method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
return AbstractInterpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -38,6 +38,9 @@
|
||||
#include "vm_version_ppc.hpp"
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#if defined(_AIX)
|
||||
#include <libperfstat.h>
|
||||
#endif
|
||||
|
||||
#if defined(LINUX) && defined(VM_LITTLE_ENDIAN)
|
||||
#include <sys/auxv.h>
|
||||
@ -382,6 +385,58 @@ void VM_Version::initialize() {
|
||||
}
|
||||
|
||||
void VM_Version::print_platform_virtualization_info(outputStream* st) {
|
||||
#if defined(_AIX)
|
||||
// more info about perfstat API see
|
||||
// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.prftools/idprftools_perfstat_glob_partition.htm
|
||||
int rc = 0;
|
||||
perfstat_partition_total_t pinfo;
|
||||
memset(&pinfo, 0, sizeof(perfstat_partition_total_t));
|
||||
rc = perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1);
|
||||
if (rc != 1) {
|
||||
return;
|
||||
} else {
|
||||
st->print_cr("Virtualization type : PowerVM");
|
||||
}
|
||||
// CPU information
|
||||
perfstat_cpu_total_t cpuinfo;
|
||||
memset(&cpuinfo, 0, sizeof(perfstat_cpu_total_t));
|
||||
rc = perfstat_cpu_total(NULL, &cpuinfo, sizeof(perfstat_cpu_total_t), 1);
|
||||
if (rc != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
st->print_cr("Processor description : %s", cpuinfo.description);
|
||||
st->print_cr("Processor speed : %llu Hz", cpuinfo.processorHZ);
|
||||
|
||||
st->print_cr("LPAR partition name : %s", pinfo.name);
|
||||
st->print_cr("LPAR partition number : %u", pinfo.lpar_id);
|
||||
st->print_cr("LPAR partition type : %s", pinfo.type.b.shared_enabled ? "shared" : "dedicated");
|
||||
st->print_cr("LPAR mode : %s", pinfo.type.b.donate_enabled ? "donating" : pinfo.type.b.capped ? "capped" : "uncapped");
|
||||
st->print_cr("LPAR partition group ID : %u", pinfo.group_id);
|
||||
st->print_cr("LPAR shared pool ID : %u", pinfo.pool_id);
|
||||
|
||||
st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_capable ? "capable" : "not capable");
|
||||
st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_enabled ? "on" : "off");
|
||||
st->print_cr("AME (active memory expansion) : %s", pinfo.type.b.ame_enabled ? "on" : "off");
|
||||
|
||||
if (pinfo.type.b.ame_enabled) {
|
||||
st->print_cr("AME true memory in bytes : %llu", pinfo.true_memory);
|
||||
st->print_cr("AME expanded memory in bytes : %llu", pinfo.expanded_memory);
|
||||
}
|
||||
|
||||
st->print_cr("SMT : %s", pinfo.type.b.smt_capable ? "capable" : "not capable");
|
||||
st->print_cr("SMT : %s", pinfo.type.b.smt_enabled ? "on" : "off");
|
||||
int ocpus = pinfo.online_cpus > 0 ? pinfo.online_cpus : 1;
|
||||
st->print_cr("LPAR threads : %d", cpuinfo.ncpus/ocpus);
|
||||
st->print_cr("LPAR online virtual cpus : %d", pinfo.online_cpus);
|
||||
st->print_cr("LPAR logical cpus : %d", cpuinfo.ncpus);
|
||||
st->print_cr("LPAR maximum virtual cpus : %u", pinfo.max_cpus);
|
||||
st->print_cr("LPAR minimum virtual cpus : %u", pinfo.min_cpus);
|
||||
st->print_cr("LPAR entitled capacity : %4.2f", (double) (pinfo.entitled_proc_capacity/100.0));
|
||||
st->print_cr("LPAR online memory : %llu MB", pinfo.online_memory);
|
||||
st->print_cr("LPAR maximum memory : %llu MB", pinfo.max_memory);
|
||||
st->print_cr("LPAR minimum memory : %llu MB", pinfo.min_memory);
|
||||
#else
|
||||
const char* info_file = "/proc/ppc64/lparcfg";
|
||||
const char* kw[] = { "system_type=", // qemu indicates PowerKVM
|
||||
"partition_entitled_capacity=", // entitled processor capacity percentage
|
||||
@ -400,6 +455,7 @@ void VM_Version::print_platform_virtualization_info(outputStream* st) {
|
||||
if (!print_matching_lines_from_file(info_file, st, kw)) {
|
||||
st->print_cr(" <%s Not Available>", info_file);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VM_Version::use_biased_locking() {
|
||||
|
@ -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.
|
||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -151,15 +151,15 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin
|
||||
|
||||
void SignatureHandlerLibrary::pd_set_handler(address handler) {}
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::get_signature(JavaThread* thread, Method* method))
|
||||
JRT_ENTRY(address, InterpreterRuntime::get_signature(JavaThread* thread, Method* method))
|
||||
methodHandle m(thread, method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
Symbol *s = m->signature();
|
||||
return (address) s->base();
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::get_result_handler(JavaThread* thread, Method* method))
|
||||
JRT_ENTRY(address, InterpreterRuntime::get_result_handler(JavaThread* thread, Method* method))
|
||||
methodHandle m(thread, method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
return AbstractInterpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -4355,12 +4355,9 @@ void MacroAssembler::load_mirror(Register mirror, Register method) {
|
||||
// Emitter does not KILL cnt and base arguments, since they need to be copied to
|
||||
// work registers anyway.
|
||||
// Actually, only r0, r1, and r5 are killed.
|
||||
unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len) {
|
||||
// Src_addr is evenReg.
|
||||
// Src_len is odd_Reg.
|
||||
unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg) {
|
||||
|
||||
int block_start = offset();
|
||||
Register tmp_reg = src_len; // Holds target instr addr for EX.
|
||||
Register dst_len = Z_R1; // Holds dst len for MVCLE.
|
||||
Register dst_addr = Z_R0; // Holds dst addr for MVCLE.
|
||||
|
||||
@ -4369,7 +4366,7 @@ unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer
|
||||
BLOCK_COMMENT("Clear_Array {");
|
||||
|
||||
// Check for zero len and convert to long.
|
||||
z_ltgfr(src_len, cnt_arg); // Remember casted value for doSTG case.
|
||||
z_ltgfr(odd_tmp_reg, cnt_arg);
|
||||
z_bre(done); // Nothing to do if len == 0.
|
||||
|
||||
// Prefetch data to be cleared.
|
||||
@ -4378,16 +4375,17 @@ unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer
|
||||
z_pfd(0x02, 256, Z_R0, base_pointer_arg);
|
||||
}
|
||||
|
||||
z_sllg(dst_len, src_len, 3); // #bytes to clear.
|
||||
z_cghi(src_len, 32); // Check for len <= 256 bytes (<=32 DW).
|
||||
z_brnh(doXC); // If so, use executed XC to clear.
|
||||
z_sllg(dst_len, odd_tmp_reg, 3); // #bytes to clear.
|
||||
z_cghi(odd_tmp_reg, 32); // Check for len <= 256 bytes (<=32 DW).
|
||||
z_brnh(doXC); // If so, use executed XC to clear.
|
||||
|
||||
// MVCLE: initialize long arrays (general case).
|
||||
bind(doMVCLE);
|
||||
z_lgr(dst_addr, base_pointer_arg);
|
||||
clear_reg(src_len, true, false); // Src len of MVCLE is zero.
|
||||
|
||||
MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
|
||||
// Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
|
||||
// The even register of the register pair is not killed.
|
||||
clear_reg(odd_tmp_reg, true, false);
|
||||
MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding()-1), 0);
|
||||
z_bru(done);
|
||||
|
||||
// XC: initialize short arrays.
|
||||
@ -4396,12 +4394,12 @@ unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer
|
||||
z_xc(0,0,base_pointer_arg,0,base_pointer_arg);
|
||||
|
||||
bind(doXC);
|
||||
add2reg(dst_len, -1); // Get #bytes-1 for EXECUTE.
|
||||
add2reg(dst_len, -1); // Get #bytes-1 for EXECUTE.
|
||||
if (VM_Version::has_ExecuteExtensions()) {
|
||||
z_exrl(dst_len, XC_template); // Execute XC with var. len.
|
||||
z_exrl(dst_len, XC_template); // Execute XC with var. len.
|
||||
} else {
|
||||
z_larl(tmp_reg, XC_template);
|
||||
z_ex(dst_len,0,Z_R0,tmp_reg); // Execute XC with var. len.
|
||||
z_larl(odd_tmp_reg, XC_template);
|
||||
z_ex(dst_len,0,Z_R0,odd_tmp_reg); // Execute XC with var. len.
|
||||
}
|
||||
// z_bru(done); // fallthru
|
||||
|
||||
@ -4463,7 +4461,7 @@ unsigned int MacroAssembler::Clear_Array_Const(long cnt, Register base) {
|
||||
// Compiler ensures base is doubleword aligned and cnt is #doublewords.
|
||||
// Emitter does not KILL cnt and base arguments, since they need to be copied to
|
||||
// work registers anyway.
|
||||
// Actually, only r0, r1, r4, and r5 (which are work registers) are killed.
|
||||
// Actually, only r0, r1, (which are work registers) and odd_tmp_reg are killed.
|
||||
//
|
||||
// For very large arrays, exploit MVCLE H/W support.
|
||||
// MVCLE instruction automatically exploits H/W-optimized page mover.
|
||||
@ -4471,9 +4469,7 @@ unsigned int MacroAssembler::Clear_Array_Const(long cnt, Register base) {
|
||||
// - All full pages are cleared with the page mover H/W assist.
|
||||
// - Remaining bytes are again cleared by a series of XC to self.
|
||||
//
|
||||
unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len) {
|
||||
// Src_addr is evenReg.
|
||||
// Src_len is odd_Reg.
|
||||
unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg) {
|
||||
|
||||
int block_start = offset();
|
||||
Register dst_len = Z_R1; // Holds dst len for MVCLE.
|
||||
@ -4486,11 +4482,10 @@ unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_point
|
||||
|
||||
// Prepare other args to MVCLE.
|
||||
z_lgr(dst_addr, base_pointer_arg);
|
||||
// Indicate unused result.
|
||||
(void) clear_reg(src_len, true, false); // Src len of MVCLE is zero.
|
||||
|
||||
// Clear.
|
||||
MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
|
||||
// Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
|
||||
// The even register of the register pair is not killed.
|
||||
(void) clear_reg(odd_tmp_reg, true, false); // Src len of MVCLE is zero.
|
||||
MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding() - 1), 0);
|
||||
BLOCK_COMMENT("} Clear_Array_Const_Big");
|
||||
|
||||
int block_end = offset();
|
||||
|
@ -828,9 +828,9 @@ class MacroAssembler: public Assembler {
|
||||
//--------------------------
|
||||
//--- Operations on arrays.
|
||||
//--------------------------
|
||||
unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len);
|
||||
unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg);
|
||||
unsigned int Clear_Array_Const(long cnt, Register base);
|
||||
unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len);
|
||||
unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg);
|
||||
unsigned int CopyRawMemory_AlignedDisjoint(Register src_reg, Register dst_reg,
|
||||
Register cnt_reg,
|
||||
Register tmp1_reg, Register tmp2_reg);
|
||||
|
@ -474,6 +474,19 @@ reg_class z_long_reg(
|
||||
/*Z_R15_H,Z_R15*/ // SP
|
||||
);
|
||||
|
||||
// z_long_reg without even registers
|
||||
reg_class z_long_odd_reg(
|
||||
/*Z_R0_H,Z_R0*/ // R0
|
||||
/*Z_R1_H,Z_R1*/
|
||||
Z_R3_H,Z_R3,
|
||||
Z_R5_H,Z_R5,
|
||||
Z_R7_H,Z_R7,
|
||||
Z_R9_H,Z_R9,
|
||||
Z_R11_H,Z_R11,
|
||||
Z_R13_H,Z_R13
|
||||
/*Z_R14_H,Z_R14,*/ // return_pc
|
||||
/*Z_R15_H,Z_R15*/ // SP
|
||||
);
|
||||
|
||||
// Special Class for Condition Code Flags Register
|
||||
|
||||
@ -3378,6 +3391,7 @@ operand iRegL() %{
|
||||
match(RegL);
|
||||
match(revenRegL);
|
||||
match(roddRegL);
|
||||
match(allRoddRegL);
|
||||
match(rarg1RegL);
|
||||
match(rarg5RegL);
|
||||
format %{ %}
|
||||
@ -3400,6 +3414,14 @@ operand roddRegL() %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// available odd registers for iRegL
|
||||
operand allRoddRegL() %{
|
||||
constraint(ALLOC_IN_RC(z_long_odd_reg));
|
||||
match(iRegL);
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand rarg1RegL() %{
|
||||
constraint(ALLOC_IN_RC(z_rarg1_long_reg));
|
||||
match(iRegL);
|
||||
@ -9899,23 +9921,23 @@ instruct inlineCallClearArrayConst(SSlenDW cnt, iRegP_N2P base, Universe dummy,
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
|
||||
instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
|
||||
effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
|
||||
ins_cost(200);
|
||||
// TODO: s390 port size(VARIABLE_SIZE); // Variable in size due to optimized constant loader.
|
||||
format %{ "ClearArrayConstBig $cnt,$base" %}
|
||||
ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $srcA$$Register, $srcL$$Register); %}
|
||||
ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $tmpL$$Register); %}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
|
||||
instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
|
||||
effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
|
||||
ins_cost(300);
|
||||
// TODO: s390 port size(FIXED_SIZE); // z/Architecture: emitted code depends on PreferLAoverADD being on/off.
|
||||
format %{ "ClearArrayVar $cnt,$base" %}
|
||||
ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $srcA$$Register, $srcL$$Register); %}
|
||||
ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $tmpL$$Register); %}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
|
@ -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
|
||||
@ -191,7 +191,7 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
};
|
||||
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(
|
||||
JRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(
|
||||
JavaThread* thread,
|
||||
Method* method,
|
||||
intptr_t* from,
|
||||
@ -204,4 +204,4 @@ IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(
|
||||
SlowSignatureHandler(m, (address)from, m->is_static() ? to+2 : to+1, to).iterate((uint64_t)CONST64(-1));
|
||||
// return result handler
|
||||
return Interpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -3099,7 +3099,7 @@ void Assembler::nop(int i) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (UseAddressNop && VM_Version::is_amd()) {
|
||||
if (UseAddressNop && VM_Version::is_amd_family()) {
|
||||
//
|
||||
// Using multi-bytes nops "0x0F 0x1F [address]" for AMD.
|
||||
// 1: 0x90
|
||||
|
@ -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
|
||||
@ -147,11 +147,11 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
}
|
||||
};
|
||||
|
||||
IRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(JavaThread* thread, Method* method, intptr_t* from, intptr_t* to))
|
||||
JRT_ENTRY(address, InterpreterRuntime::slow_signature_handler(JavaThread* thread, Method* method, intptr_t* from, intptr_t* to))
|
||||
methodHandle m(thread, (Method*)method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
// handle arguments
|
||||
SlowSignatureHandler(m, (address)from, to + 1).iterate((uint64_t)CONST64(-1));
|
||||
// return result handler
|
||||
return Interpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -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
|
||||
@ -496,7 +496,7 @@ class SlowSignatureHandler
|
||||
#endif
|
||||
|
||||
|
||||
IRT_ENTRY(address,
|
||||
JRT_ENTRY(address,
|
||||
InterpreterRuntime::slow_signature_handler(JavaThread* thread,
|
||||
Method* method,
|
||||
intptr_t* from,
|
||||
@ -509,4 +509,4 @@ IRT_ENTRY(address,
|
||||
|
||||
// return result handler
|
||||
return Interpreter::result_handler(m->result_type());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
@ -2968,9 +2968,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
__ enter();
|
||||
__ subptr(rsp, 8 * wordSize);
|
||||
if (multi_block) {
|
||||
__ push(limit);
|
||||
}
|
||||
handleSOERegisters(true /*saving*/);
|
||||
|
||||
__ movptr(buf, buf_param);
|
||||
__ movptr(state, state_param);
|
||||
if (multi_block) {
|
||||
@ -2981,9 +2980,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask,
|
||||
buf, state, ofs, limit, rsp, multi_block);
|
||||
|
||||
if (multi_block) {
|
||||
__ pop(limit);
|
||||
}
|
||||
handleSOERegisters(false /*restoring*/);
|
||||
__ addptr(rsp, 8 * wordSize);
|
||||
__ leave();
|
||||
__ ret(0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -43,10 +43,10 @@ typedef enum {
|
||||
CPU_FAMILY_PENTIUM_4 = 0xF
|
||||
} FamilyFlag;
|
||||
|
||||
typedef enum {
|
||||
RDTSCP_FLAG = 0x08000000, // bit 27
|
||||
INTEL64_FLAG = 0x20000000 // bit 29
|
||||
} _featureExtendedEdxFlag;
|
||||
typedef enum {
|
||||
RDTSCP_FLAG = 0x08000000, // bit 27
|
||||
INTEL64_FLAG = 0x20000000 // bit 29
|
||||
} _featureExtendedEdxFlag;
|
||||
|
||||
#define CPUID_STANDARD_FN 0x0
|
||||
#define CPUID_STANDARD_FN_1 0x1
|
||||
@ -340,6 +340,10 @@ bool VM_Version_Ext::supports_tscinv_ext(void) {
|
||||
return !is_amd_Barcelona();
|
||||
}
|
||||
|
||||
if (is_hygon()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -399,13 +403,20 @@ int VM_Version_Ext::number_of_sockets(void) {
|
||||
const char* VM_Version_Ext::cpu_family_description(void) {
|
||||
int cpu_family_id = extended_cpu_family();
|
||||
if (is_amd()) {
|
||||
return _family_id_amd[cpu_family_id];
|
||||
if (cpu_family_id < ExtendedFamilyIdLength_AMD) {
|
||||
return _family_id_amd[cpu_family_id];
|
||||
}
|
||||
}
|
||||
if (is_intel()) {
|
||||
if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) {
|
||||
return cpu_model_description();
|
||||
}
|
||||
return _family_id_intel[cpu_family_id];
|
||||
if (cpu_family_id < ExtendedFamilyIdLength_INTEL) {
|
||||
return _family_id_intel[cpu_family_id];
|
||||
}
|
||||
}
|
||||
if (is_hygon()) {
|
||||
return "Dhyana";
|
||||
}
|
||||
return "Unknown x86";
|
||||
}
|
||||
@ -423,6 +434,9 @@ int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) {
|
||||
} else if (is_amd()) {
|
||||
cpu_type = "AMD";
|
||||
x64 = cpu_is_em64t() ? " AMD64" : "";
|
||||
} else if (is_hygon()) {
|
||||
cpu_type = "Hygon";
|
||||
x64 = cpu_is_em64t() ? " AMD64" : "";
|
||||
} else {
|
||||
cpu_type = "Unknown x86";
|
||||
x64 = cpu_is_em64t() ? " x86_64" : "";
|
||||
@ -694,7 +708,7 @@ jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
|
||||
return _max_qualified_cpu_frequency;
|
||||
}
|
||||
|
||||
const char* const VM_Version_Ext::_family_id_intel[] = {
|
||||
const char* const VM_Version_Ext::_family_id_intel[ExtendedFamilyIdLength_INTEL] = {
|
||||
"8086/8088",
|
||||
"",
|
||||
"286",
|
||||
@ -713,7 +727,7 @@ const char* const VM_Version_Ext::_family_id_intel[] = {
|
||||
"Pentium 4"
|
||||
};
|
||||
|
||||
const char* const VM_Version_Ext::_family_id_amd[] = {
|
||||
const char* const VM_Version_Ext::_family_id_amd[ExtendedFamilyIdLength_AMD] = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
@ -731,6 +745,13 @@ const char* const VM_Version_Ext::_family_id_amd[] = {
|
||||
"",
|
||||
"Opteron/Athlon64",
|
||||
"Opteron QC/Phenom" // Barcelona et.al.
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Zen"
|
||||
};
|
||||
// Partially from Intel 64 and IA-32 Architecture Software Developer's Manual,
|
||||
// September 2013, Vol 3C Table 35-1
|
||||
|
@ -29,14 +29,20 @@
|
||||
#include "vm_version_x86.hpp"
|
||||
|
||||
class VM_Version_Ext : public VM_Version {
|
||||
|
||||
enum {
|
||||
ExtendedFamilyIdLength_INTEL = 16,
|
||||
ExtendedFamilyIdLength_AMD = 24
|
||||
};
|
||||
|
||||
private:
|
||||
static const size_t VENDOR_LENGTH;
|
||||
static const size_t CPU_EBS_MAX_LENGTH;
|
||||
static const size_t CPU_TYPE_DESC_BUF_SIZE;
|
||||
static const size_t CPU_DETAILED_DESC_BUF_SIZE;
|
||||
|
||||
static const char* const _family_id_intel[];
|
||||
static const char* const _family_id_amd[];
|
||||
static const char* const _family_id_intel[ExtendedFamilyIdLength_INTEL];
|
||||
static const char* const _family_id_amd[ExtendedFamilyIdLength_AMD];
|
||||
static const char* const _brand_id[];
|
||||
static const char* const _model_id_pentium_pro[];
|
||||
|
||||
|
@ -680,7 +680,7 @@ void VM_Version::get_processor_features() {
|
||||
_features &= ~CPU_HT;
|
||||
}
|
||||
|
||||
if( is_intel() ) { // Intel cpus specific settings
|
||||
if (is_intel()) { // Intel cpus specific settings
|
||||
if (is_knights_family()) {
|
||||
_features &= ~CPU_VZEROUPPER;
|
||||
}
|
||||
@ -781,7 +781,7 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
|
||||
}
|
||||
} else {
|
||||
if(supports_sse4_1()) {
|
||||
if (supports_sse4_1()) {
|
||||
if (FLAG_IS_DEFAULT(UseAESCTRIntrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, true);
|
||||
}
|
||||
@ -1001,7 +1001,7 @@ void VM_Version::get_processor_features() {
|
||||
} else if (UseAVX == 1 || UseAVX == 2) {
|
||||
// 32 bytes vectors (in YMM) are only supported with AVX+
|
||||
max_vector_size = 32;
|
||||
} else if (UseAVX > 2 ) {
|
||||
} else if (UseAVX > 2) {
|
||||
// 64 bytes vectors (in ZMM) are only supported with AVX 3
|
||||
max_vector_size = 64;
|
||||
}
|
||||
@ -1165,38 +1165,38 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
|
||||
if( is_amd() ) { // AMD cpus specific settings
|
||||
if( supports_sse2() && FLAG_IS_DEFAULT(UseAddressNop) ) {
|
||||
if (is_amd_family()) { // AMD cpus specific settings
|
||||
if (supports_sse2() && FLAG_IS_DEFAULT(UseAddressNop)) {
|
||||
// Use it on new AMD cpus starting from Opteron.
|
||||
UseAddressNop = true;
|
||||
}
|
||||
if( supports_sse2() && FLAG_IS_DEFAULT(UseNewLongLShift) ) {
|
||||
if (supports_sse2() && FLAG_IS_DEFAULT(UseNewLongLShift)) {
|
||||
// Use it on new AMD cpus starting from Opteron.
|
||||
UseNewLongLShift = true;
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper)) {
|
||||
if (supports_sse4a()) {
|
||||
UseXmmLoadAndClearUpper = true; // use movsd only on '10h' Opteron
|
||||
} else {
|
||||
UseXmmLoadAndClearUpper = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
||||
if( supports_sse4a() ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll)) {
|
||||
if (supports_sse4a()) {
|
||||
UseXmmRegToRegMoveAll = true; // use movaps, movapd only on '10h'
|
||||
} else {
|
||||
UseXmmRegToRegMoveAll = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
|
||||
if( supports_sse4a() ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmI2F)) {
|
||||
if (supports_sse4a()) {
|
||||
UseXmmI2F = true;
|
||||
} else {
|
||||
UseXmmI2F = false;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
|
||||
if( supports_sse4a() ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmI2D)) {
|
||||
if (supports_sse4a()) {
|
||||
UseXmmI2D = true;
|
||||
} else {
|
||||
UseXmmI2D = false;
|
||||
@ -1214,7 +1214,7 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
// some defaults for AMD family 15h
|
||||
if ( cpu_family() == 0x15 ) {
|
||||
if (cpu_family() == 0x15) {
|
||||
// On family 15h processors default is no sw prefetch
|
||||
if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0);
|
||||
@ -1239,8 +1239,8 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
// Some defaults for AMD family 17h
|
||||
if ( cpu_family() == 0x17 ) {
|
||||
// Some defaults for AMD family 17h || Hygon family 18h
|
||||
if (cpu_family() == 0x17 || cpu_family() == 0x18) {
|
||||
// On family 17h processors use XMM and UnalignedLoadStores for Array Copy
|
||||
if (supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy)) {
|
||||
FLAG_SET_DEFAULT(UseXMMForArrayCopy, true);
|
||||
@ -1256,29 +1256,29 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
|
||||
if( is_intel() ) { // Intel cpus specific settings
|
||||
if( FLAG_IS_DEFAULT(UseStoreImmI16) ) {
|
||||
if (is_intel()) { // Intel cpus specific settings
|
||||
if (FLAG_IS_DEFAULT(UseStoreImmI16)) {
|
||||
UseStoreImmI16 = false; // don't use it on Intel cpus
|
||||
}
|
||||
if( cpu_family() == 6 || cpu_family() == 15 ) {
|
||||
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
|
||||
if (cpu_family() == 6 || cpu_family() == 15) {
|
||||
if (FLAG_IS_DEFAULT(UseAddressNop)) {
|
||||
// Use it on all Intel cpus starting from PentiumPro
|
||||
UseAddressNop = true;
|
||||
}
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper)) {
|
||||
UseXmmLoadAndClearUpper = true; // use movsd on all Intel cpus
|
||||
}
|
||||
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
||||
if( supports_sse3() ) {
|
||||
if (FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll)) {
|
||||
if (supports_sse3()) {
|
||||
UseXmmRegToRegMoveAll = true; // use movaps, movapd on new Intel cpus
|
||||
} else {
|
||||
UseXmmRegToRegMoveAll = false;
|
||||
}
|
||||
}
|
||||
if( cpu_family() == 6 && supports_sse3() ) { // New Intel cpus
|
||||
if (cpu_family() == 6 && supports_sse3()) { // New Intel cpus
|
||||
#ifdef COMPILER2
|
||||
if( FLAG_IS_DEFAULT(MaxLoopPad) ) {
|
||||
if (FLAG_IS_DEFAULT(MaxLoopPad)) {
|
||||
// For new Intel cpus do the next optimization:
|
||||
// don't align the beginning of a loop if there are enough instructions
|
||||
// left (NumberOfLoopInstrToAlign defined in c2_globals.hpp)
|
||||
@ -1324,7 +1324,7 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseIncDec, false);
|
||||
}
|
||||
}
|
||||
if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
|
||||
if (FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3);
|
||||
}
|
||||
}
|
||||
|
@ -495,13 +495,13 @@ protected:
|
||||
result |= CPU_CX8;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0)
|
||||
result |= CPU_CMOV;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || (is_amd() &&
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
|
||||
_cpuid_info.ext_cpuid1_edx.bits.fxsr != 0))
|
||||
result |= CPU_FXSR;
|
||||
// HT flag is set for multi-core processors also.
|
||||
if (threads_per_core() > 1)
|
||||
result |= CPU_HT;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || (is_amd() &&
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
|
||||
_cpuid_info.ext_cpuid1_edx.bits.mmx != 0))
|
||||
result |= CPU_MMX;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
|
||||
@ -553,7 +553,7 @@ protected:
|
||||
result |= CPU_VNNI;
|
||||
}
|
||||
}
|
||||
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
|
||||
result |= CPU_BMI1;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
|
||||
result |= CPU_TSC;
|
||||
@ -567,17 +567,17 @@ protected:
|
||||
result |= CPU_CLMUL;
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
|
||||
result |= CPU_RTM;
|
||||
if(_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
|
||||
result |= CPU_ADX;
|
||||
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
|
||||
result |= CPU_BMI2;
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0)
|
||||
result |= CPU_SHA;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.fma != 0)
|
||||
result |= CPU_FMA;
|
||||
|
||||
// AMD features.
|
||||
if (is_amd()) {
|
||||
// AMD|Hygon features.
|
||||
if (is_amd_family()) {
|
||||
if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
|
||||
(_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
|
||||
result |= CPU_3DNOW_PREFETCH;
|
||||
@ -587,8 +587,8 @@ protected:
|
||||
result |= CPU_SSE4A;
|
||||
}
|
||||
// Intel features.
|
||||
if(is_intel()) {
|
||||
if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
|
||||
if (is_intel()) {
|
||||
if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
|
||||
result |= CPU_LZCNT;
|
||||
// for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw
|
||||
if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) {
|
||||
@ -714,6 +714,8 @@ public:
|
||||
static int cpu_family() { return _cpu;}
|
||||
static bool is_P6() { return cpu_family() >= 6; }
|
||||
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
|
||||
static bool is_hygon() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x6F677948; } // 'ogyH'
|
||||
static bool is_amd_family() { return is_amd() || is_hygon(); }
|
||||
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
|
||||
static bool is_zx() { assert_is_initialized(); return (_cpuid_info.std_vendor_name_0 == 0x746e6543) || (_cpuid_info.std_vendor_name_0 == 0x68532020); } // 'tneC'||'hS '
|
||||
static bool is_atom_family() { return ((cpu_family() == 0x06) && ((extended_cpu_model() == 0x36) || (extended_cpu_model() == 0x37) || (extended_cpu_model() == 0x4D))); } //Silvermont and Centerton
|
||||
@ -737,7 +739,7 @@ public:
|
||||
if (!supports_topology || result == 0) {
|
||||
result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
|
||||
}
|
||||
} else if (is_amd()) {
|
||||
} else if (is_amd_family()) {
|
||||
result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
|
||||
} else if (is_zx()) {
|
||||
bool supports_topology = supports_processor_topology();
|
||||
@ -773,7 +775,7 @@ public:
|
||||
intx result = 0;
|
||||
if (is_intel()) {
|
||||
result = (_cpuid_info.dcp_cpuid4_ebx.bits.L1_line_size + 1);
|
||||
} else if (is_amd()) {
|
||||
} else if (is_amd_family()) {
|
||||
result = _cpuid_info.ext_cpuid5_ecx.bits.L1_line_size;
|
||||
} else if (is_zx()) {
|
||||
result = (_cpuid_info.dcp_cpuid4_ebx.bits.L1_line_size + 1);
|
||||
@ -860,7 +862,7 @@ public:
|
||||
|
||||
// AMD features
|
||||
static bool supports_3dnow_prefetch() { return (_features & CPU_3DNOW_PREFETCH) != 0; }
|
||||
static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
|
||||
static bool supports_mmx_ext() { return is_amd_family() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
|
||||
static bool supports_lzcnt() { return (_features & CPU_LZCNT) != 0; }
|
||||
static bool supports_sse4a() { return (_features & CPU_SSE4A) != 0; }
|
||||
|
||||
@ -873,8 +875,8 @@ public:
|
||||
}
|
||||
static bool supports_tscinv() {
|
||||
return supports_tscinv_bit() &&
|
||||
( (is_amd() && !is_amd_Barcelona()) ||
|
||||
is_intel_tsc_synched_at_init() );
|
||||
((is_amd_family() && !is_amd_Barcelona()) ||
|
||||
is_intel_tsc_synched_at_init());
|
||||
}
|
||||
|
||||
// Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
|
||||
@ -899,7 +901,7 @@ public:
|
||||
// Core - 256 / prefetchnta
|
||||
// It will be used only when AllocatePrefetchStyle > 0
|
||||
|
||||
if (is_amd()) { // AMD
|
||||
if (is_amd_family()) { // AMD | Hygon
|
||||
if (supports_sse2()) {
|
||||
return 256; // Opteron
|
||||
} else {
|
||||
|
@ -699,11 +699,11 @@ intptr_t* CppInterpreter::calculate_unwind_sp(ZeroStack* stack,
|
||||
return stack->sp() + argument_slots;
|
||||
}
|
||||
|
||||
IRT_ENTRY(void, CppInterpreter::throw_exception(JavaThread* thread,
|
||||
JRT_ENTRY(void, CppInterpreter::throw_exception(JavaThread* thread,
|
||||
Symbol* name,
|
||||
char* message))
|
||||
THROW_MSG(name, message);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
InterpreterFrame *InterpreterFrame::build(Method* const method, TRAPS) {
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
|
@ -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.
|
||||
* Copyright 2007, 2008, 2010 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -141,7 +141,7 @@ void InterpreterRuntime::SignatureHandler::finalize() {
|
||||
assert(status == FFI_OK, "should be");
|
||||
}
|
||||
|
||||
IRT_ENTRY(address,
|
||||
JRT_ENTRY(address,
|
||||
InterpreterRuntime::slow_signature_handler(JavaThread* thread,
|
||||
Method* method,
|
||||
intptr_t* unused1,
|
||||
@ -162,7 +162,7 @@ IRT_ENTRY(address,
|
||||
handler->finalize();
|
||||
|
||||
return (address) handler;
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
void SignatureHandlerLibrary::pd_set_handler(address handlerAddr) {
|
||||
InterpreterRuntime::SignatureHandler *handler =
|
||||
|
@ -1405,13 +1405,7 @@ void os::print_os_info(outputStream* st) {
|
||||
st->print_cr("type: %s", (wi.app_wpar ? "application" : "system"));
|
||||
}
|
||||
|
||||
// print partition info
|
||||
libperfstat::partitioninfo_t pi;
|
||||
if (libperfstat::get_partitioninfo(&pi)) {
|
||||
st->print_cr("partition info");
|
||||
st->print_cr(" name: %s", pi.name);
|
||||
}
|
||||
|
||||
VM_Version::print_platform_virtualization_info(st);
|
||||
}
|
||||
|
||||
void os::print_memory_info(outputStream* st) {
|
||||
|
@ -122,7 +122,25 @@ class CgroupSubsystem: CHeapObj<mtInternal> {
|
||||
char *subsystem_path() { return _path; }
|
||||
};
|
||||
|
||||
CgroupSubsystem* memory = NULL;
|
||||
class CgroupMemorySubsystem: CgroupSubsystem {
|
||||
friend class OSContainer;
|
||||
|
||||
private:
|
||||
/* Some container runtimes set limits via cgroup
|
||||
* hierarchy. If set to true consider also memory.stat
|
||||
* file if everything else seems unlimited */
|
||||
bool _uses_mem_hierarchy;
|
||||
|
||||
public:
|
||||
CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
|
||||
_uses_mem_hierarchy = false;
|
||||
}
|
||||
|
||||
bool is_hierarchical() { return _uses_mem_hierarchy; }
|
||||
void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
|
||||
};
|
||||
|
||||
CgroupMemorySubsystem* memory = NULL;
|
||||
CgroupSubsystem* cpuset = NULL;
|
||||
CgroupSubsystem* cpu = NULL;
|
||||
CgroupSubsystem* cpuacct = NULL;
|
||||
@ -131,21 +149,24 @@ typedef char * cptr;
|
||||
|
||||
PRAGMA_DIAG_PUSH
|
||||
PRAGMA_FORMAT_NONLITERAL_IGNORED
|
||||
template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
|
||||
template <typename T> int subsystem_file_line_contents(CgroupSubsystem* c,
|
||||
const char *filename,
|
||||
const char *matchline,
|
||||
const char *scan_fmt,
|
||||
T returnval) {
|
||||
FILE *fp = NULL;
|
||||
char *p;
|
||||
char file[MAXPATHLEN+1];
|
||||
char buf[MAXPATHLEN+1];
|
||||
char discard[MAXPATHLEN+1];
|
||||
bool found_match = false;
|
||||
|
||||
if (c == NULL) {
|
||||
log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL");
|
||||
log_debug(os, container)("subsystem_file_line_contents: CgroupSubsytem* is NULL");
|
||||
return OSCONTAINER_ERROR;
|
||||
}
|
||||
if (c->subsystem_path() == NULL) {
|
||||
log_debug(os, container)("subsystem_file_contents: subsystem path is NULL");
|
||||
log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL");
|
||||
return OSCONTAINER_ERROR;
|
||||
}
|
||||
|
||||
@ -160,16 +181,32 @@ template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
|
||||
log_trace(os, container)("Path to %s is %s", filename, file);
|
||||
fp = fopen(file, "r");
|
||||
if (fp != NULL) {
|
||||
p = fgets(buf, MAXPATHLEN, fp);
|
||||
if (p != NULL) {
|
||||
int matched = sscanf(p, scan_fmt, returnval);
|
||||
if (matched == 1) {
|
||||
int err = 0;
|
||||
while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) {
|
||||
found_match = false;
|
||||
if (matchline == NULL) {
|
||||
// single-line file case
|
||||
int matched = sscanf(p, scan_fmt, returnval);
|
||||
found_match = (matched == 1);
|
||||
} else {
|
||||
// multi-line file case
|
||||
if (strstr(p, matchline) != NULL) {
|
||||
// discard matchline string prefix
|
||||
int matched = sscanf(p, scan_fmt, discard, returnval);
|
||||
found_match = (matched == 2);
|
||||
} else {
|
||||
continue; // substring not found
|
||||
}
|
||||
}
|
||||
if (found_match) {
|
||||
fclose(fp);
|
||||
return 0;
|
||||
} else {
|
||||
err = 1;
|
||||
log_debug(os, container)("Type %s not found in file %s", scan_fmt, file);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (err == 0) {
|
||||
log_debug(os, container)("Empty file %s", file);
|
||||
}
|
||||
} else {
|
||||
@ -186,10 +223,11 @@ PRAGMA_DIAG_POP
|
||||
return_type variable; \
|
||||
{ \
|
||||
int err; \
|
||||
err = subsystem_file_contents(subsystem, \
|
||||
filename, \
|
||||
scan_fmt, \
|
||||
&variable); \
|
||||
err = subsystem_file_line_contents(subsystem, \
|
||||
filename, \
|
||||
NULL, \
|
||||
scan_fmt, \
|
||||
&variable); \
|
||||
if (err != 0) \
|
||||
return (return_type) OSCONTAINER_ERROR; \
|
||||
\
|
||||
@ -201,16 +239,33 @@ PRAGMA_DIAG_POP
|
||||
char variable[bufsize]; \
|
||||
{ \
|
||||
int err; \
|
||||
err = subsystem_file_contents(subsystem, \
|
||||
filename, \
|
||||
scan_fmt, \
|
||||
variable); \
|
||||
err = subsystem_file_line_contents(subsystem, \
|
||||
filename, \
|
||||
NULL, \
|
||||
scan_fmt, \
|
||||
variable); \
|
||||
if (err != 0) \
|
||||
return (return_type) NULL; \
|
||||
\
|
||||
log_trace(os, container)(logstring, variable); \
|
||||
}
|
||||
|
||||
#define GET_CONTAINER_INFO_LINE(return_type, subsystem, filename, \
|
||||
matchline, logstring, scan_fmt, variable) \
|
||||
return_type variable; \
|
||||
{ \
|
||||
int err; \
|
||||
err = subsystem_file_line_contents(subsystem, \
|
||||
filename, \
|
||||
matchline, \
|
||||
scan_fmt, \
|
||||
&variable); \
|
||||
if (err != 0) \
|
||||
return (return_type) OSCONTAINER_ERROR; \
|
||||
\
|
||||
log_trace(os, container)(logstring, variable); \
|
||||
}
|
||||
|
||||
/* init
|
||||
*
|
||||
* Initialize the container support and determine if
|
||||
@ -266,7 +321,7 @@ void OSContainer::init() {
|
||||
}
|
||||
while ((token = strsep(&cptr, ",")) != NULL) {
|
||||
if (strcmp(token, "memory") == 0) {
|
||||
memory = new CgroupSubsystem(tmproot, tmpmount);
|
||||
memory = new CgroupMemorySubsystem(tmproot, tmpmount);
|
||||
} else if (strcmp(token, "cpuset") == 0) {
|
||||
cpuset = new CgroupSubsystem(tmproot, tmpmount);
|
||||
} else if (strcmp(token, "cpu") == 0) {
|
||||
@ -344,6 +399,10 @@ void OSContainer::init() {
|
||||
while ((token = strsep(&controllers, ",")) != NULL) {
|
||||
if (strcmp(token, "memory") == 0) {
|
||||
memory->set_subsystem_path(base);
|
||||
jlong hierarchy = uses_mem_hierarchy();
|
||||
if (hierarchy > 0) {
|
||||
memory->set_hierarchical(true);
|
||||
}
|
||||
} else if (strcmp(token, "cpuset") == 0) {
|
||||
cpuset->set_subsystem_path(base);
|
||||
} else if (strcmp(token, "cpu") == 0) {
|
||||
@ -360,6 +419,7 @@ void OSContainer::init() {
|
||||
// command line arguments have been processed.
|
||||
if ((mem_limit = memory_limit_in_bytes()) > 0) {
|
||||
os::Linux::set_physical_memory(mem_limit);
|
||||
log_info(os, container)("Memory Limit is: " JLONG_FORMAT, mem_limit);
|
||||
}
|
||||
|
||||
_is_containerized = true;
|
||||
@ -374,6 +434,21 @@ const char * OSContainer::container_type() {
|
||||
}
|
||||
}
|
||||
|
||||
/* uses_mem_hierarchy
|
||||
*
|
||||
* Return whether or not hierarchical cgroup accounting is being
|
||||
* done.
|
||||
*
|
||||
* return:
|
||||
* A number > 0 if true, or
|
||||
* OSCONTAINER_ERROR for not supported
|
||||
*/
|
||||
jlong OSContainer::uses_mem_hierarchy() {
|
||||
GET_CONTAINER_INFO(jlong, memory, "/memory.use_hierarchy",
|
||||
"Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
|
||||
return use_hierarchy;
|
||||
}
|
||||
|
||||
|
||||
/* memory_limit_in_bytes
|
||||
*
|
||||
@ -389,7 +464,18 @@ jlong OSContainer::memory_limit_in_bytes() {
|
||||
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
|
||||
|
||||
if (memlimit >= _unlimited_memory) {
|
||||
log_trace(os, container)("Memory Limit is: Unlimited");
|
||||
log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");
|
||||
if (memory->is_hierarchical()) {
|
||||
const char* matchline = "hierarchical_memory_limit";
|
||||
char* format = "%s " JULONG_FORMAT;
|
||||
GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
|
||||
"Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit)
|
||||
if (hier_memlimit >= _unlimited_memory) {
|
||||
log_trace(os, container)("Hierarchical Memory Limit is: Unlimited");
|
||||
} else {
|
||||
return (jlong)hier_memlimit;
|
||||
}
|
||||
}
|
||||
return (jlong)-1;
|
||||
}
|
||||
else {
|
||||
@ -401,7 +487,18 @@ jlong OSContainer::memory_and_swap_limit_in_bytes() {
|
||||
GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
|
||||
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
|
||||
if (memswlimit >= _unlimited_memory) {
|
||||
log_trace(os, container)("Memory and Swap Limit is: Unlimited");
|
||||
log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");
|
||||
if (memory->is_hierarchical()) {
|
||||
const char* matchline = "hierarchical_memsw_limit";
|
||||
char* format = "%s " JULONG_FORMAT;
|
||||
GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
|
||||
"Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit)
|
||||
if (hier_memlimit >= _unlimited_memory) {
|
||||
log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");
|
||||
} else {
|
||||
return (jlong)hier_memlimit;
|
||||
}
|
||||
}
|
||||
return (jlong)-1;
|
||||
} else {
|
||||
return (jlong)memswlimit;
|
||||
|
@ -42,6 +42,7 @@ class OSContainer: AllStatic {
|
||||
static inline bool is_containerized();
|
||||
static const char * container_type();
|
||||
|
||||
static jlong uses_mem_hierarchy();
|
||||
static jlong memory_limit_in_bytes();
|
||||
static jlong memory_and_swap_limit_in_bytes();
|
||||
static jlong memory_soft_limit_in_bytes();
|
||||
|
@ -5000,17 +5000,13 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
|
||||
char *addr, size_t bytes, bool read_only,
|
||||
bool allow_exec) {
|
||||
// This OS does not allow existing memory maps to be remapped so we
|
||||
// have to unmap the memory before we remap it.
|
||||
if (!os::unmap_memory(addr, bytes)) {
|
||||
return NULL;
|
||||
}
|
||||
// would have to unmap the memory before we remap it.
|
||||
|
||||
// There is a very small theoretical window between the unmap_memory()
|
||||
// call above and the map_memory() call below where a thread in native
|
||||
// code may be able to access an address that is no longer mapped.
|
||||
|
||||
return os::map_memory(fd, file_name, file_offset, addr, bytes,
|
||||
read_only, allow_exec);
|
||||
// Because there is a small window between unmapping memory and mapping
|
||||
// it in again with different protections, CDS archives are mapped RW
|
||||
// on windows, so this function isn't called.
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2004, 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,8 +36,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION JDK_VER
|
||||
PRODUCTVERSION JDK_VER
|
||||
FILEVERSION HS_FVER
|
||||
PRODUCTVERSION HS_FVER
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -54,15 +54,15 @@ BEGIN
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", XSTR(HS_COMPANY) "\0"
|
||||
VALUE "FileDescription", XSTR(HS_FILEDESC) "\0"
|
||||
VALUE "FileVersion", XSTR(JDK_DOTVER) "\0"
|
||||
VALUE "Full Version", XSTR(HS_BUILD_ID) "\0"
|
||||
VALUE "InternalName", XSTR(HS_INTERNAL_NAME) "\0"
|
||||
VALUE "LegalCopyright", XSTR(HS_COPYRIGHT) "\0"
|
||||
VALUE "OriginalFilename", XSTR(HS_FNAME) "\0"
|
||||
VALUE "ProductName", XSTR(HS_NAME) "\0"
|
||||
VALUE "ProductVersion", XSTR(JDK_DOTVER) "\0"
|
||||
VALUE "CompanyName", XSTR(HS_COMPANY) "\0"
|
||||
VALUE "FileDescription", XSTR(HS_FILEDESC) "\0"
|
||||
VALUE "FileVersion", XSTR(HS_VER) "\0"
|
||||
VALUE "Full Version", XSTR(HS_VERSION_STRING) "\0"
|
||||
VALUE "InternalName", XSTR(HS_INTERNAL_NAME) "\0"
|
||||
VALUE "LegalCopyright", XSTR(HS_COPYRIGHT) "\0"
|
||||
VALUE "OriginalFilename", XSTR(HS_FNAME) "\0"
|
||||
VALUE "ProductName", XSTR(HS_NAME) "\0"
|
||||
VALUE "ProductVersion", XSTR(HS_VER) "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -774,10 +774,16 @@ bool InstructForm::captures_bottom_type(FormDict &globals) const {
|
||||
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN") ||
|
||||
#if INCLUDE_ZGC
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadBarrierSlowReg") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadBarrierWeakSlowReg") ||
|
||||
#endif
|
||||
#if INCLUDE_SHENANDOAHGC
|
||||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN"))) return true;
|
||||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
|
||||
#endif
|
||||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true;
|
||||
else if ( is_ideal_load() == Form::idealP ) return true;
|
||||
else if ( is_ideal_store() != Form::none ) return true;
|
||||
|
||||
|
@ -5975,9 +5975,9 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
|
||||
_minor_version = stream->get_u2_fast();
|
||||
_major_version = stream->get_u2_fast();
|
||||
|
||||
if (DumpSharedSpaces && _major_version < JAVA_1_5_VERSION) {
|
||||
if (DumpSharedSpaces && _major_version < JAVA_6_VERSION) {
|
||||
ResourceMark rm;
|
||||
warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s",
|
||||
warning("Pre JDK 6 class not supported by CDS: %u.%u %s",
|
||||
_major_version, _minor_version, _class_name->as_C_string());
|
||||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
|
@ -1714,20 +1714,13 @@ oop java_lang_Thread::inherited_access_control_context(oop java_thread) {
|
||||
|
||||
|
||||
jlong java_lang_Thread::stackSize(oop java_thread) {
|
||||
if (_stackSize_offset > 0) {
|
||||
return java_thread->long_field(_stackSize_offset);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return java_thread->long_field(_stackSize_offset);
|
||||
}
|
||||
|
||||
// Write the thread status value to threadStatus field in java.lang.Thread java class.
|
||||
void java_lang_Thread::set_thread_status(oop java_thread,
|
||||
java_lang_Thread::ThreadStatus status) {
|
||||
// The threadStatus is only present starting in 1.5
|
||||
if (_thread_status_offset > 0) {
|
||||
java_thread->int_field_put(_thread_status_offset, status);
|
||||
}
|
||||
java_thread->int_field_put(_thread_status_offset, status);
|
||||
}
|
||||
|
||||
// Read thread status value from threadStatus field in java.lang.Thread java class.
|
||||
@ -1737,62 +1730,31 @@ java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thre
|
||||
assert(Threads_lock->owned_by_self() || Thread::current()->is_VM_thread() ||
|
||||
JavaThread::current()->thread_state() == _thread_in_vm,
|
||||
"Java Thread is not running in vm");
|
||||
// The threadStatus is only present starting in 1.5
|
||||
if (_thread_status_offset > 0) {
|
||||
return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
|
||||
} else {
|
||||
// All we can easily figure out is if it is alive, but that is
|
||||
// enough info for a valid unknown status.
|
||||
// These aren't restricted to valid set ThreadStatus values, so
|
||||
// use JVMTI values and cast.
|
||||
JavaThread* thr = java_lang_Thread::thread(java_thread);
|
||||
if (thr == NULL) {
|
||||
// the thread hasn't run yet or is in the process of exiting
|
||||
return NEW;
|
||||
}
|
||||
return (java_lang_Thread::ThreadStatus)JVMTI_THREAD_STATE_ALIVE;
|
||||
}
|
||||
return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
|
||||
}
|
||||
|
||||
|
||||
jlong java_lang_Thread::thread_id(oop java_thread) {
|
||||
// The thread ID field is only present starting in 1.5
|
||||
if (_tid_offset > 0) {
|
||||
return java_thread->long_field(_tid_offset);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return java_thread->long_field(_tid_offset);
|
||||
}
|
||||
|
||||
oop java_lang_Thread::park_blocker(oop java_thread) {
|
||||
assert(JDK_Version::current().supports_thread_park_blocker() &&
|
||||
_park_blocker_offset != 0, "Must support parkBlocker field");
|
||||
assert(JDK_Version::current().supports_thread_park_blocker(),
|
||||
"Must support parkBlocker field");
|
||||
|
||||
if (_park_blocker_offset > 0) {
|
||||
return java_thread->obj_field(_park_blocker_offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return java_thread->obj_field(_park_blocker_offset);
|
||||
}
|
||||
|
||||
jlong java_lang_Thread::park_event(oop java_thread) {
|
||||
if (_park_event_offset > 0) {
|
||||
return java_thread->long_field(_park_event_offset);
|
||||
}
|
||||
return 0;
|
||||
return java_thread->long_field(_park_event_offset);
|
||||
}
|
||||
|
||||
bool java_lang_Thread::set_park_event(oop java_thread, jlong ptr) {
|
||||
if (_park_event_offset > 0) {
|
||||
java_thread->long_field_put(_park_event_offset, ptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
java_thread->long_field_put(_park_event_offset, ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* java_lang_Thread::thread_status_name(oop java_thread) {
|
||||
assert(_thread_status_offset != 0, "Must have thread status");
|
||||
ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
|
||||
switch (status) {
|
||||
case NEW : return "NEW";
|
||||
@ -3635,23 +3597,48 @@ void java_lang_invoke_ResolvedMethodName::set_vmtarget(oop resolved_method, Meth
|
||||
resolved_method->address_field_put(_vmtarget_offset, (address)m);
|
||||
}
|
||||
|
||||
void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop holder) {
|
||||
assert(is_instance(resolved_method), "wrong type");
|
||||
resolved_method->obj_field_put(_vmholder_offset, holder);
|
||||
}
|
||||
|
||||
oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) {
|
||||
const Method* method = m();
|
||||
|
||||
// lookup ResolvedMethod oop in the table, or create a new one and intern it
|
||||
oop resolved_method = ResolvedMethodTable::find_method(m());
|
||||
if (resolved_method == NULL) {
|
||||
InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass();
|
||||
if (!k->is_initialized()) {
|
||||
k->initialize(CHECK_NULL);
|
||||
}
|
||||
oop new_resolved_method = k->allocate_instance(CHECK_NULL);
|
||||
new_resolved_method->address_field_put(_vmtarget_offset, (address)m());
|
||||
// Add a reference to the loader (actually mirror because unsafe anonymous classes will not have
|
||||
// distinct loaders) to ensure the metadata is kept alive.
|
||||
// This mirror may be different than the one in clazz field.
|
||||
new_resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror());
|
||||
resolved_method = ResolvedMethodTable::add_method(m, Handle(THREAD, new_resolved_method));
|
||||
oop resolved_method = ResolvedMethodTable::find_method(method);
|
||||
if (resolved_method != NULL) {
|
||||
return resolved_method;
|
||||
}
|
||||
return resolved_method;
|
||||
|
||||
InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass();
|
||||
if (!k->is_initialized()) {
|
||||
k->initialize(CHECK_NULL);
|
||||
}
|
||||
|
||||
oop new_resolved_method = k->allocate_instance(CHECK_NULL);
|
||||
|
||||
NoSafepointVerifier nsv;
|
||||
|
||||
if (method->is_old()) {
|
||||
method = (method->is_deleted()) ? Universe::throw_no_such_method_error() :
|
||||
method->get_new_method();
|
||||
}
|
||||
|
||||
InstanceKlass* holder = method->method_holder();
|
||||
|
||||
set_vmtarget(new_resolved_method, const_cast<Method*>(method));
|
||||
// Add a reference to the loader (actually mirror because unsafe anonymous classes will not have
|
||||
// distinct loaders) to ensure the metadata is kept alive.
|
||||
// This mirror may be different than the one in clazz field.
|
||||
set_vmholder(new_resolved_method, holder->java_mirror());
|
||||
|
||||
// Set flag in class to indicate this InstanceKlass has entries in the table
|
||||
// to avoid walking table during redefinition if none of the redefined classes
|
||||
// have any membernames in the table.
|
||||
holder->set_has_resolved_methods();
|
||||
|
||||
return ResolvedMethodTable::add_method(method, Handle(THREAD, new_resolved_method));
|
||||
}
|
||||
|
||||
oop java_lang_invoke_LambdaForm::vmentry(oop lform) {
|
||||
|
@ -1063,6 +1063,8 @@ class java_lang_invoke_ResolvedMethodName : AllStatic {
|
||||
static Method* vmtarget(oop resolved_method);
|
||||
static void set_vmtarget(oop resolved_method, Method* method);
|
||||
|
||||
static void set_vmholder(oop resolved_method, oop holder);
|
||||
|
||||
// find or create resolved member name
|
||||
static oop find_resolved_method(const methodHandle& m, TRAPS);
|
||||
|
||||
|
@ -68,7 +68,6 @@
|
||||
#include "oops/symbol.hpp"
|
||||
#include "oops/typeArrayKlass.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
@ -1836,8 +1835,6 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) {
|
||||
}
|
||||
|
||||
GCTraceTime(Debug, gc, phases) t("Trigger cleanups", gc_timer);
|
||||
// Trigger cleaning the ResolvedMethodTable even if no unloading occurred.
|
||||
ResolvedMethodTable::trigger_cleanup();
|
||||
|
||||
if (unloading_occurred) {
|
||||
SymbolTable::trigger_cleanup();
|
||||
|
@ -31,22 +31,33 @@
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
template <typename Container>
|
||||
class OopsDoAndReportCounts {
|
||||
public:
|
||||
void operator()(BoolObjectClosure* is_alive, OopClosure* keep_alive, WeakProcessorPhase phase) {
|
||||
Container::reset_dead_counter();
|
||||
|
||||
CountingSkippedIsAliveClosure<BoolObjectClosure, OopClosure> cl(is_alive, keep_alive);
|
||||
WeakProcessorPhases::oop_storage(phase)->oops_do(&cl);
|
||||
|
||||
Container::inc_dead_counter(cl.num_dead() + cl.num_skipped());
|
||||
Container::finish_dead_counter();
|
||||
}
|
||||
};
|
||||
|
||||
void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
|
||||
FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
|
||||
if (WeakProcessorPhases::is_serial(phase)) {
|
||||
WeakProcessorPhases::processor(phase)(is_alive, keep_alive);
|
||||
} else {
|
||||
if (WeakProcessorPhases::is_stringtable(phase)) {
|
||||
StringTable::reset_dead_counter();
|
||||
|
||||
CountingSkippedIsAliveClosure<BoolObjectClosure, OopClosure> cl(is_alive, keep_alive);
|
||||
WeakProcessorPhases::oop_storage(phase)->oops_do(&cl);
|
||||
|
||||
StringTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
|
||||
StringTable::finish_dead_counter();
|
||||
OopsDoAndReportCounts<StringTable>()(is_alive, keep_alive, phase);
|
||||
} else if (WeakProcessorPhases::is_resolved_method_table(phase)){
|
||||
OopsDoAndReportCounts<ResolvedMethodTable>()(is_alive, keep_alive, phase);
|
||||
} else {
|
||||
WeakProcessorPhases::oop_storage(phase)->weak_oops_do(is_alive, keep_alive);
|
||||
}
|
||||
@ -104,6 +115,7 @@ void WeakProcessor::Task::initialize() {
|
||||
new (states++) StorageState(storage, _nworkers);
|
||||
}
|
||||
StringTable::reset_dead_counter();
|
||||
ResolvedMethodTable::reset_dead_counter();
|
||||
}
|
||||
|
||||
WeakProcessor::Task::Task(uint nworkers) :
|
||||
@ -134,6 +146,7 @@ WeakProcessor::Task::~Task() {
|
||||
FREE_C_HEAP_ARRAY(StorageState, _storage_states);
|
||||
}
|
||||
StringTable::finish_dead_counter();
|
||||
ResolvedMethodTable::finish_dead_counter();
|
||||
}
|
||||
|
||||
void WeakProcessor::GangTask::work(uint worker_id) {
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
class BoolObjectClosure;
|
||||
@ -115,6 +116,9 @@ void WeakProcessor::Task::work(uint worker_id,
|
||||
if (WeakProcessorPhases::is_stringtable(phase)) {
|
||||
StringTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
|
||||
}
|
||||
if (WeakProcessorPhases::is_resolved_method_table(phase)) {
|
||||
ResolvedMethodTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
@ -80,6 +81,7 @@ const char* WeakProcessorPhases::description(Phase phase) {
|
||||
JFR_ONLY(case jfr: return "JFR weak processing";)
|
||||
case jni: return "JNI weak processing";
|
||||
case stringtable: return "StringTable weak processing";
|
||||
case resolved_method_table: return "ResolvedMethodTable weak processing";
|
||||
case vm: return "VM weak processing";
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
@ -101,6 +103,7 @@ OopStorage* WeakProcessorPhases::oop_storage(Phase phase) {
|
||||
switch (phase) {
|
||||
case jni: return JNIHandles::weak_global_handles();
|
||||
case stringtable: return StringTable::weak_storage();
|
||||
case resolved_method_table: return ResolvedMethodTable::weak_storage();
|
||||
case vm: return SystemDictionary::vm_weak_oop_storage();
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
@ -111,3 +114,7 @@ OopStorage* WeakProcessorPhases::oop_storage(Phase phase) {
|
||||
bool WeakProcessorPhases::is_stringtable(Phase phase) {
|
||||
return phase == stringtable;
|
||||
}
|
||||
|
||||
bool WeakProcessorPhases::is_resolved_method_table(Phase phase) {
|
||||
return phase == resolved_method_table;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
// OopStorage phases.
|
||||
jni,
|
||||
stringtable,
|
||||
resolved_method_table,
|
||||
vm
|
||||
};
|
||||
|
||||
@ -68,6 +69,7 @@ public:
|
||||
static OopStorage* oop_storage(Phase phase); // Precondition: is_oop_storage(phase)
|
||||
|
||||
static bool is_stringtable(Phase phase);
|
||||
static bool is_resolved_method_table(Phase phase);
|
||||
};
|
||||
|
||||
typedef WeakProcessorPhases::Phase WeakProcessorPhase;
|
||||
|
82
src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp
Normal file
82
src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
|
||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
|
||||
|
||||
#include "memory/iterator.hpp"
|
||||
|
||||
class ShenandoahHeap;
|
||||
class ShenandoahMarkingContext;
|
||||
class Thread;
|
||||
|
||||
class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
|
||||
private:
|
||||
ShenandoahMarkingContext* const _mark_context;
|
||||
public:
|
||||
inline ShenandoahForwardedIsAliveClosure();
|
||||
inline bool do_object_b(oop obj);
|
||||
};
|
||||
|
||||
class ShenandoahIsAliveClosure: public BoolObjectClosure {
|
||||
private:
|
||||
ShenandoahMarkingContext* const _mark_context;
|
||||
public:
|
||||
inline ShenandoahIsAliveClosure();
|
||||
inline bool do_object_b(oop obj);
|
||||
};
|
||||
|
||||
class ShenandoahIsAliveSelector : public StackObj {
|
||||
private:
|
||||
ShenandoahIsAliveClosure _alive_cl;
|
||||
ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
|
||||
public:
|
||||
inline BoolObjectClosure* is_alive_closure();
|
||||
};
|
||||
|
||||
class ShenandoahUpdateRefsClosure: public OopClosure {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
public:
|
||||
inline ShenandoahUpdateRefsClosure();
|
||||
inline void do_oop(oop* p);
|
||||
inline void do_oop(narrowOop* p);
|
||||
private:
|
||||
template <class T>
|
||||
inline void do_oop_work(T* p);
|
||||
};
|
||||
|
||||
class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
Thread* _thread;
|
||||
public:
|
||||
inline ShenandoahEvacuateUpdateRootsClosure();
|
||||
inline void do_oop(oop* p);
|
||||
inline void do_oop(narrowOop* p);
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
inline void do_oop_work(T* p);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
|
110
src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp
Normal file
110
src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
|
||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
|
||||
|
||||
#include "gc/shenandoah/shenandoahAsserts.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
|
||||
ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
|
||||
_mark_context(ShenandoahHeap::heap()->marking_context()) {
|
||||
}
|
||||
|
||||
bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
|
||||
if (CompressedOops::is_null(obj)) {
|
||||
return false;
|
||||
}
|
||||
obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
|
||||
shenandoah_assert_not_forwarded_if(NULL, obj,
|
||||
(ShenandoahHeap::heap()->is_concurrent_mark_in_progress() ||
|
||||
ShenandoahHeap::heap()->is_concurrent_traversal_in_progress()));
|
||||
return _mark_context->is_marked(obj);
|
||||
}
|
||||
|
||||
ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
|
||||
_mark_context(ShenandoahHeap::heap()->marking_context()) {
|
||||
}
|
||||
|
||||
bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
|
||||
if (CompressedOops::is_null(obj)) {
|
||||
return false;
|
||||
}
|
||||
shenandoah_assert_not_forwarded(NULL, obj);
|
||||
return _mark_context->is_marked(obj);
|
||||
}
|
||||
|
||||
BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
|
||||
return ShenandoahHeap::heap()->has_forwarded_objects() ?
|
||||
reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl) :
|
||||
reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
|
||||
}
|
||||
|
||||
ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() :
|
||||
_heap(ShenandoahHeap::heap()) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
|
||||
T o = RawAccess<>::oop_load(p);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
_heap->update_with_forwarded_not_null(p, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
|
||||
void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
|
||||
ShenandoahEvacuateUpdateRootsClosure::ShenandoahEvacuateUpdateRootsClosure() :
|
||||
_heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahEvacuateUpdateRootsClosure::do_oop_work(T* p) {
|
||||
assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
|
||||
|
||||
T o = RawAccess<>::oop_load(p);
|
||||
if (! CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (_heap->in_collection_set(obj)) {
|
||||
shenandoah_assert_marked(p, obj);
|
||||
oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
|
||||
if (oopDesc::equals_raw(resolved, obj)) {
|
||||
resolved = _heap->evacuate_object(obj, _thread);
|
||||
}
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ShenandoahEvacuateUpdateRootsClosure::do_oop(oop* p) {
|
||||
do_oop_work(p);
|
||||
}
|
||||
|
||||
void ShenandoahEvacuateUpdateRootsClosure::do_oop(narrowOop* p) {
|
||||
do_oop_work(p);
|
||||
}
|
||||
|
||||
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
|
@ -33,6 +33,7 @@
|
||||
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
|
||||
|
||||
#include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "gc/shenandoah/shenandoahAllocTracker.hpp"
|
||||
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahBrooksPointer.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
|
||||
#include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
|
||||
@ -70,8 +71,6 @@
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "services/mallocTracker.hpp"
|
||||
|
||||
ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() : _heap(ShenandoahHeap::heap()) {}
|
||||
|
||||
#ifdef ASSERT
|
||||
template <class T>
|
||||
void ShenandoahAssertToSpaceClosure::do_oop_work(T* p) {
|
||||
@ -459,8 +458,8 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
|
||||
_max_workers = MAX2(_max_workers, 1U);
|
||||
_workers = new ShenandoahWorkGang("Shenandoah GC Threads", _max_workers,
|
||||
/* are_GC_task_threads */true,
|
||||
/* are_ConcurrentGC_threads */false);
|
||||
/* are_GC_task_threads */ true,
|
||||
/* are_ConcurrentGC_threads */ true);
|
||||
if (_workers == NULL) {
|
||||
vm_exit_during_initialization("Failed necessary allocation.");
|
||||
} else {
|
||||
@ -470,7 +469,8 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
if (ShenandoahParallelSafepointThreads > 1) {
|
||||
_safepoint_workers = new ShenandoahWorkGang("Safepoint Cleanup Thread",
|
||||
ShenandoahParallelSafepointThreads,
|
||||
false, false);
|
||||
/* are_GC_task_threads */ false,
|
||||
/* are_ConcurrentGC_threads */ false);
|
||||
_safepoint_workers->initialize_workers();
|
||||
}
|
||||
}
|
||||
@ -939,43 +939,6 @@ size_t ShenandoahHeap::min_dummy_object_size() const {
|
||||
return CollectedHeap::min_dummy_object_size() + ShenandoahBrooksPointer::word_size();
|
||||
}
|
||||
|
||||
class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
Thread* _thread;
|
||||
public:
|
||||
ShenandoahEvacuateUpdateRootsClosure() :
|
||||
_heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
|
||||
}
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
void do_oop_work(T* p) {
|
||||
assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
|
||||
|
||||
T o = RawAccess<>::oop_load(p);
|
||||
if (! CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (_heap->in_collection_set(obj)) {
|
||||
shenandoah_assert_marked(p, obj);
|
||||
oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
|
||||
if (oopDesc::equals_raw(resolved, obj)) {
|
||||
resolved = _heap->evacuate_object(obj, _thread);
|
||||
}
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void do_oop(oop* p) {
|
||||
do_oop_work(p);
|
||||
}
|
||||
void do_oop(narrowOop* p) {
|
||||
do_oop_work(p);
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahConcurrentEvacuateRegionObjectClosure : public ObjectClosure {
|
||||
private:
|
||||
ShenandoahHeap* const _heap;
|
||||
@ -1883,31 +1846,6 @@ HeapWord* ShenandoahHeap::tlab_post_allocation_setup(HeapWord* obj) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
|
||||
_mark_context(ShenandoahHeap::heap()->marking_context()) {
|
||||
}
|
||||
|
||||
ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
|
||||
_mark_context(ShenandoahHeap::heap()->marking_context()) {
|
||||
}
|
||||
|
||||
bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
|
||||
if (CompressedOops::is_null(obj)) {
|
||||
return false;
|
||||
}
|
||||
obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
|
||||
shenandoah_assert_not_forwarded_if(NULL, obj, ShenandoahHeap::heap()->is_concurrent_mark_in_progress() || ShenandoahHeap::heap()->is_concurrent_traversal_in_progress());
|
||||
return _mark_context->is_marked(obj);
|
||||
}
|
||||
|
||||
bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
|
||||
if (CompressedOops::is_null(obj)) {
|
||||
return false;
|
||||
}
|
||||
shenandoah_assert_not_forwarded(NULL, obj);
|
||||
return _mark_context->is_marked(obj);
|
||||
}
|
||||
|
||||
void ShenandoahHeap::ref_processing_init() {
|
||||
assert(_max_workers > 0, "Sanity");
|
||||
|
||||
@ -2878,8 +2816,3 @@ size_t ShenandoahHeap::obj_size(oop obj) const {
|
||||
ptrdiff_t ShenandoahHeap::cell_header_size() const {
|
||||
return ShenandoahBrooksPointer::byte_size();
|
||||
}
|
||||
|
||||
BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
|
||||
return ShenandoahHeap::heap()->has_forwarded_objects() ? reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl)
|
||||
: reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
|
||||
}
|
||||
|
@ -91,19 +91,6 @@ public:
|
||||
virtual bool is_thread_safe() { return false; }
|
||||
};
|
||||
|
||||
class ShenandoahUpdateRefsClosure: public OopClosure {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
|
||||
template <class T>
|
||||
inline void do_oop_work(T* p);
|
||||
|
||||
public:
|
||||
ShenandoahUpdateRefsClosure();
|
||||
inline void do_oop(oop* p);
|
||||
inline void do_oop(narrowOop* p);
|
||||
};
|
||||
|
||||
#ifdef ASSERT
|
||||
class ShenandoahAssertToSpaceClosure : public OopClosure {
|
||||
private:
|
||||
@ -115,34 +102,6 @@ public:
|
||||
};
|
||||
#endif
|
||||
|
||||
class ShenandoahAlwaysTrueClosure : public BoolObjectClosure {
|
||||
public:
|
||||
bool do_object_b(oop p) { return true; }
|
||||
};
|
||||
|
||||
class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
|
||||
private:
|
||||
ShenandoahMarkingContext* const _mark_context;
|
||||
public:
|
||||
ShenandoahForwardedIsAliveClosure();
|
||||
bool do_object_b(oop obj);
|
||||
};
|
||||
|
||||
class ShenandoahIsAliveClosure: public BoolObjectClosure {
|
||||
private:
|
||||
ShenandoahMarkingContext* const _mark_context;
|
||||
public:
|
||||
ShenandoahIsAliveClosure();
|
||||
bool do_object_b(oop obj);
|
||||
};
|
||||
|
||||
class ShenandoahIsAliveSelector : public StackObj {
|
||||
private:
|
||||
ShenandoahIsAliveClosure _alive_cl;
|
||||
ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
|
||||
public:
|
||||
BoolObjectClosure* is_alive_closure();
|
||||
};
|
||||
|
||||
// Shenandoah GC is low-pause concurrent GC that uses Brooks forwarding pointers
|
||||
// to encode forwarding data. See BrooksPointer for details on forwarding data encoding.
|
||||
|
@ -46,17 +46,6 @@
|
||||
#include "utilities/copy.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
template <class T>
|
||||
void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
|
||||
T o = RawAccess<>::oop_load(p);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
_heap->update_with_forwarded_not_null(p, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
|
||||
void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
|
||||
inline ShenandoahHeapRegion* ShenandoahRegionIterator::next() {
|
||||
size_t new_index = Atomic::add((size_t) 1, &_index);
|
||||
|
@ -51,6 +51,7 @@ class outputStream;
|
||||
f(scan_jfr_weak_roots, " S: JFR Weak Roots") \
|
||||
f(scan_jni_weak_roots, " S: JNI Weak Roots") \
|
||||
f(scan_stringtable_roots, " S: String Table Roots") \
|
||||
f(scan_resolved_method_table_roots, " S: Resolved Table Roots") \
|
||||
f(scan_vm_weak_roots, " S: VM Weak Roots") \
|
||||
f(scan_synchronizer_roots, " S: Synchronizer Roots") \
|
||||
f(scan_management_roots, " S: Management Roots") \
|
||||
@ -76,6 +77,7 @@ class outputStream;
|
||||
f(update_jfr_weak_roots, " U: JFR Weak Roots") \
|
||||
f(update_jni_weak_roots, " U: JNI Weak Roots") \
|
||||
f(update_stringtable_roots, " U: String Table Roots") \
|
||||
f(update_resolved_method_table_roots, " U: Resolved Table Roots") \
|
||||
f(update_vm_weak_roots, " U: VM Weak Roots") \
|
||||
f(update_synchronizer_roots, " U: Synchronizer Roots") \
|
||||
f(update_management_roots, " U: Management Roots") \
|
||||
@ -109,6 +111,7 @@ class outputStream;
|
||||
f(evac_jfr_weak_roots, " E: JFR Weak Roots") \
|
||||
f(evac_jni_weak_roots, " E: JNI Weak Roots") \
|
||||
f(evac_stringtable_roots, " E: String Table Roots") \
|
||||
f(evac_resolved_method_table_roots, " E: Resolved Table Roots") \
|
||||
f(evac_vm_weak_roots, " E: VM Weak Roots") \
|
||||
f(evac_synchronizer_roots, " E: Synchronizer Roots") \
|
||||
f(evac_management_roots, " E: Management Roots") \
|
||||
@ -139,6 +142,7 @@ class outputStream;
|
||||
f(final_update_jfr_weak_roots, " UR: JFR Weak Roots") \
|
||||
f(final_update_jni_weak_roots, " UR: JNI Weak Roots") \
|
||||
f(final_update_stringtable_roots, " UR: String Table Roots") \
|
||||
f(final_update_resolved_method_table_roots, " UR: Resolved Table Roots") \
|
||||
f(final_update_vm_weak_roots, " UR: VM Weak Roots") \
|
||||
f(final_update_refs_synchronizer_roots, " UR: Synchronizer Roots") \
|
||||
f(final_update_refs_management_roots, " UR: Management Roots") \
|
||||
@ -164,6 +168,7 @@ class outputStream;
|
||||
f(degen_gc_update_jfr_weak_roots, " DU: JFR Weak Roots") \
|
||||
f(degen_gc_update_jni_weak_roots, " DU: JNI Weak Roots") \
|
||||
f(degen_gc_update_stringtable_roots, " DU: String Table Roots") \
|
||||
f(degen_gc_update_resolved_method_table_roots, " DU: Resolved Table Roots") \
|
||||
f(degen_gc_update_vm_weak_roots, " DU: VM Weak Roots") \
|
||||
f(degen_gc_update_synchronizer_roots, " DU: Synchronizer Roots") \
|
||||
f(degen_gc_update_management_roots, " DU: Management Roots") \
|
||||
@ -190,6 +195,7 @@ class outputStream;
|
||||
f(init_traversal_gc_jfr_weak_roots, " TI: JFR Weak Roots") \
|
||||
f(init_traversal_gc_jni_weak_roots, " TI: JNI Weak Roots") \
|
||||
f(init_traversal_gc_stringtable_roots, " TI: String Table Roots") \
|
||||
f(init_traversal_gc_resolved_method_table_roots, " TI: Resolved Table Roots") \
|
||||
f(init_traversal_gc_vm_weak_roots, " TI: VM Weak Roots") \
|
||||
f(init_traversal_gc_synchronizer_roots, " TI: Synchronizer Roots") \
|
||||
f(init_traversal_gc_management_roots, " TI: Management Roots") \
|
||||
@ -213,6 +219,7 @@ class outputStream;
|
||||
f(final_traversal_gc_jfr_weak_roots, " TF: JFR Weak Roots") \
|
||||
f(final_traversal_gc_jni_weak_roots, " TF: JNI Weak Roots") \
|
||||
f(final_traversal_gc_stringtable_roots, " TF: String Table Roots") \
|
||||
f(final_traversal_gc_resolved_method_table_roots, " TF: Resolved Table Roots") \
|
||||
f(final_traversal_gc_vm_weak_roots, " TF: VM Weak Roots") \
|
||||
f(final_traversal_gc_synchronizer_roots, " TF: Synchronizer Roots") \
|
||||
f(final_traversal_gc_management_roots, " TF: Management Roots") \
|
||||
@ -225,24 +232,25 @@ class outputStream;
|
||||
f(final_traversal_gc_termination, " TF: Termination") \
|
||||
\
|
||||
/* Per-thread timer block, should have "roots" counters in consistent order */ \
|
||||
f(final_traversal_update_roots, " Update Roots") \
|
||||
f(final_traversal_update_thread_roots, " TU: Thread Roots") \
|
||||
f(final_traversal_update_code_roots, " TU: Code Cache Roots") \
|
||||
f(final_traversal_update_universe_roots, " TU: Universe Roots") \
|
||||
f(final_traversal_update_jni_roots, " TU: JNI Roots") \
|
||||
f(final_traversal_update_jvmti_weak_roots, " TU: JVMTI Weak Roots") \
|
||||
f(final_traversal_update_jfr_weak_roots, " TU: JFR Weak Roots") \
|
||||
f(final_traversal_update_jni_weak_roots, " TU: JNI Weak Roots") \
|
||||
f(final_traversal_update_stringtable_roots, " TU: String Table Roots") \
|
||||
f(final_traversal_update_vm_weak_roots, " TU: VM Weak Roots") \
|
||||
f(final_traversal_update_synchronizer_roots, " TU: Synchronizer Roots") \
|
||||
f(final_traversal_update_management_roots, " TU: Management Roots") \
|
||||
f(final_traversal_update_system_dict_roots, " TU: System Dict Roots") \
|
||||
f(final_traversal_update_cldg_roots, " TU: CLDG Roots") \
|
||||
f(final_traversal_update_jvmti_roots, " TU: JVMTI Roots") \
|
||||
f(final_traversal_update_string_dedup_table_roots, " TU: Dedup Table Roots") \
|
||||
f(final_traversal_update_string_dedup_queue_roots, " TU: Dedup Queue Roots") \
|
||||
f(final_traversal_update_finish_queues, " TU: Finish Queues") \
|
||||
f(final_traversal_update_roots, " Update Roots") \
|
||||
f(final_traversal_update_thread_roots, " TU: Thread Roots") \
|
||||
f(final_traversal_update_code_roots, " TU: Code Cache Roots") \
|
||||
f(final_traversal_update_universe_roots, " TU: Universe Roots") \
|
||||
f(final_traversal_update_jni_roots, " TU: JNI Roots") \
|
||||
f(final_traversal_update_jvmti_weak_roots, " TU: JVMTI Weak Roots") \
|
||||
f(final_traversal_update_jfr_weak_roots, " TU: JFR Weak Roots") \
|
||||
f(final_traversal_update_jni_weak_roots, " TU: JNI Weak Roots") \
|
||||
f(final_traversal_update_stringtable_roots, " TU: String Table Roots") \
|
||||
f(final_traversal_update_resolved_method_table_roots, " TU: Resolved Table Roots") \
|
||||
f(final_traversal_update_vm_weak_roots, " TU: VM Weak Roots") \
|
||||
f(final_traversal_update_synchronizer_roots, " TU: Synchronizer Roots") \
|
||||
f(final_traversal_update_management_roots, " TU: Management Roots") \
|
||||
f(final_traversal_update_system_dict_roots, " TU: System Dict Roots") \
|
||||
f(final_traversal_update_cldg_roots, " TU: CLDG Roots") \
|
||||
f(final_traversal_update_jvmti_roots, " TU: JVMTI Roots") \
|
||||
f(final_traversal_update_string_dedup_table_roots, " TU: Dedup Table Roots") \
|
||||
f(final_traversal_update_string_dedup_queue_roots, " TU: Dedup Queue Roots") \
|
||||
f(final_traversal_update_finish_queues, " TU: Finish Queues") \
|
||||
\
|
||||
f(traversal_gc_cleanup, " Cleanup") \
|
||||
\
|
||||
@ -261,6 +269,7 @@ class outputStream;
|
||||
f(full_gc_jfr_weak_roots, " F: JFR Weak Roots") \
|
||||
f(full_gc_jni_weak_roots, " F: JNI Weak Roots") \
|
||||
f(full_gc_stringtable_roots, " F: String Table Roots") \
|
||||
f(full_gc_resolved_method_table_roots, " F: Resolved Table Roots") \
|
||||
f(full_gc_vm_weak_roots, " F: VM Weak Roots") \
|
||||
f(full_gc_synchronizer_roots, " F: Synchronizer Roots") \
|
||||
f(full_gc_management_roots, " F: Management Roots") \
|
||||
@ -311,23 +320,24 @@ class outputStream;
|
||||
// end
|
||||
|
||||
#define SHENANDOAH_GC_PAR_PHASE_DO(f) \
|
||||
f(ThreadRoots, "Thread Roots (ms):") \
|
||||
f(CodeCacheRoots, "CodeCache Roots (ms):") \
|
||||
f(UniverseRoots, "Universe Roots (ms):") \
|
||||
f(JNIRoots, "JNI Handles Roots (ms):") \
|
||||
f(JVMTIWeakRoots, "JVMTI Weak Roots (ms):") \
|
||||
f(JFRWeakRoots, "JFR Weak Roots (ms):") \
|
||||
f(JNIWeakRoots, "JNI Weak Roots (ms):") \
|
||||
f(StringTableRoots, "StringTable Roots(ms):") \
|
||||
f(VMWeakRoots, "VM Weak Roots(ms)") \
|
||||
f(ObjectSynchronizerRoots, "ObjectSynchronizer Roots (ms):") \
|
||||
f(ManagementRoots, "Management Roots (ms):") \
|
||||
f(SystemDictionaryRoots, "SystemDictionary Roots (ms):") \
|
||||
f(CLDGRoots, "CLDG Roots (ms):") \
|
||||
f(JVMTIRoots, "JVMTI Roots (ms):") \
|
||||
f(StringDedupTableRoots, "String Dedup Table Roots (ms):") \
|
||||
f(StringDedupQueueRoots, "String Dedup Queue Roots (ms):") \
|
||||
f(FinishQueues, "Finish Queues (ms):") \
|
||||
f(ThreadRoots, "Thread Roots (ms):") \
|
||||
f(CodeCacheRoots, "CodeCache Roots (ms):") \
|
||||
f(UniverseRoots, "Universe Roots (ms):") \
|
||||
f(JNIRoots, "JNI Handles Roots (ms):") \
|
||||
f(JVMTIWeakRoots, "JVMTI Weak Roots (ms):") \
|
||||
f(JFRWeakRoots, "JFR Weak Roots (ms):") \
|
||||
f(JNIWeakRoots, "JNI Weak Roots (ms):") \
|
||||
f(StringTableRoots, "StringTable Roots(ms):") \
|
||||
f(ResolvedMethodTableRoots, "Resolved Table Roots(ms):") \
|
||||
f(VMWeakRoots, "VM Weak Roots(ms)") \
|
||||
f(ObjectSynchronizerRoots, "ObjectSynchronizer Roots (ms):") \
|
||||
f(ManagementRoots, "Management Roots (ms):") \
|
||||
f(SystemDictionaryRoots, "SystemDictionary Roots (ms):") \
|
||||
f(CLDGRoots, "CLDG Roots (ms):") \
|
||||
f(JVMTIRoots, "JVMTI Roots (ms):") \
|
||||
f(StringDedupTableRoots, "String Dedup Table Roots (ms):") \
|
||||
f(StringDedupQueueRoots, "String Dedup Queue Roots (ms):") \
|
||||
f(FinishQueues, "Finish Queues (ms):") \
|
||||
// end
|
||||
|
||||
class ShenandoahPhaseTimings : public CHeapObj<mtGC> {
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.hpp"
|
||||
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
||||
@ -48,14 +49,15 @@ struct PhaseMap {
|
||||
|
||||
static const struct PhaseMap phase_mapping[] = {
|
||||
#if INCLUDE_JVMTI
|
||||
{WeakProcessorPhases::jvmti, ShenandoahPhaseTimings::JVMTIWeakRoots},
|
||||
{WeakProcessorPhases::jvmti, ShenandoahPhaseTimings::JVMTIWeakRoots},
|
||||
#endif
|
||||
#if INCLUDE_JFR
|
||||
{WeakProcessorPhases::jfr, ShenandoahPhaseTimings::JFRWeakRoots},
|
||||
{WeakProcessorPhases::jfr, ShenandoahPhaseTimings::JFRWeakRoots},
|
||||
#endif
|
||||
{WeakProcessorPhases::jni, ShenandoahPhaseTimings::JNIWeakRoots},
|
||||
{WeakProcessorPhases::stringtable, ShenandoahPhaseTimings::StringTableRoots},
|
||||
{WeakProcessorPhases::vm, ShenandoahPhaseTimings::VMWeakRoots}
|
||||
{WeakProcessorPhases::jni, ShenandoahPhaseTimings::JNIWeakRoots},
|
||||
{WeakProcessorPhases::stringtable, ShenandoahPhaseTimings::StringTableRoots},
|
||||
{WeakProcessorPhases::resolved_method_table, ShenandoahPhaseTimings::ResolvedMethodTableRoots},
|
||||
{WeakProcessorPhases::vm, ShenandoahPhaseTimings::VMWeakRoots}
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(phase_mapping) / sizeof(PhaseMap) == WeakProcessorPhases::phase_count);
|
||||
@ -64,7 +66,6 @@ ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_wo
|
||||
ShenandoahPhaseTimings::Phase phase) :
|
||||
_process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)),
|
||||
_srs(n_workers),
|
||||
_par_state_string(StringTable::weak_storage()),
|
||||
_phase(phase),
|
||||
_coderoots_all_iterator(ShenandoahCodeRoots::iterator()),
|
||||
_weak_processor_timings(n_workers),
|
||||
@ -242,10 +243,7 @@ ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_wo
|
||||
_evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
|
||||
_srs(n_workers),
|
||||
_phase(phase),
|
||||
_coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
|
||||
_par_state_string(StringTable::weak_storage())
|
||||
|
||||
{
|
||||
_coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()) {
|
||||
heap->phase_timings()->record_workers_start(_phase);
|
||||
if (ShenandoahStringDedup::is_enabled()) {
|
||||
StringDedup::gc_prologue(false);
|
||||
|
@ -56,7 +56,6 @@ enum Shenandoah_process_roots_tasks {
|
||||
class ShenandoahRootProcessor : public StackObj {
|
||||
SubTasksDone* _process_strong_tasks;
|
||||
StrongRootsScope _srs;
|
||||
OopStorage::ParState<false, false> _par_state_string;
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
ParallelCLDRootIterator _cld_iterator;
|
||||
ShenandoahAllCodeRootsIterator _coderoots_all_iterator;
|
||||
@ -120,7 +119,6 @@ class ShenandoahRootEvacuator : public StackObj {
|
||||
StrongRootsScope _srs;
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
|
||||
OopStorage::ParState<false, false> _par_state_string;
|
||||
|
||||
enum Shenandoah_evacuate_roots_tasks {
|
||||
SHENANDOAH_EVAC_Universe_oops_do,
|
||||
|
@ -92,7 +92,7 @@ void ShenandoahStringDedup::parallel_oops_do(BoolObjectClosure* is_alive, OopClo
|
||||
void ShenandoahStringDedup::oops_do_slow(OopClosure* cl) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
|
||||
assert(is_enabled(), "String deduplication not enabled");
|
||||
ShenandoahAlwaysTrueClosure always_true;
|
||||
AlwaysTrueClosure always_true;
|
||||
StringDedupUnlinkOrOopsDoClosure sd_cl(&always_true, cl);
|
||||
StringDedupQueue::unlink_or_oops_do(&sd_cl);
|
||||
StringDedupTable::unlink_or_oops_do(&sd_cl, 0);
|
||||
|
@ -76,8 +76,11 @@ ShenandoahTerminationTracker::ShenandoahTerminationTracker(ShenandoahPhaseTiming
|
||||
phase == ShenandoahPhaseTimings::full_gc_weakrefs_termination,
|
||||
"Only these phases");
|
||||
|
||||
assert(Thread::current()->is_VM_thread() || Thread::current()->is_ConcurrentGC_thread(),
|
||||
"Called from wrong thread");
|
||||
assert(!Thread::current()->is_Worker_thread() &&
|
||||
(Thread::current()->is_VM_thread() ||
|
||||
Thread::current()->is_ConcurrentGC_thread()),
|
||||
"Called from wrong thread");
|
||||
|
||||
_current_termination_phase = phase;
|
||||
ShenandoahHeap::heap()->phase_timings()->termination_times()->reset();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahCodeRoots.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
|
||||
|
@ -100,9 +100,10 @@ ShenandoahGCPauseMark::~ShenandoahGCPauseMark() {
|
||||
|
||||
ShenandoahGCPhase::ShenandoahGCPhase(const ShenandoahPhaseTimings::Phase phase) :
|
||||
_heap(ShenandoahHeap::heap()), _phase(phase) {
|
||||
assert(Thread::current()->is_VM_thread() ||
|
||||
Thread::current()->is_ConcurrentGC_thread(),
|
||||
"Must be set by these threads");
|
||||
assert(!Thread::current()->is_Worker_thread() &&
|
||||
(Thread::current()->is_VM_thread() ||
|
||||
Thread::current()->is_ConcurrentGC_thread()),
|
||||
"Must be set by these threads");
|
||||
_parent_phase = _current_phase;
|
||||
_current_phase = phase;
|
||||
|
||||
|
@ -55,11 +55,7 @@ bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
|
||||
|
||||
// Heal oops and disarm
|
||||
ZNMethodOopClosure cl;
|
||||
nm->oops_do(&cl);
|
||||
nm->fix_oop_relocations();
|
||||
|
||||
OrderAccess::release();
|
||||
|
||||
ZNMethod::nmethod_oops_do(nm, &cl);
|
||||
disarm(nm);
|
||||
|
||||
return true;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
@ -80,6 +81,7 @@ static const ZStatSubPhase ZSubPhaseConcurrentWeakRoots("Concurrent Weak Roots")
|
||||
static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsVMWeakHandles("Concurrent Weak Roots VMWeakHandles");
|
||||
static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsJNIWeakHandles("Concurrent Weak Roots JNIWeakHandles");
|
||||
static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsStringTable("Concurrent Weak Roots StringTable");
|
||||
static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsResolvedMethodTable("Concurrent Weak Roots ResolvedMethodTable");
|
||||
|
||||
template <typename T, void (T::*F)(ZRootsIteratorClosure*)>
|
||||
ZSerialOopsDo<T, F>::ZSerialOopsDo(T* iter) :
|
||||
@ -341,14 +343,18 @@ ZConcurrentWeakRootsIterator::ZConcurrentWeakRootsIterator() :
|
||||
_vm_weak_handles_iter(SystemDictionary::vm_weak_oop_storage()),
|
||||
_jni_weak_handles_iter(JNIHandles::weak_global_handles()),
|
||||
_string_table_iter(StringTable::weak_storage()),
|
||||
_resolved_method_table_iter(ResolvedMethodTable::weak_storage()),
|
||||
_vm_weak_handles(this),
|
||||
_jni_weak_handles(this),
|
||||
_string_table(this) {
|
||||
_string_table(this),
|
||||
_resolved_method_table(this) {
|
||||
StringTable::reset_dead_counter();
|
||||
ResolvedMethodTable::reset_dead_counter();
|
||||
}
|
||||
|
||||
ZConcurrentWeakRootsIterator::~ZConcurrentWeakRootsIterator() {
|
||||
StringTable::finish_dead_counter();
|
||||
ResolvedMethodTable::finish_dead_counter();
|
||||
}
|
||||
|
||||
void ZConcurrentWeakRootsIterator::do_vm_weak_handles(ZRootsIteratorClosure* cl) {
|
||||
@ -361,18 +367,19 @@ void ZConcurrentWeakRootsIterator::do_jni_weak_handles(ZRootsIteratorClosure* cl
|
||||
_jni_weak_handles_iter.oops_do(cl);
|
||||
}
|
||||
|
||||
class ZStringTableDeadCounterClosure : public ZRootsIteratorClosure {
|
||||
template <class Container>
|
||||
class ZDeadCounterClosure : public ZRootsIteratorClosure {
|
||||
private:
|
||||
ZRootsIteratorClosure* const _cl;
|
||||
size_t _ndead;
|
||||
|
||||
public:
|
||||
ZStringTableDeadCounterClosure(ZRootsIteratorClosure* cl) :
|
||||
ZDeadCounterClosure(ZRootsIteratorClosure* cl) :
|
||||
_cl(cl),
|
||||
_ndead(0) {}
|
||||
|
||||
~ZStringTableDeadCounterClosure() {
|
||||
StringTable::inc_dead_counter(_ndead);
|
||||
~ZDeadCounterClosure() {
|
||||
Container::inc_dead_counter(_ndead);
|
||||
}
|
||||
|
||||
virtual void do_oop(oop* p) {
|
||||
@ -389,15 +396,22 @@ public:
|
||||
|
||||
void ZConcurrentWeakRootsIterator::do_string_table(ZRootsIteratorClosure* cl) {
|
||||
ZStatTimer timer(ZSubPhaseConcurrentWeakRootsStringTable);
|
||||
ZStringTableDeadCounterClosure counter_cl(cl);
|
||||
ZDeadCounterClosure<StringTable> counter_cl(cl);
|
||||
_string_table_iter.oops_do(&counter_cl);
|
||||
}
|
||||
|
||||
void ZConcurrentWeakRootsIterator::do_resolved_method_table(ZRootsIteratorClosure* cl) {
|
||||
ZStatTimer timer(ZSubPhaseConcurrentWeakRootsResolvedMethodTable);
|
||||
ZDeadCounterClosure<ResolvedMethodTable> counter_cl(cl);
|
||||
_resolved_method_table_iter.oops_do(&counter_cl);
|
||||
}
|
||||
|
||||
void ZConcurrentWeakRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
||||
ZStatTimer timer(ZSubPhaseConcurrentWeakRoots);
|
||||
_vm_weak_handles.oops_do(cl);
|
||||
_jni_weak_handles.oops_do(cl);
|
||||
_string_table.oops_do(cl);
|
||||
_resolved_method_table.oops_do(cl);
|
||||
}
|
||||
|
||||
ZThreadRootsIterator::ZThreadRootsIterator() :
|
||||
|
@ -149,14 +149,17 @@ private:
|
||||
ZOopStorageIterator _vm_weak_handles_iter;
|
||||
ZOopStorageIterator _jni_weak_handles_iter;
|
||||
ZOopStorageIterator _string_table_iter;
|
||||
ZOopStorageIterator _resolved_method_table_iter;
|
||||
|
||||
void do_vm_weak_handles(ZRootsIteratorClosure* cl);
|
||||
void do_jni_weak_handles(ZRootsIteratorClosure* cl);
|
||||
void do_string_table(ZRootsIteratorClosure* cl);
|
||||
void do_resolved_method_table(ZRootsIteratorClosure* cl);
|
||||
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_vm_weak_handles> _vm_weak_handles;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_jni_weak_handles> _jni_weak_handles;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_string_table> _string_table;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_vm_weak_handles> _vm_weak_handles;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_jni_weak_handles> _jni_weak_handles;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_string_table> _string_table;
|
||||
ZParallelOopsDo<ZConcurrentWeakRootsIterator, &ZConcurrentWeakRootsIterator::do_resolved_method_table> _resolved_method_table;
|
||||
|
||||
public:
|
||||
ZConcurrentWeakRootsIterator();
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
|
||||
ZLocker<ZReentrantLock> locker(lock);
|
||||
ZIsUnloadingOopClosure cl;
|
||||
nm->oops_do(&cl, true /* allow_zombie */);
|
||||
ZNMethod::nmethod_oops_do(nm, &cl);
|
||||
return cl.is_unloading();
|
||||
}
|
||||
};
|
||||
|
@ -156,7 +156,7 @@ void InterpreterRuntime::set_bcp_and_mdp(address bcp, JavaThread *thread) {
|
||||
// Constants
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
|
||||
JRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
|
||||
// access constant pool
|
||||
LastFrameAccessor last_frame(thread);
|
||||
ConstantPool* pool = last_frame.method()->constants();
|
||||
@ -167,9 +167,9 @@ IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
|
||||
Klass* klass = pool->klass_at(index, CHECK);
|
||||
oop java_class = klass->java_mirror();
|
||||
thread->set_vm_result(java_class);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
|
||||
JRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
|
||||
assert(bytecode == Bytecodes::_ldc ||
|
||||
bytecode == Bytecodes::_ldc_w ||
|
||||
bytecode == Bytecodes::_ldc2_w ||
|
||||
@ -219,13 +219,13 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::C
|
||||
thread->set_vm_result_2((Metadata*)flags);
|
||||
}
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Allocation
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index))
|
||||
JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index))
|
||||
Klass* k = pool->klass_at(index, CHECK);
|
||||
InstanceKlass* klass = InstanceKlass::cast(k);
|
||||
|
||||
@ -251,23 +251,23 @@ IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool,
|
||||
// because the _breakpoint bytecode would be lost.
|
||||
oop obj = klass->allocate_instance(CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size))
|
||||
JRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size))
|
||||
oop obj = oopFactory::new_typeArray(type, size, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
|
||||
JRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
|
||||
Klass* klass = pool->klass_at(index, CHECK);
|
||||
objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
|
||||
JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
|
||||
// We may want to pass in more arguments - could make this slightly faster
|
||||
LastFrameAccessor last_frame(thread);
|
||||
ConstantPool* constants = last_frame.method()->constants();
|
||||
@ -292,18 +292,18 @@ IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* fir
|
||||
}
|
||||
oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK);
|
||||
thread->set_vm_result(obj);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
|
||||
JRT_ENTRY(void, InterpreterRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
|
||||
assert(oopDesc::is_oop(obj), "must be a valid oop");
|
||||
assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
|
||||
InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
// Quicken instance-of and check-cast bytecodes
|
||||
IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
|
||||
// Force resolving; quicken the bytecode
|
||||
LastFrameAccessor last_frame(thread);
|
||||
int which = last_frame.get_index_u2(Bytecodes::_checkcast);
|
||||
@ -314,7 +314,7 @@ IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
|
||||
// assert( cpool->tag_at(which).is_unresolved_klass(), "should only come here to quicken bytecodes" );
|
||||
Klass* klass = cpool->klass_at(which, CHECK);
|
||||
thread->set_vm_result_2(klass);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
@ -354,10 +354,10 @@ void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
||||
|
||||
#ifdef CC_INTERP
|
||||
// As legacy note_trap, but we have more arguments.
|
||||
IRT_ENTRY(void, InterpreterRuntime::note_trap(JavaThread* thread, int reason, Method *method, int trap_bci))
|
||||
JRT_ENTRY(void, InterpreterRuntime::note_trap(JavaThread* thread, int reason, Method *method, int trap_bci))
|
||||
methodHandle trap_method(method);
|
||||
note_trap_inner(thread, reason, trap_method, trap_bci, THREAD);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
// Class Deoptimization is not visible in BytecodeInterpreter, so we need a wrapper
|
||||
// for each exception.
|
||||
@ -394,16 +394,16 @@ static Handle get_preinitialized_exception(Klass* k, TRAPS) {
|
||||
// space left we use the pre-allocated & pre-initialized StackOverflowError
|
||||
// klass to create an stack overflow error instance. We do not call its
|
||||
// constructor for the same reason (it is empty, anyway).
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* thread))
|
||||
Handle exception = get_preinitialized_exception(
|
||||
SystemDictionary::StackOverflowError_klass(),
|
||||
CHECK);
|
||||
// Increment counter for hs_err file reporting
|
||||
Atomic::inc(&Exceptions::_stack_overflow_errors);
|
||||
THROW_HANDLE(exception);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread))
|
||||
Handle exception = get_preinitialized_exception(
|
||||
SystemDictionary::StackOverflowError_klass(),
|
||||
CHECK);
|
||||
@ -412,9 +412,9 @@ IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread*
|
||||
// Increment counter for hs_err file reporting
|
||||
Atomic::inc(&Exceptions::_stack_overflow_errors);
|
||||
THROW_HANDLE(exception);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* thread, char* name, char* message))
|
||||
JRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* thread, char* name, char* message))
|
||||
// lookup exception klass
|
||||
TempNewSymbol s = SymbolTable::new_symbol(name, CHECK);
|
||||
if (ProfileTraps) {
|
||||
@ -427,10 +427,10 @@ IRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* thread, char* n
|
||||
// create exception
|
||||
Handle exception = Exceptions::new_exception(thread, s, message);
|
||||
thread->set_vm_result(exception());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* thread, char* name, oopDesc* obj))
|
||||
JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* thread, char* name, oopDesc* obj))
|
||||
// Produce the error message first because note_trap can safepoint
|
||||
ResourceMark rm(thread);
|
||||
const char* klass_name = obj->klass()->external_name();
|
||||
@ -442,9 +442,9 @@ IRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* thread, c
|
||||
// create exception, with klass name as detail message
|
||||
Handle exception = Exceptions::new_exception(thread, s, klass_name);
|
||||
thread->set_vm_result(exception());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThread* thread, arrayOopDesc* a, jint index))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThread* thread, arrayOopDesc* a, jint index))
|
||||
// Produce the error message first because note_trap can safepoint
|
||||
ResourceMark rm(thread);
|
||||
stringStream ss;
|
||||
@ -455,9 +455,9 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThr
|
||||
}
|
||||
|
||||
THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
||||
JavaThread* thread, oopDesc* obj))
|
||||
|
||||
// Produce the error message first because note_trap can safepoint
|
||||
@ -471,7 +471,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
||||
|
||||
// create exception
|
||||
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
// exception_handler_for_exception(...) returns the continuation address,
|
||||
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
|
||||
@ -481,7 +481,7 @@ IRT_END
|
||||
// bci where the exception happened. If the exception was propagated back
|
||||
// from a call, the expression stack contains the values for the bci at the
|
||||
// invoke w/o arguments (i.e., as if one were inside the call).
|
||||
IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* thread, oopDesc* exception))
|
||||
JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* thread, oopDesc* exception))
|
||||
|
||||
LastFrameAccessor last_frame(thread);
|
||||
Handle h_exception(thread, exception);
|
||||
@ -622,18 +622,18 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
|
||||
thread->set_vm_result(h_exception());
|
||||
return continuation;
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_pending_exception(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_pending_exception(JavaThread* thread))
|
||||
assert(thread->has_pending_exception(), "must only ne called if there's an exception pending");
|
||||
// nothing to do - eventually we should remove this code entirely (see comments @ call sites)
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodError(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodError(JavaThread* thread))
|
||||
THROW(vmSymbols::java_lang_AbstractMethodError());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
// This method is called from the "abstract_entry" of the interpreter.
|
||||
// At that point, the arguments have already been removed from the stack
|
||||
@ -641,28 +641,28 @@ IRT_END
|
||||
// on some platforms the receiver still resides in a register...). Thus,
|
||||
// we have no choice but print an error message not containing the receiver
|
||||
// type.
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorWithMethod(JavaThread* thread,
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorWithMethod(JavaThread* thread,
|
||||
Method* missingMethod))
|
||||
ResourceMark rm(thread);
|
||||
assert(missingMethod != NULL, "sanity");
|
||||
methodHandle m(thread, missingMethod);
|
||||
LinkResolver::throw_abstract_method_error(m, THREAD);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorVerbose(JavaThread* thread,
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorVerbose(JavaThread* thread,
|
||||
Klass* recvKlass,
|
||||
Method* missingMethod))
|
||||
ResourceMark rm(thread);
|
||||
methodHandle mh = methodHandle(thread, missingMethod);
|
||||
LinkResolver::throw_abstract_method_error(mh, recvKlass, THREAD);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeError(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeError(JavaThread* thread))
|
||||
THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(JavaThread* thread,
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(JavaThread* thread,
|
||||
Klass* recvKlass,
|
||||
Klass* interfaceKlass))
|
||||
ResourceMark rm(thread);
|
||||
@ -673,7 +673,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(Ja
|
||||
recvKlass ? recvKlass->external_name() : "NULL",
|
||||
interfaceKlass ? interfaceKlass->external_name() : "NULL");
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Fields
|
||||
@ -760,7 +760,7 @@ void InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code byt
|
||||
//%note synchronization_3
|
||||
|
||||
//%note monitor_1
|
||||
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
|
||||
JRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
|
||||
#ifdef ASSERT
|
||||
thread->last_frame().interpreter_frame_verify_monitor(elem);
|
||||
#endif
|
||||
@ -781,11 +781,11 @@ IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, Ba
|
||||
#ifdef ASSERT
|
||||
thread->last_frame().interpreter_frame_verify_monitor(elem);
|
||||
#endif
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
//%note monitor_1
|
||||
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))
|
||||
JRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))
|
||||
#ifdef ASSERT
|
||||
thread->last_frame().interpreter_frame_verify_monitor(elem);
|
||||
#endif
|
||||
@ -802,15 +802,15 @@ IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, Bas
|
||||
#ifdef ASSERT
|
||||
thread->last_frame().interpreter_frame_verify_monitor(elem);
|
||||
#endif
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::throw_illegal_monitor_state_exception(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::throw_illegal_monitor_state_exception(JavaThread* thread))
|
||||
THROW(vmSymbols::java_lang_IllegalMonitorStateException());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThread* thread))
|
||||
// Returns an illegal exception to install into the current thread. The
|
||||
// pending_exception flag is cleared so normal exception handling does not
|
||||
// trigger. Any current installed exception will be overwritten. This
|
||||
@ -826,23 +826,23 @@ IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre
|
||||
CATCH);
|
||||
}
|
||||
thread->set_vm_result(exception());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Invokes
|
||||
|
||||
IRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp))
|
||||
JRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp))
|
||||
return method->orig_bytecode_at(method->bci_from(bcp));
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code))
|
||||
JRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code))
|
||||
method->set_orig_bytecode_at(method->bci_from(bcp), new_code);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::_breakpoint(JavaThread* thread, Method* method, address bcp))
|
||||
JRT_ENTRY(void, InterpreterRuntime::_breakpoint(JavaThread* thread, Method* method, address bcp))
|
||||
JvmtiExport::post_raw_breakpoint(thread, method, bcp);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode) {
|
||||
Thread* THREAD = thread;
|
||||
@ -998,7 +998,7 @@ void InterpreterRuntime::resolve_invokedynamic(JavaThread* thread) {
|
||||
// This function is the interface to the assembly code. It returns the resolved
|
||||
// cpCache entry. This doesn't safepoint, but the helper routines safepoint.
|
||||
// This function will check for redefinition!
|
||||
IRT_ENTRY(void, InterpreterRuntime::resolve_from_cache(JavaThread* thread, Bytecodes::Code bytecode)) {
|
||||
JRT_ENTRY(void, InterpreterRuntime::resolve_from_cache(JavaThread* thread, Bytecodes::Code bytecode)) {
|
||||
switch (bytecode) {
|
||||
case Bytecodes::_getstatic:
|
||||
case Bytecodes::_putstatic:
|
||||
@ -1023,7 +1023,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_from_cache(JavaThread* thread, Bytec
|
||||
break;
|
||||
}
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Miscellaneous
|
||||
@ -1069,7 +1069,7 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr
|
||||
return nm;
|
||||
}
|
||||
|
||||
IRT_ENTRY(nmethod*,
|
||||
JRT_ENTRY(nmethod*,
|
||||
InterpreterRuntime::frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp))
|
||||
// use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized
|
||||
// flag, in case this method triggers classloading which will call into Java.
|
||||
@ -1113,17 +1113,17 @@ IRT_ENTRY(nmethod*,
|
||||
}
|
||||
}
|
||||
return osr_nm;
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_LEAF(jint, InterpreterRuntime::bcp_to_di(Method* method, address cur_bcp))
|
||||
JRT_LEAF(jint, InterpreterRuntime::bcp_to_di(Method* method, address cur_bcp))
|
||||
assert(ProfileInterpreter, "must be profiling interpreter");
|
||||
int bci = method->bci_from(cur_bcp);
|
||||
MethodData* mdo = method->method_data();
|
||||
if (mdo == NULL) return 0;
|
||||
return mdo->bci_to_di(bci);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
|
||||
// use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized
|
||||
// flag, in case this method triggers classloading which will call into Java.
|
||||
UnlockFlagSaver fs(thread);
|
||||
@ -1138,11 +1138,11 @@ IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
// and fall through...
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
#ifdef ASSERT
|
||||
IRT_LEAF(void, InterpreterRuntime::verify_mdp(Method* method, address bcp, address mdp))
|
||||
JRT_LEAF(void, InterpreterRuntime::verify_mdp(Method* method, address bcp, address mdp))
|
||||
assert(ProfileInterpreter, "must be profiling interpreter");
|
||||
|
||||
MethodData* mdo = method->method_data();
|
||||
@ -1169,10 +1169,10 @@ IRT_LEAF(void, InterpreterRuntime::verify_mdp(Method* method, address bcp, addre
|
||||
method->print_codes();
|
||||
}
|
||||
assert(mdp == mdp2, "wrong mdp");
|
||||
IRT_END
|
||||
JRT_END
|
||||
#endif // ASSERT
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int return_bci))
|
||||
JRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int return_bci))
|
||||
assert(ProfileInterpreter, "must be profiling interpreter");
|
||||
ResourceMark rm(thread);
|
||||
HandleMark hm(thread);
|
||||
@ -1191,24 +1191,24 @@ IRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int r
|
||||
RetData* rdata = data->as_RetData();
|
||||
address new_mdp = rdata->fixup_ret(return_bci, h_mdo);
|
||||
last_frame.set_mdp(new_mdp);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(MethodCounters*, InterpreterRuntime::build_method_counters(JavaThread* thread, Method* m))
|
||||
JRT_ENTRY(MethodCounters*, InterpreterRuntime::build_method_counters(JavaThread* thread, Method* m))
|
||||
MethodCounters* mcs = Method::build_method_counters(m, thread);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
return mcs;
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread))
|
||||
// We used to need an explict preserve_arguments here for invoke bytecodes. However,
|
||||
// stack traversal automatically takes care of preserving arguments for invoke, so
|
||||
// this is no longer needed.
|
||||
|
||||
// IRT_END does an implicit safepoint check, hence we are guaranteed to block
|
||||
// JRT_END does an implicit safepoint check, hence we are guaranteed to block
|
||||
// if this is called during a safepoint
|
||||
|
||||
if (JvmtiExport::should_post_single_step()) {
|
||||
@ -1218,9 +1218,9 @@ IRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread))
|
||||
LastFrameAccessor last_frame(thread);
|
||||
JvmtiExport::at_single_stepping_point(thread, last_frame.method(), last_frame.bcp());
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread *thread, oopDesc* obj,
|
||||
JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread *thread, oopDesc* obj,
|
||||
ConstantPoolCacheEntry *cp_entry))
|
||||
|
||||
// check the access_flags for the field in the klass
|
||||
@ -1241,9 +1241,9 @@ ConstantPoolCacheEntry *cp_entry))
|
||||
jfieldID fid = jfieldIDWorkaround::to_jfieldID(cp_entry_f1, cp_entry->f2_as_index(), is_static);
|
||||
LastFrameAccessor last_frame(thread);
|
||||
JvmtiExport::post_field_access(thread, last_frame.method(), last_frame.bcp(), cp_entry_f1, h_obj, fid);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
|
||||
JRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
|
||||
oopDesc* obj, ConstantPoolCacheEntry *cp_entry, jvalue *value))
|
||||
|
||||
Klass* k = cp_entry->f1_as_klass();
|
||||
@ -1298,24 +1298,24 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
|
||||
LastFrameAccessor last_frame(thread);
|
||||
JvmtiExport::post_raw_field_modification(thread, last_frame.method(), last_frame.bcp(), ik, h_obj,
|
||||
fid, sig_type, &fvalue);
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::post_method_entry(JavaThread *thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::post_method_entry(JavaThread *thread))
|
||||
LastFrameAccessor last_frame(thread);
|
||||
JvmtiExport::post_method_entry(thread, last_frame.method(), last_frame.get_frame());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::post_method_exit(JavaThread *thread))
|
||||
JRT_ENTRY(void, InterpreterRuntime::post_method_exit(JavaThread *thread))
|
||||
LastFrameAccessor last_frame(thread);
|
||||
JvmtiExport::post_method_exit(thread, last_frame.method(), last_frame.get_frame());
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
IRT_LEAF(int, InterpreterRuntime::interpreter_contains(address pc))
|
||||
JRT_LEAF(int, InterpreterRuntime::interpreter_contains(address pc))
|
||||
{
|
||||
return (Interpreter::contains(pc) ? 1 : 0);
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
// Implementation of SignatureHandlerLibrary
|
||||
@ -1508,7 +1508,7 @@ GrowableArray<address>* SignatureHandlerLibrary::_handlers = NULL;
|
||||
address SignatureHandlerLibrary::_buffer = NULL;
|
||||
|
||||
|
||||
IRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, Method* method))
|
||||
JRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, Method* method))
|
||||
methodHandle m(thread, method);
|
||||
assert(m->is_native(), "sanity check");
|
||||
// lookup native function entry point if it doesn't exist
|
||||
@ -1522,10 +1522,10 @@ IRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, Meth
|
||||
// before trying to fetch the native entry point and klass mirror.
|
||||
// We must set the signature handler last, so that multiple processors
|
||||
// preparing the same method will be sure to see non-null entry & mirror.
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
#if defined(IA32) || defined(AMD64) || defined(ARM)
|
||||
IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address))
|
||||
JRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address))
|
||||
if (src_address == dest_address) {
|
||||
return;
|
||||
}
|
||||
@ -1541,7 +1541,7 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa
|
||||
int size_of_arguments = (asc.size() + (invoke.has_receiver() ? 1 : 0)); // receiver
|
||||
Copy::conjoint_jbytes(src_address, dest_address,
|
||||
size_of_arguments * Interpreter::stackElementSize);
|
||||
IRT_END
|
||||
JRT_END
|
||||
#endif
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
@ -1551,7 +1551,7 @@ IRT_END
|
||||
// The member_name argument is a saved reference (in local#0) to the member_name.
|
||||
// For backward compatibility with some JDK versions (7, 8) it can also be a direct method handle.
|
||||
// FIXME: remove DMH case after j.l.i.InvokerBytecodeGenerator code shape is updated.
|
||||
IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address member_name,
|
||||
JRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address member_name,
|
||||
Method* method, address bcp))
|
||||
Bytecodes::Code code = Bytecodes::code_at(method, bcp);
|
||||
if (code != Bytecodes::_invokestatic) {
|
||||
@ -1572,19 +1572,19 @@ IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread,
|
||||
} else {
|
||||
thread->set_vm_result(NULL);
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
#ifndef PRODUCT
|
||||
// This must be a IRT_LEAF function because the interpreter must save registers on x86 to
|
||||
// This must be a JRT_LEAF function because the interpreter must save registers on x86 to
|
||||
// call this, which changes rsp and makes the interpreter's expression stack not walkable.
|
||||
// The generated code still uses call_VM because that will set up the frame pointer for
|
||||
// bcp and method.
|
||||
IRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
|
||||
JRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
|
||||
LastFrameAccessor last_frame(thread);
|
||||
assert(last_frame.is_interpreted_frame(), "must be an interpreted frame");
|
||||
methodHandle mh(thread, last_frame.method());
|
||||
BytecodeTracer::trace(mh, last_frame.bcp(), tos, tos2);
|
||||
return preserve_this_value;
|
||||
IRT_END
|
||||
JRT_END
|
||||
#endif // !PRODUCT
|
||||
|
@ -359,7 +359,7 @@ bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame*
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
thread->set_trace_flag();
|
||||
thread->set_trace_flag(); // Provides StoreLoad, needed to keep read of thread state from floating up.
|
||||
if (JAVA_SAMPLE == type) {
|
||||
if (thread_state_in_java(thread)) {
|
||||
ret = sample_thread_in_java(thread, frames, max_frames);
|
||||
|
@ -806,13 +806,14 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
addr, size, false /* !read_only */,
|
||||
si->_allow_exec);
|
||||
close();
|
||||
// These have to be errors because the shared region is now unmapped.
|
||||
if (base == NULL) {
|
||||
fail_continue("Unable to remap shared readonly space (errno=%d).", errno);
|
||||
return false;
|
||||
log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
|
||||
vm_exit(1);
|
||||
}
|
||||
if (base != addr) {
|
||||
fail_continue("Unable to remap shared readonly space at required address.");
|
||||
return false;
|
||||
log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
|
||||
vm_exit(1);
|
||||
}
|
||||
si->_read_only = false;
|
||||
return true;
|
||||
@ -849,10 +850,17 @@ char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
size_t size = align_up(used, alignment);
|
||||
char *requested_addr = region_addr(i);
|
||||
|
||||
// If a tool agent is in use (debugging enabled), we must map the address space RW
|
||||
if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
|
||||
#ifdef _WINDOWS
|
||||
// Windows cannot remap read-only shared memory to read-write when required for
|
||||
// RedefineClasses, which is also used by JFR. Always map windows regions as RW.
|
||||
si->_read_only = false;
|
||||
#else
|
||||
// If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
|
||||
if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
|
||||
Arguments::has_jfr_option()) {
|
||||
si->_read_only = false;
|
||||
}
|
||||
#endif // _WINDOWS
|
||||
|
||||
// map the contents of the CDS archive in this memory
|
||||
char *base = os::map_memory(_fd, _full_path, si->_file_offset,
|
||||
@ -868,7 +876,6 @@ char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
MemTracker::record_virtual_memory_type((address)base, mtClassShared);
|
||||
#endif
|
||||
|
||||
|
||||
if (!verify_region_checksum(i)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1151,6 +1151,8 @@ void Universe::initialize_verify_flags() {
|
||||
verify_flags |= Verify_JNIHandles;
|
||||
} else if (strcmp(token, "codecache_oops") == 0) {
|
||||
verify_flags |= Verify_CodeCacheOops;
|
||||
} else if (strcmp(token, "resolved_method_table") == 0) {
|
||||
verify_flags |= Verify_ResolvedMethodTable;
|
||||
} else {
|
||||
vm_exit_during_initialization(err_msg("VerifySubSet: \'%s\' memory sub-system is unknown, please correct it", token));
|
||||
}
|
||||
@ -1230,6 +1232,10 @@ void Universe::verify(VerifyOption option, const char* prefix) {
|
||||
log_debug(gc, verify)("CodeCache Oops");
|
||||
CodeCache::verify_oops();
|
||||
}
|
||||
if (should_verify_subset(Verify_ResolvedMethodTable)) {
|
||||
log_debug(gc, verify)("ResolvedMethodTable Oops");
|
||||
ResolvedMethodTable::verify();
|
||||
}
|
||||
|
||||
_verify_in_progress = false;
|
||||
}
|
||||
|
@ -478,6 +478,7 @@ class Universe: AllStatic {
|
||||
Verify_MetaspaceUtils = 128,
|
||||
Verify_JNIHandles = 256,
|
||||
Verify_CodeCacheOops = 512,
|
||||
Verify_ResolvedMethodTable = 1024,
|
||||
Verify_All = -1
|
||||
};
|
||||
static void initialize_verify_flags();
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "oops/access.inline.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/weakHandle.inline.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
@ -40,6 +41,10 @@ template <> OopStorage* WeakHandle<vm_string_table_data>::get_storage() {
|
||||
return StringTable::weak_storage();
|
||||
}
|
||||
|
||||
template <> OopStorage* WeakHandle<vm_resolved_method_table_data>::get_storage() {
|
||||
return ResolvedMethodTable::weak_storage();
|
||||
}
|
||||
|
||||
template <WeakHandleType T>
|
||||
WeakHandle<T> WeakHandle<T>::create(Handle obj) {
|
||||
assert(obj() != NULL, "no need to create weak null oop");
|
||||
@ -74,4 +79,4 @@ void WeakHandle<T>::print_on(outputStream* st) const {
|
||||
// Provide instantiation.
|
||||
template class WeakHandle<vm_class_loader_data>;
|
||||
template class WeakHandle<vm_string_table_data>;
|
||||
|
||||
template class WeakHandle<vm_resolved_method_table_data>;
|
||||
|
@ -39,7 +39,7 @@ class OopStorage;
|
||||
// This is the vm version of jweak but has different GC lifetimes and policies,
|
||||
// depending on the type.
|
||||
|
||||
enum WeakHandleType { vm_class_loader_data, vm_string_table_data };
|
||||
enum WeakHandleType { vm_class_loader_data, vm_string_table_data, vm_resolved_method_table_data };
|
||||
|
||||
template <WeakHandleType T>
|
||||
class WeakHandle {
|
||||
@ -64,6 +64,4 @@ class WeakHandle {
|
||||
void print_on(outputStream* st) const;
|
||||
};
|
||||
|
||||
typedef WeakHandle<vm_class_loader_data> ClassLoaderWeakHandle;
|
||||
|
||||
#endif // SHARE_OOPS_WEAKHANDLE_HPP
|
||||
|
@ -787,6 +787,12 @@ static jvmtiError check_nest_attributes(InstanceKlass* the_class,
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool can_add_or_delete(Method* m) {
|
||||
// Compatibility mode
|
||||
return (AllowRedefinitionToAddDeleteMethods &&
|
||||
(m->is_private() && (m->is_static() || m->is_final())));
|
||||
}
|
||||
|
||||
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||
InstanceKlass* the_class,
|
||||
InstanceKlass* scratch_class) {
|
||||
@ -992,12 +998,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||
break;
|
||||
case added:
|
||||
// method added, see if it is OK
|
||||
new_flags = (jushort) k_new_method->access_flags().get_flags();
|
||||
if ((new_flags & JVM_ACC_PRIVATE) == 0
|
||||
// hack: private should be treated as final, but alas
|
||||
|| (new_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0
|
||||
) {
|
||||
// new methods must be private
|
||||
if (!can_add_or_delete(k_new_method)) {
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED;
|
||||
}
|
||||
{
|
||||
@ -1026,12 +1027,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||
break;
|
||||
case deleted:
|
||||
// method deleted, see if it is OK
|
||||
old_flags = (jushort) k_old_method->access_flags().get_flags();
|
||||
if ((old_flags & JVM_ACC_PRIVATE) == 0
|
||||
// hack: private should be treated as final, but alas
|
||||
|| (old_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0
|
||||
) {
|
||||
// deleted methods must be private
|
||||
if (!can_add_or_delete(k_old_method)) {
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED;
|
||||
}
|
||||
log_trace(redefine, class, normalize)
|
||||
|
@ -24,223 +24,395 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/access.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "oops/weakHandle.inline.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
#include "runtime/timerTrace.hpp"
|
||||
#include "utilities/concurrentHashTable.inline.hpp"
|
||||
#include "utilities/concurrentHashTableTasks.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
// 2^24 is max size
|
||||
static const size_t END_SIZE = 24;
|
||||
// If a chain gets to 32 something might be wrong
|
||||
static const size_t GROW_HINT = 32;
|
||||
|
||||
oop ResolvedMethodEntry::object() {
|
||||
return literal().resolve();
|
||||
}
|
||||
static const size_t ResolvedMethodTableSizeLog = 10;
|
||||
|
||||
oop ResolvedMethodEntry::object_no_keepalive() {
|
||||
// The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
|
||||
// This is dangerous in general but is okay if the loaded oop does
|
||||
// not leak out past a thread transition where a safepoint can happen.
|
||||
// A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor)
|
||||
// keeps the oop alive before doing so.
|
||||
return literal().peek();
|
||||
}
|
||||
|
||||
ResolvedMethodTable::ResolvedMethodTable()
|
||||
: Hashtable<ClassLoaderWeakHandle, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
|
||||
|
||||
oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
|
||||
assert_locked_or_safepoint(ResolvedMethodTable_lock);
|
||||
for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||
if (p->hash() == hash) {
|
||||
|
||||
// Peek the object to check if it is the right target.
|
||||
oop target = p->object_no_keepalive();
|
||||
|
||||
// The method is in the table as a target already
|
||||
if (target != NULL && java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
|
||||
ResourceMark rm;
|
||||
log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
|
||||
method->name_and_sig_as_C_string(), index);
|
||||
// The object() accessor makes sure the target object is kept alive before
|
||||
// leaking out.
|
||||
return p->object();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int ResolvedMethodTable::compute_hash(Method* method) {
|
||||
unsigned int method_hash(const Method* method) {
|
||||
unsigned int name_hash = method->name()->identity_hash();
|
||||
unsigned int signature_hash = method->signature()->identity_hash();
|
||||
return name_hash ^ signature_hash;
|
||||
}
|
||||
|
||||
|
||||
oop ResolvedMethodTable::lookup(Method* method) {
|
||||
unsigned int hash = compute_hash(method);
|
||||
int index = hash_to_index(hash);
|
||||
return lookup(index, hash, method);
|
||||
}
|
||||
|
||||
oop ResolvedMethodTable::basic_add(Method* method, Handle rmethod_name) {
|
||||
assert_locked_or_safepoint(ResolvedMethodTable_lock);
|
||||
|
||||
unsigned int hash = compute_hash(method);
|
||||
int index = hash_to_index(hash);
|
||||
|
||||
// One was added while aquiring the lock
|
||||
oop entry = lookup(index, hash, method);
|
||||
if (entry != NULL) {
|
||||
return entry;
|
||||
class ResolvedMethodTableConfig : public ResolvedMethodTableHash::BaseConfig {
|
||||
private:
|
||||
public:
|
||||
static uintx get_hash(WeakHandle<vm_resolved_method_table_data> const& value,
|
||||
bool* is_dead) {
|
||||
EXCEPTION_MARK;
|
||||
oop val_oop = value.peek();
|
||||
if (val_oop == NULL) {
|
||||
*is_dead = true;
|
||||
return 0;
|
||||
}
|
||||
*is_dead = false;
|
||||
Method* method = java_lang_invoke_ResolvedMethodName::vmtarget(val_oop);
|
||||
return method_hash(method);
|
||||
}
|
||||
|
||||
// We use default allocation/deallocation but counted
|
||||
static void* allocate_node(size_t size, WeakHandle<vm_resolved_method_table_data> const& value) {
|
||||
ResolvedMethodTable::item_added();
|
||||
return ResolvedMethodTableHash::BaseConfig::allocate_node(size, value);
|
||||
}
|
||||
static void free_node(void* memory, WeakHandle<vm_resolved_method_table_data> const& value) {
|
||||
value.release();
|
||||
ResolvedMethodTableHash::BaseConfig::free_node(memory, value);
|
||||
ResolvedMethodTable::item_removed();
|
||||
}
|
||||
};
|
||||
|
||||
ResolvedMethodTableHash* ResolvedMethodTable::_local_table = NULL;
|
||||
size_t ResolvedMethodTable::_current_size = (size_t)1 << ResolvedMethodTableSizeLog;
|
||||
|
||||
OopStorage* ResolvedMethodTable::_weak_handles = NULL;
|
||||
|
||||
volatile bool ResolvedMethodTable::_has_work = false;
|
||||
volatile size_t ResolvedMethodTable::_items_count = 0;
|
||||
volatile size_t ResolvedMethodTable::_uncleaned_items_count = 0;
|
||||
|
||||
void ResolvedMethodTable::create_table() {
|
||||
_local_table = new ResolvedMethodTableHash(ResolvedMethodTableSizeLog, END_SIZE, GROW_HINT);
|
||||
_weak_handles = new OopStorage("ResolvedMethodTable weak",
|
||||
ResolvedMethodTableWeakAlloc_lock,
|
||||
ResolvedMethodTableWeakActive_lock);
|
||||
log_trace(membername, table)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
|
||||
_current_size, ResolvedMethodTableSizeLog);
|
||||
}
|
||||
|
||||
size_t ResolvedMethodTable::table_size() {
|
||||
return (size_t)1 << _local_table->get_size_log2(Thread::current());
|
||||
}
|
||||
|
||||
class ResolvedMethodTableLookup : StackObj {
|
||||
private:
|
||||
Thread* _thread;
|
||||
uintx _hash;
|
||||
const Method* _method;
|
||||
Handle _found;
|
||||
|
||||
public:
|
||||
ResolvedMethodTableLookup(Thread* thread, uintx hash, const Method* key)
|
||||
: _thread(thread), _hash(hash), _method(key) {
|
||||
}
|
||||
uintx get_hash() const {
|
||||
return _hash;
|
||||
}
|
||||
bool equals(WeakHandle<vm_resolved_method_table_data>* value, bool* is_dead) {
|
||||
oop val_oop = value->peek();
|
||||
if (val_oop == NULL) {
|
||||
// dead oop, mark this hash dead for cleaning
|
||||
*is_dead = true;
|
||||
return false;
|
||||
}
|
||||
bool equals = _method == java_lang_invoke_ResolvedMethodName::vmtarget(val_oop);
|
||||
if (!equals) {
|
||||
return false;
|
||||
}
|
||||
// Need to resolve weak handle and Handleize through possible safepoint.
|
||||
_found = Handle(_thread, value->resolve());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ResolvedMethodGet : public StackObj {
|
||||
Thread* _thread;
|
||||
const Method* _method;
|
||||
Handle _return;
|
||||
public:
|
||||
ResolvedMethodGet(Thread* thread, const Method* method) : _thread(thread), _method(method) {}
|
||||
void operator()(WeakHandle<vm_resolved_method_table_data>* val) {
|
||||
oop result = val->resolve();
|
||||
assert(result != NULL, "Result should be reachable");
|
||||
_return = Handle(_thread, result);
|
||||
log_get();
|
||||
}
|
||||
oop get_res_oop() {
|
||||
return _return();
|
||||
}
|
||||
void log_get() {
|
||||
LogTarget(Trace, membername, table) log;
|
||||
if (log.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
log.print("ResolvedMethod entry found for %s",
|
||||
_method->name_and_sig_as_C_string());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
oop ResolvedMethodTable::find_method(const Method* method) {
|
||||
Thread* thread = Thread::current();
|
||||
|
||||
ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
|
||||
ResolvedMethodGet rmg(thread, method);
|
||||
_local_table->get(thread, lookup, rmg);
|
||||
|
||||
return rmg.get_res_oop();
|
||||
}
|
||||
|
||||
static void log_insert(const Method* method) {
|
||||
LogTarget(Debug, membername, table) log;
|
||||
if (log.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
log_debug(membername, table) ("ResolvedMethod entry added for %s",
|
||||
method->name_and_sig_as_C_string());
|
||||
}
|
||||
}
|
||||
|
||||
oop ResolvedMethodTable::add_method(const Method* method, Handle rmethod_name) {
|
||||
Thread* thread = Thread::current();
|
||||
|
||||
ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
|
||||
ResolvedMethodGet rmg(thread, method);
|
||||
|
||||
while (true) {
|
||||
if (_local_table->get(thread, lookup, rmg)) {
|
||||
return rmg.get_res_oop();
|
||||
}
|
||||
WeakHandle<vm_resolved_method_table_data> wh = WeakHandle<vm_resolved_method_table_data>::create(rmethod_name);
|
||||
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
|
||||
if (_local_table->insert(thread, lookup, wh)) {
|
||||
log_insert(method);
|
||||
return wh.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
ClassLoaderWeakHandle w = ClassLoaderWeakHandle::create(rmethod_name);
|
||||
ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::new_entry(hash, w);
|
||||
Hashtable<ClassLoaderWeakHandle, mtClass>::add_entry(index, p);
|
||||
ResourceMark rm;
|
||||
log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
|
||||
method->name_and_sig_as_C_string(), index);
|
||||
return rmethod_name();
|
||||
}
|
||||
|
||||
ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
|
||||
|
||||
oop ResolvedMethodTable::find_method(Method* method) {
|
||||
MutexLocker ml(ResolvedMethodTable_lock);
|
||||
oop entry = _the_table->lookup(method);
|
||||
return entry;
|
||||
void ResolvedMethodTable::item_added() {
|
||||
Atomic::inc(&_items_count);
|
||||
}
|
||||
|
||||
oop ResolvedMethodTable::add_method(const methodHandle& m, Handle resolved_method_name) {
|
||||
MutexLocker ml(ResolvedMethodTable_lock);
|
||||
DEBUG_ONLY(NoSafepointVerifier nsv);
|
||||
void ResolvedMethodTable::item_removed() {
|
||||
Atomic::dec(&_items_count);
|
||||
log_trace(membername, table) ("ResolvedMethod entry removed");
|
||||
}
|
||||
|
||||
Method* method = m();
|
||||
// Check if method has been redefined while taking out ResolvedMethodTable_lock, if so
|
||||
// use new method in the ResolvedMethodName. The old method won't be deallocated
|
||||
// yet because it's passed in as a Handle.
|
||||
if (method->is_old()) {
|
||||
method = (method->is_deleted()) ? Universe::throw_no_such_method_error() :
|
||||
method->get_new_method();
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(resolved_method_name(), method);
|
||||
bool ResolvedMethodTable::has_work() {
|
||||
return _has_work;
|
||||
}
|
||||
|
||||
OopStorage* ResolvedMethodTable::weak_storage() {
|
||||
return _weak_handles;
|
||||
}
|
||||
|
||||
double ResolvedMethodTable::get_load_factor() {
|
||||
return (double)_items_count/_current_size;
|
||||
}
|
||||
|
||||
double ResolvedMethodTable::get_dead_factor() {
|
||||
return (double)_uncleaned_items_count/_current_size;
|
||||
}
|
||||
|
||||
static const double PREF_AVG_LIST_LEN = 2.0;
|
||||
// If we have as many dead items as 50% of the number of bucket
|
||||
static const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
|
||||
|
||||
void ResolvedMethodTable::check_concurrent_work() {
|
||||
if (_has_work) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set flag in class to indicate this InstanceKlass has entries in the table
|
||||
// to avoid walking table during redefinition if none of the redefined classes
|
||||
// have any membernames in the table.
|
||||
method->method_holder()->set_has_resolved_methods();
|
||||
|
||||
return _the_table->basic_add(method, resolved_method_name);
|
||||
double load_factor = get_load_factor();
|
||||
double dead_factor = get_dead_factor();
|
||||
// We should clean/resize if we have more dead than alive,
|
||||
// more items than preferred load factor or
|
||||
// more dead items than water mark.
|
||||
if ((dead_factor > load_factor) ||
|
||||
(load_factor > PREF_AVG_LIST_LEN) ||
|
||||
(dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
|
||||
log_debug(membername, table)("Concurrent work triggered, live factor: %g dead factor: %g",
|
||||
load_factor, dead_factor);
|
||||
trigger_concurrent_work();
|
||||
}
|
||||
}
|
||||
|
||||
// Removing entries
|
||||
int ResolvedMethodTable::_total_oops_removed = 0;
|
||||
|
||||
// There are no dead entries at start
|
||||
bool ResolvedMethodTable::_dead_entries = false;
|
||||
|
||||
void ResolvedMethodTable::trigger_cleanup() {
|
||||
void ResolvedMethodTable::trigger_concurrent_work() {
|
||||
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
_dead_entries = true;
|
||||
_has_work = true;
|
||||
Service_lock->notify_all();
|
||||
}
|
||||
|
||||
// Serially invoke removed unused oops from the table.
|
||||
// This is done by the ServiceThread after being notified on class unloading
|
||||
void ResolvedMethodTable::unlink() {
|
||||
MutexLocker ml(ResolvedMethodTable_lock);
|
||||
int _oops_removed = 0;
|
||||
int _oops_counted = 0;
|
||||
for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
ResolvedMethodEntry** p = _the_table->bucket_addr(i);
|
||||
ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
while (entry != NULL) {
|
||||
_oops_counted++;
|
||||
oop l = entry->object_no_keepalive();
|
||||
if (l != NULL) {
|
||||
p = entry->next_addr();
|
||||
} else {
|
||||
// Entry has been removed.
|
||||
_oops_removed++;
|
||||
if (log_is_enabled(Debug, membername, table)) {
|
||||
log_debug(membername, table) ("ResolvedMethod entry removed for index %d", i);
|
||||
}
|
||||
entry->literal().release();
|
||||
*p = entry->next();
|
||||
_the_table->free_entry(entry);
|
||||
}
|
||||
// get next entry
|
||||
entry = (ResolvedMethodEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::make_ptr(*p);
|
||||
}
|
||||
void ResolvedMethodTable::do_concurrent_work(JavaThread* jt) {
|
||||
_has_work = false;
|
||||
double load_factor = get_load_factor();
|
||||
log_debug(membername, table)("Concurrent work, live factor: %g", load_factor);
|
||||
// We prefer growing, since that also removes dead items
|
||||
if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
|
||||
grow(jt);
|
||||
} else {
|
||||
clean_dead_entries(jt);
|
||||
}
|
||||
log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
|
||||
_oops_counted, _oops_removed);
|
||||
_total_oops_removed += _oops_removed;
|
||||
_dead_entries = false;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ResolvedMethodTable::print() {
|
||||
MutexLocker ml(ResolvedMethodTable_lock);
|
||||
for (int i = 0; i < table_size(); ++i) {
|
||||
ResolvedMethodEntry* entry = bucket(i);
|
||||
while (entry != NULL) {
|
||||
tty->print("%d : ", i);
|
||||
oop rmethod_name = entry->object_no_keepalive();
|
||||
if (rmethod_name != NULL) {
|
||||
rmethod_name->print();
|
||||
Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
|
||||
m->print();
|
||||
void ResolvedMethodTable::grow(JavaThread* jt) {
|
||||
ResolvedMethodTableHash::GrowTask gt(_local_table);
|
||||
if (!gt.prepare(jt)) {
|
||||
return;
|
||||
}
|
||||
log_trace(membername, table)("Started to grow");
|
||||
{
|
||||
TraceTime timer("Grow", TRACETIME_LOG(Debug, membername, table, perf));
|
||||
while (gt.do_task(jt)) {
|
||||
gt.pause(jt);
|
||||
{
|
||||
ThreadBlockInVM tbivm(jt);
|
||||
}
|
||||
entry = entry->next();
|
||||
gt.cont(jt);
|
||||
}
|
||||
}
|
||||
gt.done(jt);
|
||||
_current_size = table_size();
|
||||
log_info(membername, table)("Grown to size:" SIZE_FORMAT, _current_size);
|
||||
}
|
||||
|
||||
struct ResolvedMethodTableDoDelete : StackObj {
|
||||
void operator()(WeakHandle<vm_resolved_method_table_data>* val) {
|
||||
/* do nothing */
|
||||
}
|
||||
};
|
||||
|
||||
struct ResolvedMethodTableDeleteCheck : StackObj {
|
||||
long _count;
|
||||
long _item;
|
||||
ResolvedMethodTableDeleteCheck() : _count(0), _item(0) {}
|
||||
bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
|
||||
++_item;
|
||||
oop tmp = val->peek();
|
||||
if (tmp == NULL) {
|
||||
++_count;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void ResolvedMethodTable::clean_dead_entries(JavaThread* jt) {
|
||||
ResolvedMethodTableHash::BulkDeleteTask bdt(_local_table);
|
||||
if (!bdt.prepare(jt)) {
|
||||
return;
|
||||
}
|
||||
ResolvedMethodTableDeleteCheck stdc;
|
||||
ResolvedMethodTableDoDelete stdd;
|
||||
{
|
||||
TraceTime timer("Clean", TRACETIME_LOG(Debug, membername, table, perf));
|
||||
while(bdt.do_task(jt, stdc, stdd)) {
|
||||
bdt.pause(jt);
|
||||
{
|
||||
ThreadBlockInVM tbivm(jt);
|
||||
}
|
||||
bdt.cont(jt);
|
||||
}
|
||||
bdt.done(jt);
|
||||
}
|
||||
log_info(membername, table)("Cleaned %ld of %ld", stdc._count, stdc._item);
|
||||
}
|
||||
void ResolvedMethodTable::reset_dead_counter() {
|
||||
_uncleaned_items_count = 0;
|
||||
}
|
||||
|
||||
void ResolvedMethodTable::inc_dead_counter(size_t ndead) {
|
||||
size_t total = Atomic::add(ndead, &_uncleaned_items_count);
|
||||
log_trace(membername, table)(
|
||||
"Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
|
||||
_uncleaned_items_count, ndead, total);
|
||||
}
|
||||
|
||||
// After the parallel walk this method must be called to trigger
|
||||
// cleaning. Note it might trigger a resize instead.
|
||||
void ResolvedMethodTable::finish_dead_counter() {
|
||||
check_concurrent_work();
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
class AdjustMethodEntries : public StackObj {
|
||||
bool* _trace_name_printed;
|
||||
public:
|
||||
AdjustMethodEntries(bool* trace_name_printed) : _trace_name_printed(trace_name_printed) {};
|
||||
bool operator()(WeakHandle<vm_resolved_method_table_data>* entry) {
|
||||
oop mem_name = entry->peek();
|
||||
if (mem_name == NULL) {
|
||||
// Removed
|
||||
return true;
|
||||
}
|
||||
|
||||
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
|
||||
if (old_method->is_old()) {
|
||||
|
||||
Method* new_method = (old_method->is_deleted()) ?
|
||||
Universe::throw_no_such_method_error() :
|
||||
old_method->get_new_method();
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
|
||||
|
||||
ResourceMark rm;
|
||||
if (!(*_trace_name_printed)) {
|
||||
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
*_trace_name_printed = true;
|
||||
}
|
||||
log_debug(redefine, class, update, constantpool)
|
||||
("ResolvedMethod method update: %s(%s)",
|
||||
new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// It is called at safepoint only for RedefineClasses
|
||||
void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
// For each entry in RMT, change to new method
|
||||
for (int i = 0; i < _the_table->table_size(); ++i) {
|
||||
for (ResolvedMethodEntry* entry = _the_table->bucket(i);
|
||||
entry != NULL;
|
||||
entry = entry->next()) {
|
||||
|
||||
oop mem_name = entry->object_no_keepalive();
|
||||
// except ones removed
|
||||
if (mem_name == NULL) {
|
||||
continue;
|
||||
}
|
||||
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
|
||||
if (old_method->is_old()) {
|
||||
|
||||
Method* new_method = (old_method->is_deleted()) ?
|
||||
Universe::throw_no_such_method_error() :
|
||||
old_method->get_new_method();
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
|
||||
|
||||
ResourceMark rm;
|
||||
if (!(*trace_name_printed)) {
|
||||
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
log_debug(redefine, class, update, constantpool)
|
||||
("ResolvedMethod method update: %s(%s)",
|
||||
new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
AdjustMethodEntries adjust(trace_name_printed);
|
||||
_local_table->do_safepoint_scan(adjust);
|
||||
}
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Verification
|
||||
class VerifyResolvedMethod : StackObj {
|
||||
public:
|
||||
bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
|
||||
oop obj = val->peek();
|
||||
if (obj != NULL) {
|
||||
Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(obj);
|
||||
guarantee(method->is_method(), "Must be");
|
||||
guarantee(!method->is_old(), "Must be");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
size_t ResolvedMethodTable::items_count() {
|
||||
return _items_count;
|
||||
}
|
||||
|
||||
void ResolvedMethodTable::verify() {
|
||||
VerifyResolvedMethod vcs;
|
||||
if (!_local_table->try_scan(Thread::current(), vcs)) {
|
||||
log_info(membername, table)("verify unavailable at this moment");
|
||||
}
|
||||
}
|
||||
|
@ -25,89 +25,78 @@
|
||||
#ifndef SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
|
||||
#define SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
|
||||
|
||||
#include "gc/shared/oopStorage.hpp"
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "oops/weakHandle.hpp"
|
||||
#include "utilities/concurrentHashTable.hpp"
|
||||
#include "utilities/hashtable.hpp"
|
||||
|
||||
// Hashtable to record Method* used in ResolvedMethods, via. ResolvedMethod oops.
|
||||
// This is needed for redefinition to replace Method* with redefined versions.
|
||||
class ResolvedMethodTable;
|
||||
class ResolvedMethodTableConfig;
|
||||
typedef ConcurrentHashTable<WeakHandle<vm_resolved_method_table_data>, ResolvedMethodTableConfig, mtClass> ResolvedMethodTableHash;
|
||||
|
||||
// Entry in a ResolvedMethodTable, mapping a ClassLoaderWeakHandle for a single oop of
|
||||
// java_lang_invoke_ResolvedMethodName which holds JVM Method* in vmtarget.
|
||||
class ResolvedMethodTable : public AllStatic {
|
||||
static ResolvedMethodTableHash* _local_table;
|
||||
static size_t _current_size;
|
||||
|
||||
class ResolvedMethodEntry : public HashtableEntry<ClassLoaderWeakHandle, mtClass> {
|
||||
public:
|
||||
ResolvedMethodEntry* next() const {
|
||||
return (ResolvedMethodEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next();
|
||||
}
|
||||
static OopStorage* _weak_handles;
|
||||
|
||||
ResolvedMethodEntry** next_addr() {
|
||||
return (ResolvedMethodEntry**)HashtableEntry<ClassLoaderWeakHandle, mtClass>::next_addr();
|
||||
}
|
||||
static volatile bool _has_work;
|
||||
|
||||
oop object();
|
||||
oop object_no_keepalive();
|
||||
|
||||
void print_on(outputStream* st) const;
|
||||
};
|
||||
|
||||
class ResolvedMethodTable : public Hashtable<ClassLoaderWeakHandle, mtClass> {
|
||||
enum Constants {
|
||||
_table_size = 1007
|
||||
};
|
||||
|
||||
static int _total_oops_removed;
|
||||
|
||||
static bool _dead_entries;
|
||||
|
||||
static ResolvedMethodTable* _the_table;
|
||||
private:
|
||||
ResolvedMethodEntry* bucket(int i) {
|
||||
return (ResolvedMethodEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket(i);
|
||||
}
|
||||
|
||||
ResolvedMethodEntry** bucket_addr(int i) {
|
||||
return (ResolvedMethodEntry**) Hashtable<ClassLoaderWeakHandle, mtClass>::bucket_addr(i);
|
||||
}
|
||||
|
||||
unsigned int compute_hash(Method* method);
|
||||
|
||||
// need not be locked; no state change
|
||||
oop lookup(int index, unsigned int hash, Method* method);
|
||||
oop lookup(Method* method);
|
||||
|
||||
// must be done under ResolvedMethodTable_lock
|
||||
oop basic_add(Method* method, Handle rmethod_name);
|
||||
static volatile size_t _items_count;
|
||||
static volatile size_t _uncleaned_items_count;
|
||||
|
||||
public:
|
||||
ResolvedMethodTable();
|
||||
// Initialization
|
||||
static void create_table();
|
||||
|
||||
static void create_table() {
|
||||
assert(_the_table == NULL, "One symbol table allowed.");
|
||||
_the_table = new ResolvedMethodTable();
|
||||
}
|
||||
static size_t table_size();
|
||||
|
||||
// Called from java_lang_invoke_ResolvedMethodName
|
||||
static oop find_method(Method* method);
|
||||
static oop add_method(const methodHandle& method, Handle rmethod_name);
|
||||
// Lookup and inserts
|
||||
static oop find_method(const Method* method);
|
||||
static oop add_method(const Method* method, Handle rmethod_name);
|
||||
|
||||
static bool has_work() { return _dead_entries; }
|
||||
static void trigger_cleanup();
|
||||
// Callbacks
|
||||
static void item_added();
|
||||
static void item_removed();
|
||||
|
||||
static int removed_entries_count() { return _total_oops_removed; };
|
||||
// Cleaning
|
||||
static bool has_work();
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
// It is called at safepoint only for RedefineClasses
|
||||
static void adjust_method_entries(bool * trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
// GC Support - Backing storage for the oop*s
|
||||
static OopStorage* weak_storage();
|
||||
|
||||
// Cleanup cleared entries
|
||||
static void unlink();
|
||||
// Cleaning and table management
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print();
|
||||
#endif
|
||||
void verify();
|
||||
static double get_load_factor();
|
||||
static double get_dead_factor();
|
||||
|
||||
static void check_concurrent_work();
|
||||
static void trigger_concurrent_work();
|
||||
static void do_concurrent_work(JavaThread* jt);
|
||||
|
||||
static void grow(JavaThread* jt);
|
||||
static void clean_dead_entries(JavaThread* jt);
|
||||
|
||||
// GC Notification
|
||||
|
||||
// Must be called before a parallel walk where objects might die.
|
||||
static void reset_dead_counter();
|
||||
// After the parallel walk this method must be called to trigger
|
||||
// cleaning. Note it might trigger a resize instead.
|
||||
static void finish_dead_counter();
|
||||
// If GC uses ParState directly it should add the number of cleared
|
||||
// entries to this method.
|
||||
static void inc_dead_counter(size_t ndead);
|
||||
|
||||
// JVMTI Support - It is called at safepoint only for RedefineClasses
|
||||
JVMTI_ONLY(static void adjust_method_entries(bool * trace_name_printed);)
|
||||
|
||||
// Debugging
|
||||
static size_t items_count();
|
||||
static void verify();
|
||||
};
|
||||
|
||||
#endif // SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
|
||||
|
@ -2092,8 +2092,8 @@ WB_ENTRY(void, WB_DisableElfSectionCache(JNIEnv* env))
|
||||
#endif
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jint, WB_ResolvedMethodRemovedCount(JNIEnv* env, jobject o))
|
||||
return (jint) ResolvedMethodTable::removed_entries_count();
|
||||
WB_ENTRY(jlong, WB_ResolvedMethodItemsCount(JNIEnv* env, jobject o))
|
||||
return (jlong) ResolvedMethodTable::items_count();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
|
||||
@ -2337,7 +2337,7 @@ static JNINativeMethod methods[] = {
|
||||
{CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
|
||||
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
|
||||
{CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
|
||||
{CC"resolvedMethodRemovedCount", CC"()I", (void*)&WB_ResolvedMethodRemovedCount },
|
||||
{CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount },
|
||||
{CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount },
|
||||
{CC"aotLibrariesCount", CC"()I", (void*)&WB_AotLibrariesCount },
|
||||
};
|
||||
|
@ -271,17 +271,25 @@ static bool match_option(const JavaVMOption* option, const char** names, const c
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
static bool _has_jfr_option = false; // is using JFR
|
||||
|
||||
// return true on failure
|
||||
static bool match_jfr_option(const JavaVMOption** option) {
|
||||
assert((*option)->optionString != NULL, "invariant");
|
||||
char* tail = NULL;
|
||||
if (match_option(*option, "-XX:StartFlightRecording", (const char**)&tail)) {
|
||||
_has_jfr_option = true;
|
||||
return Jfr::on_start_flight_recording_option(option, tail);
|
||||
} else if (match_option(*option, "-XX:FlightRecorderOptions", (const char**)&tail)) {
|
||||
_has_jfr_option = true;
|
||||
return Jfr::on_flight_recorder_option(option, tail);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Arguments::has_jfr_option() {
|
||||
return _has_jfr_option;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void logOption(const char* opt) {
|
||||
@ -532,6 +540,7 @@ static SpecialFlag const special_jvm_flags[] = {
|
||||
{ "FailOverToOldVerifier", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
|
||||
{ "AllowJNIEnvProxy", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
|
||||
{ "ThreadLocalHandshakes", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
|
||||
{ "AllowRedefinitionToAddDeleteMethods", JDK_Version::jdk(13), JDK_Version::undefined(), 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() },
|
||||
|
@ -649,6 +649,8 @@ class Arguments : AllStatic {
|
||||
static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0;
|
||||
|
||||
static bool atojulong(const char *s, julong* result);
|
||||
|
||||
static bool has_jfr_option() NOT_JFR_RETURN_(false);
|
||||
};
|
||||
|
||||
// Disable options not supported in this release, with a warning if they
|
||||
|
@ -978,6 +978,10 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
|
||||
product(bool, VerifyMergedCPBytecodes, true, \
|
||||
"Verify bytecodes after RedefineClasses constant pool merging") \
|
||||
\
|
||||
product(bool, AllowRedefinitionToAddDeleteMethods, false, \
|
||||
"Allow redefinition to add and delete private static or " \
|
||||
"final methods for compatibility with old releases") \
|
||||
\
|
||||
develop(bool, TraceBytecodes, false, \
|
||||
"Trace bytecode execution") \
|
||||
\
|
||||
|
@ -422,30 +422,6 @@ class RuntimeHistogramElement : public HistogramElement {
|
||||
/* begin of body */
|
||||
|
||||
|
||||
// Definitions for IRT (Interpreter Runtime)
|
||||
// (thread is an argument passed in to all these routines)
|
||||
|
||||
#define IRT_ENTRY(result_type, header) \
|
||||
result_type header { \
|
||||
ThreadInVMfromJava __tiv(thread); \
|
||||
VM_ENTRY_BASE(result_type, header, thread) \
|
||||
debug_only(VMEntryWrapper __vew;)
|
||||
|
||||
|
||||
#define IRT_LEAF(result_type, header) \
|
||||
result_type header { \
|
||||
VM_LEAF_BASE(result_type, header) \
|
||||
debug_only(NoSafepointVerifier __nspv(true);)
|
||||
|
||||
|
||||
#define IRT_ENTRY_NO_ASYNC(result_type, header) \
|
||||
result_type header { \
|
||||
ThreadInVMfromJavaNoAsyncException __tiv(thread); \
|
||||
VM_ENTRY_BASE(result_type, header, thread) \
|
||||
debug_only(VMEntryWrapper __vew;)
|
||||
|
||||
#define IRT_END }
|
||||
|
||||
#define JRT_ENTRY(result_type, header) \
|
||||
result_type header { \
|
||||
ThreadInVMfromJava __tiv(thread); \
|
||||
|
@ -54,7 +54,8 @@ Mutex* StringTableWeakActive_lock = NULL;
|
||||
Mutex* JNIHandleBlockFreeList_lock = NULL;
|
||||
Mutex* VMWeakAlloc_lock = NULL;
|
||||
Mutex* VMWeakActive_lock = NULL;
|
||||
Mutex* ResolvedMethodTable_lock = NULL;
|
||||
Mutex* ResolvedMethodTableWeakAlloc_lock = NULL;
|
||||
Mutex* ResolvedMethodTableWeakActive_lock = NULL;
|
||||
Mutex* JmethodIdCreation_lock = NULL;
|
||||
Mutex* JfieldIdCreation_lock = NULL;
|
||||
Monitor* JNICritical_lock = NULL;
|
||||
@ -212,6 +213,9 @@ void mutex_init() {
|
||||
def(StringTableWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never);
|
||||
def(StringTableWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never);
|
||||
|
||||
def(ResolvedMethodTableWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never);
|
||||
def(ResolvedMethodTableWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never);
|
||||
|
||||
if (UseConcMarkSweepGC || UseG1GC) {
|
||||
def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent
|
||||
}
|
||||
@ -298,7 +302,6 @@ void mutex_init() {
|
||||
|
||||
def(Heap_lock , PaddedMonitor, nonleaf+1, false, Monitor::_safepoint_check_sometimes);
|
||||
def(JfieldIdCreation_lock , PaddedMutex , nonleaf+1, true, Monitor::_safepoint_check_always); // jfieldID, Used in VM_Operation
|
||||
def(ResolvedMethodTable_lock , PaddedMutex , nonleaf+1, false, Monitor::_safepoint_check_always); // Used to protect ResolvedMethodTable
|
||||
|
||||
def(CompiledIC_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_never); // locks VtableStubs_lock, InlineCacheBuffer_lock
|
||||
def(CompileTaskAlloc_lock , PaddedMutex , nonleaf+2, true, Monitor::_safepoint_check_always);
|
||||
|
@ -48,7 +48,8 @@ extern Mutex* StringTableWeakActive_lock; // STringTable weak storage act
|
||||
extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list
|
||||
extern Mutex* VMWeakAlloc_lock; // VM Weak Handles storage allocate list lock
|
||||
extern Mutex* VMWeakActive_lock; // VM Weak Handles storage active list lock
|
||||
extern Mutex* ResolvedMethodTable_lock; // a lock on the ResolvedMethodTable updates
|
||||
extern Mutex* ResolvedMethodTableWeakAlloc_lock; // ResolvedMethodTable weak storage allocate list
|
||||
extern Mutex* ResolvedMethodTableWeakActive_lock; // ResolvedMethodTable weak storage active list
|
||||
extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers
|
||||
extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers
|
||||
extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
|
||||
|
@ -190,7 +190,7 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||
}
|
||||
|
||||
if (resolved_method_table_work) {
|
||||
ResolvedMethodTable::unlink();
|
||||
ResolvedMethodTable::do_concurrent_work(jt);
|
||||
}
|
||||
|
||||
if (protection_domain_table_work) {
|
||||
|
@ -1918,7 +1918,7 @@ bool SharedRuntime::should_fixup_call_destination(address destination, address e
|
||||
// where we went int -> i2c -> c2i and so the caller could in fact be
|
||||
// interpreted. If the caller is compiled we attempt to patch the caller
|
||||
// so he no longer calls into the interpreter.
|
||||
IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc))
|
||||
JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc))
|
||||
Method* moop(method);
|
||||
|
||||
address entry_point = moop->from_compiled_entry_no_trampoline();
|
||||
@ -1987,7 +1987,7 @@ IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
|
||||
}
|
||||
}
|
||||
}
|
||||
IRT_END
|
||||
JRT_END
|
||||
|
||||
|
||||
// same as JVM_Arraycopy, but called directly from compiled code
|
||||
|
@ -1415,7 +1415,7 @@ class JavaThread: public Thread {
|
||||
// Whenever a thread transitions from native to vm/java it must suspend
|
||||
// if external|deopt suspend is present.
|
||||
bool is_suspend_after_native() const {
|
||||
return (_suspend_flags & (_external_suspend | _deopt_suspend)) != 0;
|
||||
return (_suspend_flags & (_external_suspend | _deopt_suspend JFR_ONLY(| _trace_flag))) != 0;
|
||||
}
|
||||
|
||||
// external suspend request is completed
|
||||
|
@ -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
|
||||
@ -590,12 +590,9 @@ ThreadsList *ThreadsList::add_thread(ThreadsList *list, JavaThread *java_thread)
|
||||
}
|
||||
|
||||
void ThreadsList::dec_nested_handle_cnt() {
|
||||
// The decrement needs to be MO_ACQ_REL. At the moment, the Atomic::dec
|
||||
// backend on PPC does not yet conform to these requirements. Therefore
|
||||
// the decrement is simulated with an Atomic::sub(1, &addr).
|
||||
// Without this MO_ACQ_REL Atomic::dec simulation, the nested SMR mechanism
|
||||
// is not generally safe to use.
|
||||
Atomic::sub(1, &_nested_handle_cnt);
|
||||
// The decrement only needs to be MO_ACQ_REL since the reference
|
||||
// counter is volatile (and the hazard ptr is already NULL).
|
||||
Atomic::dec(&_nested_handle_cnt);
|
||||
}
|
||||
|
||||
int ThreadsList::find_index_of_JavaThread(JavaThread *target) {
|
||||
@ -626,19 +623,9 @@ JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const {
|
||||
}
|
||||
|
||||
void ThreadsList::inc_nested_handle_cnt() {
|
||||
// The increment needs to be MO_SEQ_CST. At the moment, the Atomic::inc
|
||||
// backend on PPC does not yet conform to these requirements. Therefore
|
||||
// the increment is simulated with a load phi; cas phi + 1; loop.
|
||||
// Without this MO_SEQ_CST Atomic::inc simulation, the nested SMR mechanism
|
||||
// is not generally safe to use.
|
||||
intx sample = OrderAccess::load_acquire(&_nested_handle_cnt);
|
||||
for (;;) {
|
||||
if (Atomic::cmpxchg(sample + 1, &_nested_handle_cnt, sample) == sample) {
|
||||
return;
|
||||
} else {
|
||||
sample = OrderAccess::load_acquire(&_nested_handle_cnt);
|
||||
}
|
||||
}
|
||||
// The increment needs to be MO_SEQ_CST so that the reference counter
|
||||
// update is seen before the subsequent hazard ptr update.
|
||||
Atomic::inc(&_nested_handle_cnt);
|
||||
}
|
||||
|
||||
bool ThreadsList::includes(const JavaThread * const p) const {
|
||||
|
@ -279,8 +279,10 @@
|
||||
|
||||
#if INCLUDE_JFR
|
||||
#define JFR_ONLY(code) code
|
||||
#define NOT_JFR_RETURN_(code) /* next token must be ; */
|
||||
#else
|
||||
#define JFR_ONLY(code)
|
||||
#define NOT_JFR_RETURN_(code) { return code; }
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_JVMCI
|
||||
|
@ -25,15 +25,16 @@
|
||||
|
||||
package jdk.internal.platform.cgroupv1;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
|
||||
|
||||
public class Metrics implements jdk.internal.platform.Metrics {
|
||||
private SubSystem memory;
|
||||
private MemorySubSystem memory;
|
||||
private SubSystem cpu;
|
||||
private SubSystem cpuacct;
|
||||
private SubSystem cpuset;
|
||||
@ -133,7 +134,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
for (String subsystemName: subsystemNames) {
|
||||
switch (subsystemName) {
|
||||
case "memory":
|
||||
metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
|
||||
metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4]));
|
||||
break;
|
||||
case "cpuset":
|
||||
metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
|
||||
@ -195,6 +196,11 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
|
||||
if (subsystem != null) {
|
||||
subsystem.setPath(base);
|
||||
if (subsystem instanceof MemorySubSystem) {
|
||||
MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
|
||||
boolean isHierarchial = getHierarchical(memorySubSystem);
|
||||
memorySubSystem.setHierarchical(isHierarchial);
|
||||
}
|
||||
metric.setActiveSubSystems();
|
||||
}
|
||||
if (subsystem2 != null) {
|
||||
@ -203,6 +209,11 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
}
|
||||
|
||||
|
||||
private static boolean getHierarchical(MemorySubSystem subsystem) {
|
||||
long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
|
||||
return hierarchical > 0;
|
||||
}
|
||||
|
||||
private void setActiveSubSystems() {
|
||||
activeSubSystems = true;
|
||||
}
|
||||
@ -211,7 +222,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
return activeSubSystems;
|
||||
}
|
||||
|
||||
private void setMemorySubSystem(SubSystem memory) {
|
||||
private void setMemorySubSystem(MemorySubSystem memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
@ -366,9 +377,29 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
|
||||
public long getMemoryLimit() {
|
||||
long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes");
|
||||
if (retval > unlimited_minimum) {
|
||||
if (memory.isHierarchical()) {
|
||||
// memory.limit_in_bytes returned unlimited, attempt
|
||||
// hierarchical memory limit
|
||||
String match = "hierarchical_memory_limit";
|
||||
retval = SubSystem.getLongValueMatchingLine(memory,
|
||||
"memory.stat",
|
||||
match,
|
||||
Metrics::convertHierachicalLimitLine);
|
||||
}
|
||||
}
|
||||
return retval > unlimited_minimum ? -1L : retval;
|
||||
}
|
||||
|
||||
public static long convertHierachicalLimitLine(String line) {
|
||||
String[] tokens = line.split("\\s");
|
||||
if (tokens.length == 2) {
|
||||
String strVal = tokens[1];
|
||||
return SubSystem.convertStringToLong(strVal);
|
||||
}
|
||||
return unlimited_minimum + 1; // unlimited
|
||||
}
|
||||
|
||||
public long getMemoryMaxUsage() {
|
||||
return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes");
|
||||
}
|
||||
@ -417,6 +448,17 @@ public class Metrics implements jdk.internal.platform.Metrics {
|
||||
|
||||
public long getMemoryAndSwapLimit() {
|
||||
long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
|
||||
if (retval > unlimited_minimum) {
|
||||
if (memory.isHierarchical()) {
|
||||
// memory.memsw.limit_in_bytes returned unlimited, attempt
|
||||
// hierarchical memory limit
|
||||
String match = "hierarchical_memsw_limit";
|
||||
retval = SubSystem.getLongValueMatchingLine(memory,
|
||||
"memory.stat",
|
||||
match,
|
||||
Metrics::convertHierachicalLimitLine);
|
||||
}
|
||||
}
|
||||
return retval > unlimited_minimum ? -1L : retval;
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,11 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SubSystem {
|
||||
@ -99,10 +100,32 @@ public class SubSystem {
|
||||
|
||||
}
|
||||
|
||||
public static long getLongValueMatchingLine(SubSystem subsystem,
|
||||
String param,
|
||||
String match,
|
||||
Function<String, Long> conversion) {
|
||||
long retval = Metrics.unlimited_minimum + 1; // default unlimited
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(Paths.get(subsystem.path(), param));
|
||||
for (String line: lines) {
|
||||
if (line.contains(match)) {
|
||||
retval = conversion.apply(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore. Default is unlimited.
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
public static long getLongValue(SubSystem subsystem, String parm) {
|
||||
String strval = getStringValue(subsystem, parm);
|
||||
long retval = 0;
|
||||
return convertStringToLong(strval);
|
||||
}
|
||||
|
||||
public static long convertStringToLong(String strval) {
|
||||
long retval = 0;
|
||||
if (strval == null) return 0L;
|
||||
|
||||
try {
|
||||
@ -215,4 +238,22 @@ public class SubSystem {
|
||||
|
||||
return ints;
|
||||
}
|
||||
|
||||
public static class MemorySubSystem extends SubSystem {
|
||||
|
||||
private boolean hierarchical;
|
||||
|
||||
public MemorySubSystem(String root, String mountPoint) {
|
||||
super(root, mountPoint);
|
||||
}
|
||||
|
||||
boolean isHierarchical() {
|
||||
return hierarchical;
|
||||
}
|
||||
|
||||
void setHierarchical(boolean hierarchical) {
|
||||
this.hierarchical = hierarchical;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -263,13 +263,13 @@ public final class RSACipher extends CipherSpi {
|
||||
throw new InvalidKeyException("Unknown mode: " + opmode);
|
||||
}
|
||||
RSAKey rsaKey = RSAKeyFactory.toRSAKey(key);
|
||||
if (key instanceof RSAPublicKey) {
|
||||
if (rsaKey instanceof RSAPublicKey) {
|
||||
mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
|
||||
publicKey = (RSAPublicKey)key;
|
||||
publicKey = (RSAPublicKey)rsaKey;
|
||||
privateKey = null;
|
||||
} else { // must be RSAPrivateKey per check in toRSAKey
|
||||
mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
|
||||
privateKey = (RSAPrivateKey)key;
|
||||
privateKey = (RSAPrivateKey)rsaKey;
|
||||
publicKey = null;
|
||||
}
|
||||
int n = RSACore.getByteLength(rsaKey.getModulus());
|
||||
|
@ -277,8 +277,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
.collect(Collectors.joining(",", "<", ">")));
|
||||
}
|
||||
|
||||
for (int i = 0; i < arrayDepth; i++)
|
||||
sb.append("[]");
|
||||
if (arrayDepth > 0) sb.append("[]".repeat(arrayDepth));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
@ -1589,12 +1588,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
dimensions++;
|
||||
cl = cl.getComponentType();
|
||||
} while (cl.isArray());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(cl.getName());
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
return cl.getName() + "[]".repeat(dimensions);
|
||||
} catch (Throwable e) { /*FALLTHRU*/ }
|
||||
}
|
||||
return getName();
|
||||
@ -3418,15 +3412,12 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* Helper method to get the method name from arguments.
|
||||
*/
|
||||
private String methodToString(String name, Class<?>[] argTypes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName() + "." + name + "(");
|
||||
if (argTypes != null) {
|
||||
sb.append(Arrays.stream(argTypes)
|
||||
.map(c -> (c == null) ? "null" : c.getName())
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
return getName() + '.' + name +
|
||||
((argTypes == null || argTypes.length == 0) ?
|
||||
"()" :
|
||||
Arrays.stream(argTypes)
|
||||
.map(c -> c == null ? "null" : c.getName())
|
||||
.collect(Collectors.joining(",", "(", ")")));
|
||||
}
|
||||
|
||||
/** use serialVersionUID from JDK 1.1 for interoperability */
|
||||
|
@ -1965,20 +1965,7 @@ public final class String
|
||||
if (str.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
if (coder() == str.coder()) {
|
||||
byte[] val = this.value;
|
||||
byte[] oval = str.value;
|
||||
int len = val.length + oval.length;
|
||||
byte[] buf = Arrays.copyOf(val, len);
|
||||
System.arraycopy(oval, 0, buf, val.length, oval.length);
|
||||
return new String(buf, coder);
|
||||
}
|
||||
int len = length();
|
||||
int olen = str.length();
|
||||
byte[] buf = StringUTF16.newBytesFor(len + olen);
|
||||
getBytes(buf, 0, UTF16);
|
||||
str.getBytes(buf, len, UTF16);
|
||||
return new String(buf, UTF16);
|
||||
return StringConcatHelper.simpleConcat(this, str);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
package java.lang;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
/**
|
||||
* Helper for string concatenation. These methods are mostly looked up with private lookups
|
||||
* from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
|
||||
@ -38,8 +41,10 @@ final class StringConcatHelper {
|
||||
|
||||
/**
|
||||
* Check for overflow, throw exception on overflow.
|
||||
* @param lengthCoder String length and coder
|
||||
* @return lengthCoder
|
||||
*
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @return the given parameter value, if valid
|
||||
*/
|
||||
private static long checkOverflow(long lengthCoder) {
|
||||
if ((int)lengthCoder >= 0) {
|
||||
@ -50,76 +55,83 @@ final class StringConcatHelper {
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, boolean value) {
|
||||
return checkOverflow(current + (value ? 4 : 5));
|
||||
static long mix(long lengthCoder, boolean value) {
|
||||
return checkOverflow(lengthCoder + (value ? 4 : 5));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, byte value) {
|
||||
return mix(current, (int)value);
|
||||
static long mix(long lengthCoder, byte value) {
|
||||
return mix(lengthCoder, (int)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, char value) {
|
||||
return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
|
||||
static long mix(long lengthCoder, char value) {
|
||||
return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, short value) {
|
||||
return mix(current, (int)value);
|
||||
static long mix(long lengthCoder, short value) {
|
||||
return mix(lengthCoder, (int)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, int value) {
|
||||
return checkOverflow(current + Integer.stringSize(value));
|
||||
static long mix(long lengthCoder, int value) {
|
||||
return checkOverflow(lengthCoder + Integer.stringSize(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, long value) {
|
||||
return checkOverflow(current + Long.stringSize(value));
|
||||
static long mix(long lengthCoder, long value) {
|
||||
return checkOverflow(lengthCoder + Long.stringSize(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, String value) {
|
||||
current += value.length();
|
||||
static long mix(long lengthCoder, String value) {
|
||||
lengthCoder += value.length();
|
||||
if (value.coder() == String.UTF16) {
|
||||
current |= UTF16;
|
||||
lengthCoder |= UTF16;
|
||||
}
|
||||
return checkOverflow(current);
|
||||
return checkOverflow(lengthCoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,10 +297,62 @@ final class StringConcatHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a simple concatenation between two objects. Added for startup
|
||||
* performance, but also demonstrates the code that would be emitted by
|
||||
* {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy}
|
||||
* for two Object arguments.
|
||||
*
|
||||
* @param first first argument
|
||||
* @param second second argument
|
||||
* @return String resulting string
|
||||
*/
|
||||
@ForceInline
|
||||
static String simpleConcat(Object first, Object second) {
|
||||
String s1 = stringOf(first);
|
||||
String s2 = stringOf(second);
|
||||
// start "mixing" in length and coder or arguments, order is not
|
||||
// important
|
||||
long indexCoder = mix(initialCoder(), s2);
|
||||
indexCoder = mix(indexCoder, s1);
|
||||
byte[] buf = newArray(indexCoder);
|
||||
// prepend each argument in reverse order, since we prepending
|
||||
// from the end of the byte array
|
||||
indexCoder = prepend(indexCoder, buf, s2);
|
||||
indexCoder = prepend(indexCoder, buf, s1);
|
||||
return newString(buf, indexCoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* We need some additional conversion for Objects in general, because
|
||||
* {@code String.valueOf(Object)} may return null. String conversion rules
|
||||
* in Java state we need to produce "null" String in this case, so we
|
||||
* provide a customized version that deals with this problematic corner case.
|
||||
*/
|
||||
static String stringOf(Object value) {
|
||||
String s;
|
||||
return (value == null || (s = value.toString()) == null) ? "null" : s;
|
||||
}
|
||||
|
||||
private static final long LATIN1 = (long)String.LATIN1 << 32;
|
||||
|
||||
private static final long UTF16 = (long)String.UTF16 << 32;
|
||||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
/**
|
||||
* Allocates an uninitialized byte array based on the length and coder information
|
||||
* in indexCoder
|
||||
* @param indexCoder
|
||||
* @return the newly allocated byte array
|
||||
*/
|
||||
@ForceInline
|
||||
static byte[] newArray(long indexCoder) {
|
||||
byte coder = (byte)(indexCoder >> 32);
|
||||
int index = (int)indexCoder;
|
||||
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the initial coder for the String.
|
||||
* @return initial coder, adjusted into the upper half
|
||||
|
@ -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
|
||||
@ -26,6 +26,7 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
@ -191,6 +192,8 @@ public final class StringConcatFactory {
|
||||
*/
|
||||
private static final ProxyClassesDumper DUMPER;
|
||||
|
||||
private static final Class<?> STRING_HELPER;
|
||||
|
||||
static {
|
||||
// In case we need to double-back onto the StringConcatFactory during this
|
||||
// static initialization, make sure we have the reasonable defaults to complete
|
||||
@ -202,15 +205,20 @@ public final class StringConcatFactory {
|
||||
// DEBUG = false; // implied
|
||||
// DUMPER = null; // implied
|
||||
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
try {
|
||||
STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
|
||||
} catch (Throwable e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
final String strategy =
|
||||
props.getProperty("java.lang.invoke.stringConcat");
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat");
|
||||
CACHE_ENABLE = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.stringConcat.cache"));
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.cache"));
|
||||
DEBUG = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.stringConcat.debug"));
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.debug"));
|
||||
final String dumpPath =
|
||||
props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.dumpClasses");
|
||||
|
||||
STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
|
||||
CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
|
||||
@ -1519,6 +1527,33 @@ public final class StringConcatFactory {
|
||||
|
||||
static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
|
||||
|
||||
// Fast-path two-argument Object + Object concatenations
|
||||
if (recipe.getElements().size() == 2) {
|
||||
// Two object arguments
|
||||
if (mt.parameterCount() == 2 &&
|
||||
!mt.parameterType(0).isPrimitive() &&
|
||||
!mt.parameterType(1).isPrimitive()) {
|
||||
return SIMPLE;
|
||||
}
|
||||
// One element is a constant
|
||||
if (mt.parameterCount() == 1 && !mt.parameterType(0).isPrimitive()) {
|
||||
MethodHandle mh = SIMPLE;
|
||||
// Insert constant element
|
||||
|
||||
// First recipe element is a constant
|
||||
if (recipe.getElements().get(0).getTag() == TAG_CONST &&
|
||||
recipe.getElements().get(1).getTag() != TAG_CONST) {
|
||||
return MethodHandles.insertArguments(mh, 0,
|
||||
recipe.getElements().get(0).getValue());
|
||||
} else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
|
||||
recipe.getElements().get(0).getTag() != TAG_CONST) {
|
||||
return MethodHandles.insertArguments(mh, 1,
|
||||
recipe.getElements().get(1).getValue());
|
||||
}
|
||||
// else... fall-through to slow-path
|
||||
}
|
||||
}
|
||||
|
||||
// Create filters and obtain filtered parameter types. Filters would be used in the beginning
|
||||
// to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
|
||||
// The filtered argument type list is used all over in the combinators below.
|
||||
@ -1626,13 +1661,6 @@ public final class StringConcatFactory {
|
||||
return mh;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
private static byte[] newArray(long indexCoder) {
|
||||
byte coder = (byte)(indexCoder >> 32);
|
||||
int index = (int)indexCoder;
|
||||
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
|
||||
}
|
||||
|
||||
private static MethodHandle prepender(Class<?> cl) {
|
||||
return PREPENDERS.computeIfAbsent(cl, PREPEND);
|
||||
}
|
||||
@ -1659,16 +1687,15 @@ public final class StringConcatFactory {
|
||||
}
|
||||
};
|
||||
|
||||
private static final MethodHandle SIMPLE;
|
||||
private static final MethodHandle NEW_STRING;
|
||||
private static final MethodHandle NEW_ARRAY;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> MIXERS;
|
||||
private static final long INITIAL_CODER;
|
||||
static final Class<?> STRING_HELPER;
|
||||
|
||||
static {
|
||||
try {
|
||||
STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
|
||||
MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", long.class);
|
||||
INITIAL_CODER = (long) initCoder.invoke();
|
||||
} catch (Throwable e) {
|
||||
@ -1678,8 +1705,9 @@ public final class StringConcatFactory {
|
||||
PREPENDERS = new ConcurrentHashMap<>();
|
||||
MIXERS = new ConcurrentHashMap<>();
|
||||
|
||||
SIMPLE = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "simpleConcat", String.class, Object.class, Object.class);
|
||||
NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, long.class);
|
||||
NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, long.class);
|
||||
NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newArray", byte[].class, long.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1692,22 +1720,8 @@ public final class StringConcatFactory {
|
||||
// no instantiation
|
||||
}
|
||||
|
||||
private static class ObjectStringifier {
|
||||
|
||||
// We need some additional conversion for Objects in general, because String.valueOf(Object)
|
||||
// may return null. String conversion rules in Java state we need to produce "null" String
|
||||
// in this case, so we provide a customized version that deals with this problematic corner case.
|
||||
private static String valueOf(Object value) {
|
||||
String s;
|
||||
return (value == null || (s = value.toString()) == null) ? "null" : s;
|
||||
}
|
||||
|
||||
// Could have used MethodHandles.lookup() instead of Lookup.IMPL_LOOKUP, if not for the fact
|
||||
// java.lang.invoke Lookups are explicitly forbidden to be retrieved using that API.
|
||||
private static final MethodHandle INSTANCE =
|
||||
lookupStatic(Lookup.IMPL_LOOKUP, ObjectStringifier.class, "valueOf", String.class, Object.class);
|
||||
|
||||
}
|
||||
private static final MethodHandle OBJECT_INSTANCE =
|
||||
lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "stringOf", String.class, Object.class);
|
||||
|
||||
private static class FloatStringifiers {
|
||||
private static final MethodHandle FLOAT_INSTANCE =
|
||||
@ -1751,7 +1765,7 @@ public final class StringConcatFactory {
|
||||
*/
|
||||
static MethodHandle forMost(Class<?> t) {
|
||||
if (!t.isPrimitive()) {
|
||||
return ObjectStringifier.INSTANCE;
|
||||
return OBJECT_INSTANCE;
|
||||
} else if (t == float.class) {
|
||||
return FloatStringifiers.FLOAT_INSTANCE;
|
||||
} else if (t == double.class) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -3414,9 +3414,32 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
*/
|
||||
@Override
|
||||
public long longValue(){
|
||||
return (intCompact != INFLATED && scale == 0) ?
|
||||
intCompact:
|
||||
toBigInteger().longValue();
|
||||
if (intCompact != INFLATED && scale == 0) {
|
||||
return intCompact;
|
||||
} else {
|
||||
// Fastpath zero and small values
|
||||
if (this.signum() == 0 || fractionOnly() ||
|
||||
// Fastpath very large-scale values that will result
|
||||
// in a truncated value of zero. If the scale is -64
|
||||
// or less, there are at least 64 powers of 10 in the
|
||||
// value of the numerical result. Since 10 = 2*5, in
|
||||
// that case there would also be 64 powers of 2 in the
|
||||
// result, meaning all 64 bits of a long will be zero.
|
||||
scale <= -64) {
|
||||
return 0;
|
||||
} else {
|
||||
return toBigInteger().longValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a nonzero BigDecimal has an absolute value less
|
||||
* than one; i.e. only has fraction digits.
|
||||
*/
|
||||
private boolean fractionOnly() {
|
||||
assert this.signum() != 0;
|
||||
return (this.precision() - this.scale) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3434,15 +3457,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
public long longValueExact() {
|
||||
if (intCompact != INFLATED && scale == 0)
|
||||
return intCompact;
|
||||
|
||||
// Fastpath zero
|
||||
if (this.signum() == 0)
|
||||
return 0;
|
||||
|
||||
// Fastpath numbers less than 1.0 (the latter can be very slow
|
||||
// to round if very small)
|
||||
if (fractionOnly())
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
|
||||
// If more than 19 digits in integer part it cannot possibly fit
|
||||
if ((precision() - scale) > 19) // [OK for negative scale too]
|
||||
throw new java.lang.ArithmeticException("Overflow");
|
||||
// Fastpath zero and < 1.0 numbers (the latter can be very slow
|
||||
// to round if very small)
|
||||
if (this.signum() == 0)
|
||||
return 0;
|
||||
if ((this.precision() - this.scale) <= 0)
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
|
||||
// round to an integer, with Exception if decimal part non-0
|
||||
BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
|
||||
if (num.precision() >= 19) // need to check carefully
|
||||
@ -3486,7 +3514,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
public int intValue() {
|
||||
return (intCompact != INFLATED && scale == 0) ?
|
||||
(int)intCompact :
|
||||
toBigInteger().intValue();
|
||||
(int)longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -791,7 +791,7 @@ public abstract class FileChannel
|
||||
// -- Memory-mapped buffers --
|
||||
|
||||
/**
|
||||
* A typesafe enumeration for file-mapping modes.
|
||||
* A file-mapping mode.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
@ -819,6 +819,12 @@ public abstract class FileChannel
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class. This constructor may be used
|
||||
* by code in java.base to create file mapping modes beyond the file
|
||||
* mapping modes defined here.
|
||||
* @param name the name of the map mode
|
||||
*/
|
||||
private MapMode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@ -837,8 +843,8 @@ public abstract class FileChannel
|
||||
/**
|
||||
* Maps a region of this channel's file directly into memory.
|
||||
*
|
||||
* <p> A region of a file may be mapped into memory in one of three modes:
|
||||
* </p>
|
||||
* <p> The {@code mode} parameter specifies how the region of the file is
|
||||
* mapped and may be one of the following modes:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
@ -859,6 +865,8 @@ public abstract class FileChannel
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> An implementation may support additional map modes.
|
||||
*
|
||||
* <p> For a read-only mapping, this channel must have been opened for
|
||||
* reading; for a read/write or private mapping, this channel must have
|
||||
* been opened for both reading and writing.
|
||||
@ -892,7 +900,8 @@ public abstract class FileChannel
|
||||
* MapMode#READ_WRITE READ_WRITE}, or {@link MapMode#PRIVATE
|
||||
* PRIVATE} defined in the {@link MapMode} class, according to
|
||||
* whether the file is to be mapped read-only, read/write, or
|
||||
* privately (copy-on-write), respectively
|
||||
* privately (copy-on-write), respectively, or an implementation
|
||||
* specific map mode
|
||||
*
|
||||
* @param position
|
||||
* The position within the file at which the mapped region
|
||||
@ -905,25 +914,29 @@ public abstract class FileChannel
|
||||
* @return The mapped byte buffer
|
||||
*
|
||||
* @throws NonReadableChannelException
|
||||
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} but
|
||||
* this channel was not opened for reading
|
||||
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} or
|
||||
* an implementation specific map mode requiring read access
|
||||
* but this channel was not opened for reading
|
||||
*
|
||||
* @throws NonWritableChannelException
|
||||
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE} or
|
||||
* {@link MapMode#PRIVATE PRIVATE} but this channel was not opened
|
||||
* for both reading and writing
|
||||
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE}.
|
||||
* {@link MapMode#PRIVATE PRIVATE} or an implementation specific
|
||||
* map mode requiring write access but this channel was not
|
||||
* opened for both reading and writing
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the preconditions on the parameters do not hold
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If an unsupported map mode is specified
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*
|
||||
* @see java.nio.channels.FileChannel.MapMode
|
||||
* @see java.nio.MappedByteBuffer
|
||||
*/
|
||||
public abstract MappedByteBuffer map(MapMode mode,
|
||||
long position, long size)
|
||||
public abstract MappedByteBuffer map(MapMode mode, long position, long size)
|
||||
throws IOException;
|
||||
|
||||
|
||||
|
@ -154,6 +154,8 @@ public final class JapaneseEra
|
||||
* The singleton instance for the 'Reiwa' era (2019-05-01 - )
|
||||
* which has the value 3. The end date of this era is not specified, unless
|
||||
* the Japanese Government defines it.
|
||||
*
|
||||
* @since 13
|
||||
*/
|
||||
public static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1));
|
||||
|
||||
|
@ -940,14 +940,15 @@ public class FileChannelImpl
|
||||
if (size > Integer.MAX_VALUE)
|
||||
throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
|
||||
|
||||
int imode = -1;
|
||||
int imode;
|
||||
if (mode == MapMode.READ_ONLY)
|
||||
imode = MAP_RO;
|
||||
else if (mode == MapMode.READ_WRITE)
|
||||
imode = MAP_RW;
|
||||
else if (mode == MapMode.PRIVATE)
|
||||
imode = MAP_PV;
|
||||
assert (imode >= 0);
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
if ((mode != MapMode.READ_ONLY) && !writable)
|
||||
throw new NonWritableChannelException();
|
||||
if (!readable)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user