OpenJDK / jdk / jdk
changeset 53333:fd6de53a0d6e
Merge
author | henryjen |
---|---|
date | Thu, 13 Dec 2018 11:47:35 -0800 |
parents | ab474ef0a0ac 086dfcfc3731 |
children | b94283cb226b |
files | make/scripts/pandoc-manpage-filter.js make/scripts/pandoc-manpage-filter.sh.template src/hotspot/share/classfile/classFileParser.cpp src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java src/java.logging/share/classes/java/util/logging/package.html src/java.prefs/share/classes/java/util/prefs/package.html src/java.rmi/share/classes/java/rmi/activation/package.html src/java.rmi/share/classes/java/rmi/dgc/package.html src/java.rmi/share/classes/java/rmi/package.html src/java.rmi/share/classes/java/rmi/registry/package.html src/java.rmi/share/classes/java/rmi/server/package.html src/java.rmi/share/classes/javax/rmi/ssl/package.html src/java.security.jgss/share/classes/org/ietf/jgss/package.html src/java.smartcardio/share/classes/javax/smartcardio/package.html src/java.sql.rowset/share/classes/com/sun/rowset/package.html src/java.sql.rowset/share/classes/com/sun/rowset/providers/package.html src/java.sql.rowset/share/classes/javax/sql/rowset/serial/package.html src/java.sql/share/classes/java/sql/package.html src/java.sql/share/classes/javax/sql/package.html src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSACipher.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSASignature.java src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp src/jdk.internal.le/share/classes/jdk/internal/jline/DefaultTerminal2.java src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/OSvTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal2.java src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/WCWidth.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AnsiStringsCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/extra/AnsiInterpretingOutputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Ansi.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Curses.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InfoCmp.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/NonBlockingInputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeAccess.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_75_ffffff_40x100.png src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_65_ffffff_1x400.png test/jdk/jdk/internal/jline/console/StripAnsiTest.java test/jdk/jdk/internal/jline/extra/AnsiInterpretingOutputStreamTest.java test/jdk/jdk/internal/jline/extra/HistoryTest.java |
diffstat | 709 files changed, 51292 insertions(+), 24046 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/building.html Thu Sep 13 01:49:48 2018 +0200 +++ b/doc/building.html Thu Dec 13 11:47:35 2018 -0800 @@ -1,19 +1,24 @@ <!DOCTYPE html> -<html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> <head> - <meta charset="utf-8"> - <meta name="generator" content="pandoc"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> + <meta charset="utf-8" /> + <meta name="generator" content="pandoc" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <title>Building the JDK</title> - <style type="text/css">code{white-space: pre;}</style> - <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css"> + <style type="text/css"> + code{white-space: pre-wrap;} + span.smallcaps{font-variant: small-caps;} + span.underline{text-decoration: underline;} + div.column{display: inline-block; vertical-align: top; width: 50%;} + </style> + <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" /> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <![endif]--> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style> </head> <body> -<header> +<header id="title-block-header"> <h1 class="title">Building the JDK</h1> </header> <nav id="TOC"> @@ -640,11 +645,13 @@ <p>Note that alsa is needed even if you only want to build a headless JDK.</p> <ul> <li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian Package Search</a> and search for the <code>libasound2</code> and <code>libasound2-dev</code> packages for your <em>target</em> system. Download them to /tmp.</p></li> -<li><p>Install the libraries into the cross-compilation toolchain. For instance:</p> +<li>Install the libraries into the cross-compilation toolchain. For instance:</li> +</ul> <pre><code>cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb . -dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li> -<li><p>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</p></li> +dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre> +<ul> +<li>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</li> </ul> <h4 id="x11-1">X11</h4> <p>You will need X11 libraries suitable for your <em>target</em> system. For most cases, using Debian's pre-built libraries work fine.</p> @@ -690,17 +697,21 @@ <p>Fortunately, you can create sysroots for foreign architectures with tools provided by your OS. On Debian/Ubuntu systems, one could use <code>qemu-deboostrap</code> to create the <em>target</em> system chroot, which would have the native libraries and headers specific to that <em>target</em> system. After that, we can use the cross-compiler on the <em>build</em> system, pointing into chroot to get the build dependencies right. This allows building for foreign architectures with native compilation speed.</p> <p>For example, cross-compiling to AArch64 from x86_64 could be done like this:</p> <ul> -<li><p>Install cross-compiler on the <em>build</em> system:</p> -<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre></li> -<li><p>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</p> +<li>Install cross-compiler on the <em>build</em> system:</li> +</ul> +<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre> +<ul> +<li>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</li> +</ul> <pre><code>sudo qemu-debootstrap --arch=arm64 --verbose \ - --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \ - --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre></li> -<li><p>Configure and build with newly created chroot as sysroot/toolchain-path:</p> + --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \ + --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre> +<ul> +<li>Configure and build with newly created chroot as sysroot/toolchain-path:</li> +</ul> <pre><code>CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ sh ./configure --openjdk-target=aarch64-linux-gnu --with-sysroot=/chroots/arm64/ --with-toolchain-path=/chroots/arm64/ make images -ls build/linux-aarch64-normal-server-release/</code></pre></li> -</ul> +ls build/linux-aarch64-normal-server-release/</code></pre> <p>The build does not create new files in that chroot, so it can be reused for multiple builds without additional cleanup.</p> <p>Architectures that are known to successfully cross-compile like this are:</p> <table> @@ -860,12 +871,7 @@ spawn failed</code></pre> <p>This can be a sign of a Cygwin problem. See the information about solving problems in the <a href="#cygwin">Cygwin</a> section. Rebooting the computer might help temporarily.</p> <h3 id="getting-help">Getting Help</h3> -<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <script type="text/javascript"> -<!-- -h='openjdk.java.net';a='@';n='build-dev';e=n+a+h; -document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>'); -// --> -</script><noscript>build-dev at openjdk dot java dot net</noscript>. Please include the relevant parts of the configure and/or build log.</p> +<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <a href="mailto:build-dev@openjdk.java.net">build-dev@openjdk.java.net</a>. Please include the relevant parts of the configure and/or build log.</p> <p>If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on <a href="#contributing-to-openjdk">Contributing to OpenJDK</a> for more information.</p> <h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</h2> <h3 id="setting-up-a-repository-for-pushing-changes-defpath">Setting Up a Repository for Pushing Changes (defpath)</h3>
--- a/doc/building.md Thu Sep 13 01:49:48 2018 +0200 +++ b/doc/building.md Thu Dec 13 11:47:35 2018 -0800 @@ -918,7 +918,7 @@ created. Currently, at least the following targets are known to work: Supported devkit targets - ------------------------ + ------------------------- x86_64-linux-gnu aarch64-linux-gnu arm-linux-gnueabihf @@ -1129,13 +1129,13 @@ Architectures that are known to successfully cross-compile like this are: - Target `CC` `CXX` `--arch=...` `--openjdk-target=...` - ------------ ------------------------- --------------------------- ------------ ---------------------- - x86 default default i386 i386-linux-gnu - armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf - aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu - ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu - s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu + Target `CC` `CXX` `--arch=...` `--openjdk-target=...` + ------------ ------------------------- --------------------------- ------------- ----------------------- + x86 default default i386 i386-linux-gnu + armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf + aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu + ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu + s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu Additional architectures might be supported by Debian/Ubuntu Ports.
--- a/doc/testing.html Thu Sep 13 01:49:48 2018 +0200 +++ b/doc/testing.html Thu Dec 13 11:47:35 2018 -0800 @@ -1,19 +1,24 @@ <!DOCTYPE html> -<html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> <head> - <meta charset="utf-8"> - <meta name="generator" content="pandoc"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> + <meta charset="utf-8" /> + <meta name="generator" content="pandoc" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <title>Testing the JDK</title> - <style type="text/css">code{white-space: pre;}</style> - <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css"> + <style type="text/css"> + code{white-space: pre-wrap;} + span.smallcaps{font-variant: small-caps;} + span.underline{text-decoration: underline;} + div.column{display: inline-block; vertical-align: top; width: 50%;} + </style> + <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" /> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <![endif]--> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style> </head> <body> -<header> +<header id="title-block-header"> <h1 class="title">Testing the JDK</h1> </header> <nav id="TOC">
--- a/make/CompileJavaModules.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/CompileJavaModules.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -321,7 +321,7 @@ ################################################################################ -jdk.internal.le_COPY += .properties +jdk.internal.le_COPY += .properties .caps .txt ################################################################################
--- a/make/CompileToolsJdk.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/CompileToolsJdk.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -91,15 +91,17 @@ # To be able to call the javascript filter when generating man pages using # pandoc, we need to create this executable wrapper script. ifneq ($(PANDOC), ) - # PANDOC_FILTER is duplicated for export in ToolsJdk.gmk. - PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter - PANDOC_FILTER_SETUP := $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_filter_setup.marker + # PANDOC_TROFF_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk. + PANDOC_TROFF_MANPAGE_FILTER := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-troff-manpage-filter + PANDOC_TROFF_MANPAGE_FILTER_SETUP := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_troff_manpage_filter_setup.marker # Create a usable instance of the wrapper script that calls the pandoc filter # (which is written in javascript). - $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_FILTER, \ - SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-manpage-filter.sh.template, \ - OUTPUT_FILE := $(PANDOC_FILTER), \ + $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_TROFF_MANPAGE_FILTER, \ + SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \ + OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \ REPLACEMENTS := \ @@BOOT_JDK@@ => $(BOOT_JDK) ; \ @@TOPDIR@@ => $(TOPDIR) ; \ @@ -107,11 +109,35 @@ )) # Created script must be made executable - $(PANDOC_FILTER_SETUP): $(CREATE_PANDOC_FILTER) - $(CHMOD) a+rx $(PANDOC_FILTER) + $(PANDOC_TROFF_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_TROFF_MANPAGE_FILTER) + $(CHMOD) a+rx $(PANDOC_TROFF_MANPAGE_FILTER) $(TOUCH) $@ - TARGETS += $(PANDOC_FILTER_SETUP) + TARGETS += $(PANDOC_TROFF_MANPAGE_FILTER_SETUP) + + # PANDOC_HTML_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk. + PANDOC_HTML_MANPAGE_FILTER := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-html-manpage-filter + PANDOC_HTML_MANPAGE_FILTER_SETUP := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_html_manpage_filter_setup.marker + + # Create a usable instance of the wrapper script that calls the pandoc filter + # (which is written in javascript). + $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_HTML_MANPAGE_FILTER, \ + SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.sh.template, \ + OUTPUT_FILE := $(PANDOC_HTML_MANPAGE_FILTER), \ + REPLACEMENTS := \ + @@BOOT_JDK@@ => $(BOOT_JDK) ; \ + @@TOPDIR@@ => $(TOPDIR) ; \ + @@JJS_FLAGS@@ => $(addprefix -J, $(JAVA_FLAGS_SMALL)), \ + )) + + # Created script must be made executable + $(PANDOC_HTML_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_HTML_MANPAGE_FILTER) + $(CHMOD) a+rx $(PANDOC_HTML_MANPAGE_FILTER) + $(TOUCH) $@ + + TARGETS += $(PANDOC_HTML_MANPAGE_FILTER_SETUP) endif all: $(TARGETS)
--- a/make/Docs.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/Docs.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -27,10 +27,10 @@ include $(SPEC) include MakeBase.gmk include Modules.gmk +include ModuleTools.gmk include ProcessMarkdown.gmk +include ToolsJdk.gmk include ZipArchive.gmk -include $(TOPDIR)/make/ToolsJdk.gmk -include $(TOPDIR)/make/ModuleTools.gmk # This is needed to properly setup DOCS_MODULES. $(eval $(call ReadImportMetaData)) @@ -168,14 +168,6 @@ font-family: DejaVu Sans, Arial, Helvetica, sans-serif; \ font-weight: normal;">$(DRAFT_TEXT)</div> -JDK_INDEX_CONTENT := \ - <!DOCTYPE html> \ - <html lang="en"> \ - <head> \ - <meta http-equiv="refresh" content="0;url=api/index.html"> \ - </head> \ - </html> - ################################################################################ # JDK javadoc titles/text snippets @@ -485,14 +477,7 @@ ################################################################################ -JDK_INDEX_HTML := $(DOCS_OUTPUTDIR)/index.html - -$(JDK_INDEX_HTML): - $(ECHO) '$(JDK_INDEX_CONTENT)' > $@ - -JDK_INDEX_TARGETS += $(JDK_INDEX_HTML) - -# Copy the global resources +# Copy the global resources, including the top-level redirect index.html GLOBAL_SPECS_RESOURCES_DIR := $(TOPDIR)/make/data/docs-resources/ $(eval $(call SetupCopyFiles, COPY_GLOBAL_RESOURCES, \ SRC := $(GLOBAL_SPECS_RESOURCES_DIR), \ @@ -532,9 +517,9 @@ ) \ ) -ifeq ($(ENABLE_FULL_DOCS), true) +ifneq ($(PANDOC), ) # For all markdown files in $module/share/specs directories, convert them to - # html. + # html, if we have pandoc (otherwise we'll just skip this). GLOBAL_SPECS_DEFAULT_CSS_FILE := $(DOCS_OUTPUTDIR)/resources/jdk-default.css @@ -556,6 +541,15 @@ # For all markdown files in $module/share/man directories, convert them to # html. + + # Create dynamic man pages from markdown using pandoc. We need + # PANDOC_HTML_MANPAGE_FILTER, a wrapper around + # PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. + + # We should also depend on the source javascript filter + PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT := \ + $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.js + $(foreach m, $(ALL_MODULES), \ $(eval MAN_$m := $(call FindModuleManDirs, $m)) \ $(foreach d, $(MAN_$m), \ @@ -565,8 +559,11 @@ SRC := $d, \ FILES := $(filter %.md, $(call CacheFind, $d)), \ DEST := $(DOCS_OUTPUTDIR)/specs/man, \ + FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ + EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ + $(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \ )) \ $(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \ ) \
--- a/make/Images.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/Images.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -36,7 +36,7 @@ # Hook to include the corresponding custom file, if present. $(eval $(call IncludeCustomExtension, Images-pre.gmk)) -############################################################################ +################################################################################ # All modules for the current target platform. ALL_MODULES := $(call FindAllModules) @@ -57,7 +57,7 @@ JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod) # Use this file inside the image as target for make rule -JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX) +JIMAGE_TARGET_FILE := release JLINK_ORDER_RESOURCES := **module-info.class JLINK_JLI_CLASSES :=
--- a/make/Main.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/Main.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -862,8 +862,6 @@ docs-jdk-specs: $(JVM_DOCS_TARGETS) jdk.jdi-gensrc \ docs-jdk-index - docs-jdk-index: exploded-image buildtools-modules - docs-zip: docs-jdk # Tests
--- a/make/ToolsJdk.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/ToolsJdk.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -118,7 +118,8 @@ # Executable javascript filter for man page generation using pandoc. -PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter +PANDOC_TROFF_MANPAGE_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-troff-manpage-filter +PANDOC_HTML_MANPAGE_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-html-manpage-filter ##########################################################################################
--- a/make/common/ProcessMarkdown.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/common/ProcessMarkdown.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -80,7 +80,7 @@ $$(call LogInfo, Converting $2 to $$($1_FORMAT)) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT))) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \ - $$(PANDOC) $$($1_OPTIONS) -f markdown -t $$($1_FORMAT) --standalone \ + $$(PANDOC) $$($1_OPTIONS) -f markdown-smart -t $$($1_FORMAT) --standalone \ $$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS) '$$($1_$2_PANDOC_INPUT)' \ -o '$$($1_$2_PANDOC_OUTPUT)') ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
--- a/make/data/characterdata/CharacterData00.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterData00.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -754,6 +754,21 @@ return retval; } + boolean isDigit(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterData01.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterData01.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -460,6 +460,21 @@ return retval; } + boolean isDigit(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterData02.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterData02.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,6 +217,21 @@ return retval; } + boolean isDigit(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { return (getProperties(ch) & $$maskIdentifierInfo) == $$valueJavaWhitespace; }
--- a/make/data/characterdata/CharacterData0E.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterData0E.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,6 +217,21 @@ return retval; } + boolean isDigit(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterDataLatin1.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterDataLatin1.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -25,6 +25,8 @@ package java.lang; +import jdk.internal.HotSpotIntrinsicCandidate; + /** The CharacterData class encapsulates the large tables found in Java.lang.Character. */ @@ -78,6 +80,23 @@ return props; } + @HotSpotIntrinsicCandidate + boolean isDigit(int ch) { + return '0' <= ch && ch <= '9'; + } + + @HotSpotIntrinsicCandidate + boolean isLowerCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.LOWERCASE_LETTER; + } + + @HotSpotIntrinsicCandidate + boolean isUpperCase(int ch) { + int props = getProperties(ch); + return (props & $$maskType) == Character.UPPERCASE_LETTER; + } + boolean isOtherLowercase(int ch) { int props = getPropertiesEx(ch); return (props & $$maskOtherLowercase) != 0; @@ -214,6 +233,7 @@ return retval; } + @HotSpotIntrinsicCandidate boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterDataPrivateUse.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterDataPrivateUse.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,47 +41,59 @@ } boolean isJavaIdentifierStart(int ch) { - return false; + return false; } boolean isJavaIdentifierPart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierStart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierPart(int ch) { - return false; + return false; } boolean isIdentifierIgnorable(int ch) { - return false; + return false; } int toLowerCase(int ch) { - return ch; + return ch; } int toUpperCase(int ch) { - return ch; + return ch; } int toTitleCase(int ch) { - return ch; + return ch; } int digit(int ch, int radix) { - return -1; + return -1; } int getNumericValue(int ch) { - return -1; + return -1; + } + + boolean isDigit(int ch) { + return false; + } + + boolean isLowerCase(int ch) { + return false; + } + + boolean isUpperCase(int ch) { + return false; } boolean isWhitespace(int ch) { - return false; + return false; } byte getDirectionality(int ch) { @@ -91,7 +103,7 @@ } boolean isMirrored(int ch) { - return false; + return false; } static final CharacterData instance = new CharacterDataPrivateUse();
--- a/make/data/characterdata/CharacterDataUndefined.java.template Thu Sep 13 01:49:48 2018 +0200 +++ b/make/data/characterdata/CharacterDataUndefined.java.template Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,59 +35,71 @@ } int getType(int ch) { - return Character.UNASSIGNED; + return Character.UNASSIGNED; } boolean isJavaIdentifierStart(int ch) { - return false; + return false; } boolean isJavaIdentifierPart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierStart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierPart(int ch) { - return false; + return false; } boolean isIdentifierIgnorable(int ch) { - return false; + return false; } int toLowerCase(int ch) { - return ch; + return ch; } int toUpperCase(int ch) { - return ch; + return ch; } int toTitleCase(int ch) { - return ch; + return ch; } int digit(int ch, int radix) { - return -1; + return -1; } int getNumericValue(int ch) { - return -1; + return -1; + } + + boolean isDigit(int ch) { + return false; + } + + boolean isLowerCase(int ch) { + return false; + } + + boolean isUpperCase(int ch) { + return false; } boolean isWhitespace(int ch) { - return false; + return false; } byte getDirectionality(int ch) { - return Character.DIRECTIONALITY_UNDEFINED; + return Character.DIRECTIONALITY_UNDEFINED; } boolean isMirrored(int ch) { - return false; + return false; } static final CharacterData instance = new CharacterDataUndefined();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/data/docs-resources/index.html Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,33 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> +<!-- + Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<html lang="en"> +<head> +<meta http-equiv="refresh" content="0;url=api/index.html"> +<title>Java API Documentation redirect</title> +</head> +<body> +</body> +</html>
--- a/make/jdk/src/classes/build/tools/jigsaw/ModuleSummary.java Thu Sep 13 01:49:48 2018 +0200 +++ b/make/jdk/src/classes/build/tools/jigsaw/ModuleSummary.java Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,13 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -552,6 +554,21 @@ return sb.toString(); } + private String providesEntry(Provides p) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("provides %s<br>\n", p.service())); + List<String> pvs = new ArrayList<>(p.providers()); + pvs.sort(Comparator.naturalOrder()); + for (int i = 0; i < pvs.size(); i++) { // My kingdom for Stream::zip ... + String fmt = ((i == 0) + ? " with %s" + : ",<br> %s"); + sb.append(String.format(fmt, pvs.get(i))); + } + sb.append("\n"); + return sb.toString(); + } + public String servicesColumn() { StringBuilder sb = new StringBuilder(); sb.append(String.format(" <td class=\"%s\">", CODE)); @@ -560,8 +577,7 @@ .forEach(s -> sb.append("uses ").append(s).append("<br>").append("\n")); ms.descriptor().provides().stream() .sorted(Comparator.comparing(Provides::service)) - .map(p -> String.format("provides %s<br> with %s", - p.service(), p.providers())) + .map(this::providesEntry) .forEach(p -> sb.append(p).append("<br>").append("\n")); sb.append("</td>"); return sb.toString();
--- a/make/launcher/LauncherCommon.gmk Thu Sep 13 01:49:48 2018 +0200 +++ b/make/launcher/LauncherCommon.gmk Thu Dec 13 11:47:35 2018 -0800 @@ -207,11 +207,12 @@ $(info Warning: pandoc not found. Not generating man pages) else # Create dynamic man pages from markdown using pandoc. We need - # PANDOC_FILTER, a wrapper around PANDOC_FILTER_JAVASCRIPT. This is - # created by buildtools-jdk. + # PANDOC_TROFF_MANPAGE_FILTER, a wrapper around + # PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. # We should also depend on the source javascript filter - PANDOC_FILTER_JAVASCRIPT := $(TOPDIR)/make/scripts/pandoc-manpage-filter.js + PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT := \ + $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.js # The norm in man pages is to display code literals as bold, but pandoc # "correctly" converts these constructs (encoded in markdown using `...` @@ -234,10 +235,11 @@ DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \ FILES := $(MAN_FILES_MD), \ FORMAT := man, \ - FILTER := $(PANDOC_FILTER), \ + FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \ POST_PROCESS := $(MAN_POST_PROCESS), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ - EXTRA_DEPS := $(PANDOC_FILTER) $(PANDOC_FILTER_JAVASCRIPT), \ + EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \ + $(PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT), \ )) TARGETS += $(BUILD_MAN_PAGES)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-html-manpage-filter.js Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,125 @@ +// +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// + +// +// Traverse a tree of pandoc format objects, calling callback on each +// element, and replacing it if callback returns a new object. +// +// Inspired by the walk method in +// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py +// +function traverse(obj, callback) { + if (Array.isArray(obj)) { + var processed_array = []; + obj.forEach(function(elem) { + if (elem === Object(elem) && elem.t) { + var replacement = callback(elem.t, elem.c || []); + if (!replacement) { + // no replacement object returned, use original + processed_array.push(traverse(elem, callback)); + } else if (Array.isArray(replacement)) { + // array of objects returned, splice all elements into array + replacement.forEach(function(repl_elem) { + processed_array.push(traverse(repl_elem, callback)); + }) + } else { + // replacement object given, traverse it + processed_array.push(traverse(replacement, callback)); + } + } else { + processed_array.push(traverse(elem, callback)); + } + }) + return processed_array; + } else if (obj === Object(obj)) { + if (obj.t) { + var replacement = callback(obj.t, obj.c || []); + if (replacement) { + return replacement; + } + } + var processed_obj = {}; + Object.keys(obj).forEach(function(key) { + processed_obj[key] = traverse(obj[key], callback); + }) + return processed_obj; + } else { + return obj; + } +} + +// +// Helper constructors to create pandoc format objects +// +function Space() { + return { 't': 'Space' }; +} + +function Str(value) { + return { 't': 'Str', 'c': value }; +} + +function MetaInlines(value) { + return { 't': 'MetaInlines', 'c': value }; +} + +function change_title(type, value) { + if (type === 'MetaInlines') { + if (value[0].t === 'Str') { + var match = value[0].c.match(/^([A-Z]+)\([0-9]+\)$/); + if (match) { + return MetaInlines([ + Str("The"), Space(), + Str(match[1].toLowerCase()), + Space(), Str("Command") + ]); + } + } + } +} + +// +// Main function +// +function main() { + var input = ""; + while (line = readLine()) { + input = input.concat(line); + } + + var json = JSON.parse(input); + + var meta = json.meta; + if (meta) { + meta.date = undefined; + var title = meta.title; + if (meta.title) { + meta.title = traverse(meta.title, change_title); + } + } + + print(JSON.stringify(json)); +} + +// ... and execute it +main();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-html-manpage-filter.sh.template Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Simple wrapper script to call Nashorn with the javascript pandoc filter + +@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ + "@@TOPDIR@@/make/scripts/pandoc-html-manpage-filter.js" 2> /dev/null
--- a/make/scripts/pandoc-manpage-filter.js Thu Sep 13 01:49:48 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -// -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -// -// This code is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License version 2 only, as -// published by the Free Software Foundation. -// -// This code is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// version 2 for more details (a copy is included in the LICENSE file that -// accompanied this code). -// -// You should have received a copy of the GNU General Public License version -// 2 along with this work; if not, write to the Free Software Foundation, -// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -// or visit www.oracle.com if you need additional information or have any -// questions. -// - -// -// Traverse a tree of pandoc format objects, calling callback on each -// element, and replacing it if callback returns a new object. -// -// Inspired by the walk method in -// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py -// -function traverse(obj, callback) { - if (Array.isArray(obj)) { - var processed_array = []; - obj.forEach(function(elem) { - if (elem === Object(elem) && elem.t) { - var replacement = callback(elem.t, elem.c || []); - if (!replacement) { - // no replacement object returned, use original - processed_array.push(traverse(elem, callback)); - } else if (Array.isArray(replacement)) { - // array of objects returned, splice all elements into array - replacement.forEach(function(repl_elem) { - processed_array.push(traverse(repl_elem, callback)); - }) - } else { - // replacement object given, traverse it - processed_array.push(traverse(replacement, callback)); - } - } else { - processed_array.push(traverse(elem, callback)); - } - }) - return processed_array; - } else if (obj === Object(obj)) { - var processed_obj = {}; - Object.keys(obj).forEach(function(key) { - processed_obj[key] = traverse(obj[key], callback); - }) - return processed_obj; - } else { - return obj; - } -} - -// -// Helper constructors to create pandoc format objects -// -function Space() { - return { 't': 'Space', 'c': [] }; -} - -function Str(value) { - return { 't': 'Str', 'c': value }; -} - -function Strong(value) { - return { 't': 'Strong', 'c': value }; -} - -function Header(value) { - return { 't': 'Header', 'c': value }; -} - -// -// Callback to change all Str texts to upper case -// -function uppercase(type, value) { - if (type === 'Str') { - return Str(value.toUpperCase()); - } -} - -// -// Main callback function that performs our man page AST rewrites -// -function manpage_filter(type, value) { - // If it is a header, decrease the heading level by one, and - // if it is a level 1 header, convert it to upper case. - if (type === 'Header') { - value[0] = Math.max(1, value[0] - 1); - if (value[0] == 1) { - return Header(traverse(value, uppercase)); - } - } - - // Man pages does not have superscript. We use it for footnotes, so - // enclose in [...] for best representation. - if (type === 'Superscript') { - return [ Str('['), value[0], Str(']') ]; - } - - // If it is a link, put the link name in bold. If it is an external - // link, put it in brackets. Otherwise, it is either an internal link - // (like "#next-heading"), or a relative link to another man page - // (like "java.html"), so remove it for man pages. - if (type === 'Link') { - var target = value[2][0]; - if (target.match(/^http[s]?:/)) { - return [ Strong(value[1]), Space(), Str('[' + target + ']') ]; - } else { - return Strong(value[1]); - } - } -} - -// -// Main function -// -function main() { - var input = ""; - while (line = readLine()) { - input = input.concat(line); - } - var json = JSON.parse(input); - - var transformed_json = traverse(json, manpage_filter); - - print(JSON.stringify(transformed_json)); -} - -// ... and execute it -main();
--- a/make/scripts/pandoc-manpage-filter.sh.template Thu Sep 13 01:49:48 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# Simple wrapper script to call Nashorn with the javascript pandoc filter - -@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ - "@@TOPDIR@@/make/scripts/pandoc-manpage-filter.js" 2> /dev/null
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-troff-manpage-filter.js Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,142 @@ +// +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// + +// +// Traverse a tree of pandoc format objects, calling callback on each +// element, and replacing it if callback returns a new object. +// +// Inspired by the walk method in +// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py +// +function traverse(obj, callback) { + if (Array.isArray(obj)) { + var processed_array = []; + obj.forEach(function(elem) { + if (elem === Object(elem) && elem.t) { + var replacement = callback(elem.t, elem.c || []); + if (!replacement) { + // no replacement object returned, use original + processed_array.push(traverse(elem, callback)); + } else if (Array.isArray(replacement)) { + // array of objects returned, splice all elements into array + replacement.forEach(function(repl_elem) { + processed_array.push(traverse(repl_elem, callback)); + }) + } else { + // replacement object given, traverse it + processed_array.push(traverse(replacement, callback)); + } + } else { + processed_array.push(traverse(elem, callback)); + } + }) + return processed_array; + } else if (obj === Object(obj)) { + var processed_obj = {}; + Object.keys(obj).forEach(function(key) { + processed_obj[key] = traverse(obj[key], callback); + }) + return processed_obj; + } else { + return obj; + } +} + +// +// Helper constructors to create pandoc format objects +// +function Space() { + return { 't': 'Space', 'c': [] }; +} + +function Str(value) { + return { 't': 'Str', 'c': value }; +} + +function Strong(value) { + return { 't': 'Strong', 'c': value }; +} + +function Header(value) { + return { 't': 'Header', 'c': value }; +} + +// +// Callback to change all Str texts to upper case +// +function uppercase(type, value) { + if (type === 'Str') { + return Str(value.toUpperCase()); + } +} + +// +// Main callback function that performs our man page AST rewrites +// +function manpage_filter(type, value) { + // If it is a header, decrease the heading level by one, and + // if it is a level 1 header, convert it to upper case. + if (type === 'Header') { + value[0] = Math.max(1, value[0] - 1); + if (value[0] == 1) { + return Header(traverse(value, uppercase)); + } + } + + // Man pages does not have superscript. We use it for footnotes, so + // enclose in [...] for best representation. + if (type === 'Superscript') { + return [ Str('['), value[0], Str(']') ]; + } + + // If it is a link, put the link name in bold. If it is an external + // link, put it in brackets. Otherwise, it is either an internal link + // (like "#next-heading"), or a relative link to another man page + // (like "java.html"), so remove it for man pages. + if (type === 'Link') { + var target = value[2][0]; + if (target.match(/^http[s]?:/)) { + return [ Strong(value[1]), Space(), Str('[' + target + ']') ]; + } else { + return Strong(value[1]); + } + } +} + +// +// Main function +// +function main() { + var input = ""; + while (line = readLine()) { + input = input.concat(line); + } + var json = JSON.parse(input); + + var transformed_json = traverse(json, manpage_filter); + + print(JSON.stringify(transformed_json)); +} + +// ... and execute it +main();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-troff-manpage-filter.sh.template Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Simple wrapper script to call Nashorn with the javascript pandoc filter + +@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ + "@@TOPDIR@@/make/scripts/pandoc-troff-manpage-filter.js" 2> /dev/null
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -725,8 +725,11 @@ stub_name = "forward_copy_longs"; else stub_name = "backward_copy_longs"; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); - __ align(CodeEntryAlignment); + __ bind(start); Label unaligned_copy_long; @@ -1976,9 +1979,10 @@ const Register dst_pos = c_rarg3; // destination position const Register length = c_rarg4; + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); - __ align(CodeEntryAlignment); address start = __ pc(); __ enter(); // required for proper stackwalking of RuntimeStub frame @@ -3653,7 +3657,6 @@ } address generate_has_negatives(address &has_negatives_long) { - StubCodeMark mark(this, "StubRoutines", "has_negatives"); const u1 large_loop_size = 64; const uint64_t UPPER_BIT_MASK=0x8080808080808080; int dcache_line = VM_Version::dcache_line_size(); @@ -3661,6 +3664,9 @@ Register ary1 = r1, len = r2, result = r0; __ align(CodeEntryAlignment); + + StubCodeMark mark(this, "StubRoutines", "has_negatives"); + address entry = __ pc(); __ enter(); @@ -3900,7 +3906,6 @@ // cnt1 = r10 - amount of elements left to check, reduced by wordSize // r3-r5 are reserved temporary registers address generate_large_array_equals() { - StubCodeMark mark(this, "StubRoutines", "large_array_equals"); Register a1 = r1, a2 = r2, result = r0, cnt1 = r10, tmp1 = rscratch1, tmp2 = rscratch2, tmp3 = r3, tmp4 = r4, tmp5 = r5, tmp6 = r11, tmp7 = r12, tmp8 = r13; @@ -3915,6 +3920,9 @@ tmp5, tmp6, tmp7, tmp8); __ align(CodeEntryAlignment); + + StubCodeMark mark(this, "StubRoutines", "large_array_equals"); + address entry = __ pc(); __ enter(); __ sub(cnt1, cnt1, wordSize); // first 8 bytes were loaded outside of stub
--- a/src/hotspot/cpu/ppc/assembler_ppc.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -299,6 +299,8 @@ CMPI_OPCODE = (11u << OPCODE_SHIFT), CMPL_OPCODE = (31u << OPCODE_SHIFT | 32u << 1), CMPLI_OPCODE = (10u << OPCODE_SHIFT), + CMPRB_OPCODE = (31u << OPCODE_SHIFT | 192u << 1), + CMPEQB_OPCODE = (31u << OPCODE_SHIFT | 224u << 1), ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), @@ -336,6 +338,7 @@ MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), MCRF_OPCODE = (19u << OPCODE_SHIFT | 0u << 1), + SETB_OPCODE = (31u << OPCODE_SHIFT | 128u << 1), // condition register logic instructions CRAND_OPCODE = (19u << OPCODE_SHIFT | 257u << 1), @@ -1076,7 +1079,7 @@ static int frs( int x) { return opp_u_field(x, 10, 6); } static int frt( int x) { return opp_u_field(x, 10, 6); } static int fxm( int x) { return opp_u_field(x, 19, 12); } - static int l10( int x) { return opp_u_field(x, 10, 10); } + static int l10( int x) { assert(x == 0 || x == 1, "must be 0 or 1"); return opp_u_field(x, 10, 10); } static int l14( int x) { return opp_u_field(x, 15, 14); } static int l15( int x) { return opp_u_field(x, 15, 15); } static int l910( int x) { return opp_u_field(x, 10, 9); } @@ -1443,6 +1446,10 @@ inline void cmplw( ConditionRegister crx, Register a, Register b); inline void cmpld( ConditionRegister crx, Register a, Register b); + // >= Power9 + inline void cmprb( ConditionRegister bf, int l, Register a, Register b); + inline void cmpeqb(ConditionRegister bf, Register a, Register b); + inline void isel( Register d, Register a, Register b, int bc); // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value. inline void isel( Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg); @@ -1642,6 +1649,8 @@ inline void mfcr( Register d); inline void mcrf( ConditionRegister crd, ConditionRegister cra); inline void mtcr( Register s); + // >= Power9 + inline void setb( Register d, ConditionRegister cra); // Special purpose registers // Exception Register
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -171,6 +171,8 @@ inline void Assembler::cmp( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMP_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } inline void Assembler::cmpli( ConditionRegister f, int l, Register a, int ui16) { emit_int32( CMPLI_OPCODE | bf(f) | l10(l) | ra(a) | uimm(ui16,16)); } inline void Assembler::cmpl( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPL_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } +inline void Assembler::cmprb( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPRB_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } +inline void Assembler::cmpeqb(ConditionRegister f, Register a, Register b) { emit_int32( CMPEQB_OPCODE| bf(f) | ra(a) | rb(b)); } // extended mnemonics of Compare Instructions inline void Assembler::cmpwi( ConditionRegister crx, Register a, int si16) { Assembler::cmpi( crx, 0, a, si16); } @@ -371,6 +373,8 @@ inline void Assembler::mcrf( ConditionRegister crd, ConditionRegister cra) { emit_int32(MCRF_OPCODE | bf(crd) | bfa(cra)); } inline void Assembler::mtcr( Register s) { Assembler::mtcrf(0xff, s); } +inline void Assembler::setb(Register d, ConditionRegister cra) + { emit_int32(SETB_OPCODE | rt(d) | bfa(cra)); } // Special purpose registers // Exception Register
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -2273,7 +2273,7 @@ ) { // make sure arguments make sense assert_different_registers(obj, var_size_in_bytes, t1); - assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size"); + assert(0 <= con_size_in_bytes && is_simm16(con_size_in_bytes), "illegal object size"); assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); const Register new_top = t1;
--- a/src/hotspot/cpu/ppc/ppc.ad Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/ppc/ppc.ad Thu Dec 13 11:47:35 2018 -0800 @@ -2257,6 +2257,11 @@ return SuperwordUseVSX; case Op_PopCountVI: return (SuperwordUseVSX && UsePopCountInstruction); + case Op_Digit: + case Op_LowerCase: + case Op_UpperCase: + case Op_Whitespace: + return UseCharacterCompareIntrinsics; } return true; // Per default match rules are supported. @@ -12400,6 +12405,132 @@ %} %} +// Compare char +instruct cmprb_Digit_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (Digit src1)); + effect(TEMP src2, TEMP crx); + ins_cost(3 * DEFAULT_COST); + + format %{ "LI $src2, 0x3930\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "SETB $dst, $crx" %} + size(12); + ins_encode %{ + // 0x30: 0, 0x39: 9 + __ li($src2$$Register, 0x3930); + // compare src1 with ranges 0x30 to 0x39 + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_LowerCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (LowerCase src1)); + effect(TEMP src2, TEMP crx); + ins_cost(12 * DEFAULT_COST); + + format %{ "LI $src2, 0x7A61\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xF6DF\n\t" + "ORI $src2, $src2, 0xFFF8\n\t" + "CMPRB $crx, 1, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xAAB5\n\t" + "ORI $src2, $src2, 0xBABA\n\t" + "INSRDI $src2, $src2, 32, 0\n\t" + "CMPEQB $crx, 1, $src1, $src2\n" + "done:\n\t" + "SETB $dst, $crx" %} + + size(48); + ins_encode %{ + Label done; + // 0x61: a, 0x7A: z + __ li($src2$$Register, 0x7A61); + // compare src1 with ranges 0x61 to 0x7A + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xDF: sharp s, 0xFF: y with diaeresis, 0xF7 is not the lower case + __ lis($src2$$Register, (signed short)0xF6DF); + __ ori($src2$$Register, $src2$$Register, 0xFFF8); + // compare src1 with ranges 0xDF to 0xF6 and 0xF8 to 0xFF + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xAA: feminine ordinal indicator + // 0xB5: micro sign + // 0xBA: masculine ordinal indicator + __ lis($src2$$Register, (signed short)0xAAB5); + __ ori($src2$$Register, $src2$$Register, 0xBABA); + __ insrdi($src2$$Register, $src2$$Register, 32, 0); + // compare src1 with 0xAA, 0xB5, and 0xBA + __ cmpeqb($crx$$CondRegister, $src1$$Register, $src2$$Register); + + __ bind(done); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_UpperCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (UpperCase src1)); + effect(TEMP src2, TEMP crx); + ins_cost(7 * DEFAULT_COST); + + format %{ "LI $src2, 0x5A41\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xD6C0\n\t" + "ORI $src2, $src2, 0xDED8\n\t" + "CMPRB $crx, 1, $src1, $src2\n" + "done:\n\t" + "SETB $dst, $crx" %} + + size(28); + ins_encode %{ + Label done; + // 0x41: A, 0x5A: Z + __ li($src2$$Register, 0x5A41); + // compare src1 with a range 0x41 to 0x5A + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xC0: a with grave, 0xDE: thorn, 0xD7 is not the upper case + __ lis($src2$$Register, (signed short)0xD6C0); + __ ori($src2$$Register, $src2$$Register, 0xDED8); + // compare src1 with ranges 0xC0 to 0xD6 and 0xD8 to 0xDE + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + + __ bind(done); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_Whitespace_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (Whitespace src1)); + effect(TEMP src2, TEMP crx); + ins_cost(4 * DEFAULT_COST); + + format %{ "LI $src2, 0x0D09\n\t" + "ADDIS $src2, 0x201C\n\t" + "CMPRB $crx, 1, $src1, $src2\n\t" + "SETB $dst, $crx" %} + size(16); + ins_encode %{ + // 0x09 to 0x0D, 0x1C to 0x20 + __ li($src2$$Register, 0x0D09); + __ addis($src2$$Register, $src2$$Register, 0x0201C); + // compare src with ranges 0x09 to 0x0D and 0x1C to 0x20 + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + //----------Branches--------------------------------------------------------- // Jump
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -134,11 +134,18 @@ if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionsPPC64)) { FLAG_SET_ERGO(bool, UseCountTrailingZerosInstructionsPPC64, true); } + if (FLAG_IS_DEFAULT(UseCharacterCompareIntrinsics)) { + FLAG_SET_ERGO(bool, UseCharacterCompareIntrinsics, true); + } } else { if (UseCountTrailingZerosInstructionsPPC64) { warning("UseCountTrailingZerosInstructionsPPC64 specified, but needs at least Power9."); FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionsPPC64, false); } + if (UseCharacterCompareIntrinsics) { + warning("UseCharacterCompareIntrinsics specified, but needs at least Power9."); + FLAG_SET_DEFAULT(UseCharacterCompareIntrinsics, false); + } } #endif
--- a/src/hotspot/cpu/x86/assembler_x86.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/assembler_x86.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -3966,6 +3966,34 @@ emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::pmaddwd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xF5); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpmaddwd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + (vector_len == AVX_256bit ? VM_Version::supports_avx2() : + (vector_len == AVX_512bit ? VM_Version::supports_evex() : 0)), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, nds, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xF5); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::evpdpwssd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_evex(), ""); + assert(VM_Version::supports_vnni(), "must support vnni"); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x52); + emit_int8((unsigned char)(0xC0 | encode)); +} + // generic void Assembler::pop(Register dst) { int encode = prefix_and_encode(dst->encoding()); @@ -4178,6 +4206,17 @@ emit_int8(shift); } +void Assembler::vpsrldq(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_avx512bw() : 0, ""); + InstructionAttr attributes(vector_len, /*vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(xmm3->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8(0x73); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(shift & 0xFF); +} + void Assembler::pslldq(XMMRegister dst, int shift) { // Shift left 128 bit value in dst XMMRegister by shift number of bytes. NOT_LP64(assert(VM_Version::supports_sse2(), "")); @@ -4189,6 +4228,17 @@ emit_int8(shift); } +void Assembler::vpslldq(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + vector_len == AVX_256bit ? VM_Version::supports_avx2() : + vector_len == AVX_512bit ? VM_Version::supports_avx512bw() : 0, ""); + InstructionAttr attributes(vector_len, /*vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(xmm7->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8(0x73); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(shift & 0xFF); +} + void Assembler::ptest(XMMRegister dst, Address src) { assert(VM_Version::supports_sse4_1(), ""); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); @@ -4200,7 +4250,7 @@ } void Assembler::ptest(XMMRegister dst, XMMRegister src) { - assert(VM_Version::supports_sse4_1(), ""); + assert(VM_Version::supports_sse4_1() || VM_Version::supports_avx(), ""); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8(0x17);
--- a/src/hotspot/cpu/x86/assembler_x86.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/assembler_x86.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1668,6 +1668,12 @@ void evpmovdb(Address dst, XMMRegister src, int vector_len); + // Multiply add + void pmaddwd(XMMRegister dst, XMMRegister src); + void vpmaddwd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + // Multiply add accumulate + void evpdpwssd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + #ifndef _LP64 // no 32bit push/pop on amd64 void popl(Address dst); #endif @@ -2055,6 +2061,7 @@ void vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); void vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); void vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); + void vpslldq(XMMRegister dst, XMMRegister src, int shift, int vector_len); // Logical shift right packed integers void psrlw(XMMRegister dst, int shift); @@ -2069,6 +2076,7 @@ void vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); void vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); void vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); + void vpsrldq(XMMRegister dst, XMMRegister src, int shift, int vector_len); void evpsrlvw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void evpsllvw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -943,12 +943,17 @@ int iter); void addm(int disp, Register r1, Register r2); - + void gfmul(XMMRegister tmp0, XMMRegister t); + void schoolbookAAD(int i, Register subkeyH, XMMRegister data, XMMRegister tmp0, + XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3); + void generateHtbl_one_block(Register htbl); + void generateHtbl_eight_blocks(Register htbl); public: void sha256_AVX2(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block, XMMRegister shuf_mask); + void avx_ghash(Register state, Register htbl, Register data, Register blocks); #endif #ifdef _LP64 @@ -1498,6 +1503,15 @@ // 0x11 - multiply upper 64 bits [64:127] Assembler::vpclmulqdq(dst, nds, src, 0x11); } + void vpclmullqhqdq(XMMRegister dst, XMMRegister nds, XMMRegister src) { + // 0x10 - multiply nds[0:63] and src[64:127] + Assembler::vpclmulqdq(dst, nds, src, 0x10); + } + void vpclmulhqlqdq(XMMRegister dst, XMMRegister nds, XMMRegister src) { + //0x01 - multiply nds[64:127] and src[0:63] + Assembler::vpclmulqdq(dst, nds, src, 0x01); + } + void evpclmulldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { // 0x00 - multiply lower 64 bits [0:63] Assembler::evpclmulqdq(dst, nds, src, 0x00, vector_len);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,322 @@ +/* +* Copyright (c) 2018, Intel Corporation. +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +* +*/ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "macroAssembler_x86.hpp" + +// Multiply 128 x 128 bits, using 4 pclmulqdq operations +void MacroAssembler::schoolbookAAD(int i, Register htbl, XMMRegister data, + XMMRegister tmp0, XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3) { + movdqu(xmm15, Address(htbl, i * 16)); + vpclmulhqlqdq(tmp3, data, xmm15); // 0x01 + vpxor(tmp2, tmp2, tmp3, Assembler::AVX_128bit); + vpclmulldq(tmp3, data, xmm15); // 0x00 + vpxor(tmp0, tmp0, tmp3, Assembler::AVX_128bit); + vpclmulhdq(tmp3, data, xmm15); // 0x11 + vpxor(tmp1, tmp1, tmp3, Assembler::AVX_128bit); + vpclmullqhqdq(tmp3, data, xmm15); // 0x10 + vpxor(tmp2, tmp2, tmp3, Assembler::AVX_128bit); +} + +// Multiply two 128 bit numbers resulting in a 256 bit value +// Result of the multiplication followed by reduction stored in state +void MacroAssembler::gfmul(XMMRegister tmp0, XMMRegister state) { + const XMMRegister tmp1 = xmm4; + const XMMRegister tmp2 = xmm5; + const XMMRegister tmp3 = xmm6; + const XMMRegister tmp4 = xmm7; + + vpclmulldq(tmp1, state, tmp0); //0x00 (a0 * b0) + vpclmulhdq(tmp4, state, tmp0);//0x11 (a1 * b1) + vpclmullqhqdq(tmp2, state, tmp0);//0x10 (a1 * b0) + vpclmulhqlqdq(tmp3, state, tmp0); //0x01 (a0 * b1) + + vpxor(tmp2, tmp2, tmp3, Assembler::AVX_128bit); // (a0 * b1) + (a1 * b0) + + vpslldq(tmp3, tmp2, 8, Assembler::AVX_128bit); + vpsrldq(tmp2, tmp2, 8, Assembler::AVX_128bit); + vpxor(tmp1, tmp1, tmp3, Assembler::AVX_128bit); // tmp1 and tmp4 hold the result + vpxor(tmp4, tmp4, tmp2, Assembler::AVX_128bit); // of carryless multiplication + // Follows the reduction technique mentioned in + // Shift-XOR reduction described in Gueron-Kounavis May 2010 + // First phase of reduction + // + vpslld(xmm8, tmp1, 31, Assembler::AVX_128bit); // packed right shift shifting << 31 + vpslld(xmm9, tmp1, 30, Assembler::AVX_128bit); // packed right shift shifting << 30 + vpslld(xmm10, tmp1, 25, Assembler::AVX_128bit);// packed right shift shifting << 25 + // xor the shifted versions + vpxor(xmm8, xmm8, xmm9, Assembler::AVX_128bit); + vpxor(xmm8, xmm8, xmm10, Assembler::AVX_128bit); + vpslldq(xmm9, xmm8, 12, Assembler::AVX_128bit); + vpsrldq(xmm8, xmm8, 4, Assembler::AVX_128bit); + vpxor(tmp1, tmp1, xmm9, Assembler::AVX_128bit);// first phase of the reduction complete + // + // Second phase of the reduction + // + vpsrld(xmm9, tmp1, 1, Assembler::AVX_128bit);// packed left shifting >> 1 + vpsrld(xmm10, tmp1, 2, Assembler::AVX_128bit);// packed left shifting >> 2 + vpsrld(xmm11, tmp1, 7, Assembler::AVX_128bit);// packed left shifting >> 7 + vpxor(xmm9, xmm9, xmm10, Assembler::AVX_128bit);// xor the shifted versions + vpxor(xmm9, xmm9, xmm11, Assembler::AVX_128bit); + vpxor(xmm9, xmm9, xmm8, Assembler::AVX_128bit); + vpxor(tmp1, tmp1, xmm9, Assembler::AVX_128bit); + vpxor(state, tmp4, tmp1, Assembler::AVX_128bit);// the result is in state + ret(0); +} + +// This method takes the subkey after expansion as input and generates 1 * 16 power of subkey H. +// The power of H is used in reduction process for one block ghash +void MacroAssembler::generateHtbl_one_block(Register htbl) { + const XMMRegister t = xmm13; + + // load the original subkey hash + movdqu(t, Address(htbl, 0)); + // shuffle using long swap mask + movdqu(xmm10, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr())); + vpshufb(t, t, xmm10, Assembler::AVX_128bit); + + // Compute H' = GFMUL(H, 2) + vpsrld(xmm3, t, 7, Assembler::AVX_128bit); + movdqu(xmm4, ExternalAddress(StubRoutines::x86::ghash_shufflemask_addr())); + vpshufb(xmm3, xmm3, xmm4, Assembler::AVX_128bit); + movl(rax, 0xff00); + movdl(xmm4, rax); + vpshufb(xmm4, xmm4, xmm3, Assembler::AVX_128bit); + movdqu(xmm5, ExternalAddress(StubRoutines::x86::ghash_polynomial_addr())); + vpand(xmm5, xmm5, xmm4, Assembler::AVX_128bit); + vpsrld(xmm3, t, 31, Assembler::AVX_128bit); + vpslld(xmm4, t, 1, Assembler::AVX_128bit); + vpslldq(xmm3, xmm3, 4, Assembler::AVX_128bit); + vpxor(t, xmm4, xmm3, Assembler::AVX_128bit);// t holds p(x) <<1 or H * 2 + + //Adding p(x)<<1 to xmm5 which holds the reduction polynomial + vpxor(t, t, xmm5, Assembler::AVX_128bit); + movdqu(Address(htbl, 1 * 16), t); // H * 2 + + ret(0); +} + +// This method takes the subkey after expansion as input and generates the remaining powers of subkey H. +// The power of H is used in reduction process for eight block ghash +void MacroAssembler::generateHtbl_eight_blocks(Register htbl) { + const XMMRegister t = xmm13; + const XMMRegister tmp0 = xmm1; + Label GFMUL; + + movdqu(t, Address(htbl, 1 * 16)); + movdqu(tmp0, t); + + // tmp0 and t hold H. Now we compute powers of H by using GFMUL(H, H) + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 2 * 16), t); //H ^ 2 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 3 * 16), t); //H ^ 3 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 4 * 16), t); //H ^ 4 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 5 * 16), t); //H ^ 5 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 6 * 16), t); //H ^ 6 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 7 * 16), t); //H ^ 7 * 2 + call(GFMUL, relocInfo::none); + movdqu(Address(htbl, 8 * 16), t); //H ^ 8 * 2 + ret(0); + + bind(GFMUL); + gfmul(tmp0, t); +} + +// Multiblock and single block GHASH computation using Shift XOR reduction technique +void MacroAssembler::avx_ghash(Register input_state, Register htbl, + Register input_data, Register blocks) { + + // temporary variables to hold input data and input state + const XMMRegister data = xmm1; + const XMMRegister state = xmm0; + // temporary variables to hold intermediate results + const XMMRegister tmp0 = xmm3; + const XMMRegister tmp1 = xmm4; + const XMMRegister tmp2 = xmm5; + const XMMRegister tmp3 = xmm6; + // temporary variables to hold byte and long swap masks + const XMMRegister bswap_mask = xmm2; + const XMMRegister lswap_mask = xmm14; + + Label GENERATE_HTBL_1_BLK, GENERATE_HTBL_8_BLKS, BEGIN_PROCESS, GFMUL, BLOCK8_REDUCTION, + ONE_BLK_INIT, PROCESS_1_BLOCK, PROCESS_8_BLOCKS, SAVE_STATE, EXIT_GHASH; + + testptr(blocks, blocks); + jcc(Assembler::zero, EXIT_GHASH); + + // Check if Hashtable (1*16) has been already generated + // For anything less than 8 blocks, we generate only the first power of H. + movdqu(tmp2, Address(htbl, 1 * 16)); + ptest(tmp2, tmp2); + jcc(Assembler::notZero, BEGIN_PROCESS); + call(GENERATE_HTBL_1_BLK, relocInfo::none); + + // Shuffle the input state + bind(BEGIN_PROCESS); + movdqu(lswap_mask, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr())); + movdqu(state, Address(input_state, 0)); + vpshufb(state, state, lswap_mask, Assembler::AVX_128bit); + + cmpl(blocks, 8); + jcc(Assembler::below, ONE_BLK_INIT); + // If we have 8 blocks or more data, then generate remaining powers of H + movdqu(tmp2, Address(htbl, 8 * 16)); + ptest(tmp2, tmp2); + jcc(Assembler::notZero, PROCESS_8_BLOCKS); + call(GENERATE_HTBL_8_BLKS, relocInfo::none); + + //Do 8 multiplies followed by a reduction processing 8 blocks of data at a time + //Each block = 16 bytes. + bind(PROCESS_8_BLOCKS); + subl(blocks, 8); + movdqu(bswap_mask, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr())); + movdqu(data, Address(input_data, 16 * 7)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + //Loading 1*16 as calculated powers of H required starts at that location. + movdqu(xmm15, Address(htbl, 1 * 16)); + //Perform carryless multiplication of (H*2, data block #7) + vpclmulhqlqdq(tmp2, data, xmm15);//a0 * b1 + vpclmulldq(tmp0, data, xmm15);//a0 * b0 + vpclmulhdq(tmp1, data, xmm15);//a1 * b1 + vpclmullqhqdq(tmp3, data, xmm15);//a1* b0 + vpxor(tmp2, tmp2, tmp3, Assembler::AVX_128bit);// (a0 * b1) + (a1 * b0) + + movdqu(data, Address(input_data, 16 * 6)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^2 * 2, data block #6) + schoolbookAAD(2, htbl, data, tmp0, tmp1, tmp2, tmp3); + + movdqu(data, Address(input_data, 16 * 5)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^3 * 2, data block #5) + schoolbookAAD(3, htbl, data, tmp0, tmp1, tmp2, tmp3); + movdqu(data, Address(input_data, 16 * 4)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^4 * 2, data block #4) + schoolbookAAD(4, htbl, data, tmp0, tmp1, tmp2, tmp3); + movdqu(data, Address(input_data, 16 * 3)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^5 * 2, data block #3) + schoolbookAAD(5, htbl, data, tmp0, tmp1, tmp2, tmp3); + movdqu(data, Address(input_data, 16 * 2)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^6 * 2, data block #2) + schoolbookAAD(6, htbl, data, tmp0, tmp1, tmp2, tmp3); + movdqu(data, Address(input_data, 16 * 1)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^7 * 2, data block #1) + schoolbookAAD(7, htbl, data, tmp0, tmp1, tmp2, tmp3); + movdqu(data, Address(input_data, 16 * 0)); + // xor data block#0 with input state before perfoming carry-less multiplication + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + vpxor(data, data, state, Assembler::AVX_128bit); + // Perform carryless multiplication of (H^8 * 2, data block #0) + schoolbookAAD(8, htbl, data, tmp0, tmp1, tmp2, tmp3); + vpslldq(tmp3, tmp2, 8, Assembler::AVX_128bit); + vpsrldq(tmp2, tmp2, 8, Assembler::AVX_128bit); + vpxor(tmp0, tmp0, tmp3, Assembler::AVX_128bit);// tmp0, tmp1 contains aggregated results of + vpxor(tmp1, tmp1, tmp2, Assembler::AVX_128bit);// the multiplication operation + + // we have the 2 128-bit partially accumulated multiplication results in tmp0:tmp1 + // with higher 128-bit in tmp1 and lower 128-bit in corresponding tmp0 + // Follows the reduction technique mentioned in + // Shift-XOR reduction described in Gueron-Kounavis May 2010 + bind(BLOCK8_REDUCTION); + // First Phase of the reduction + vpslld(xmm8, tmp0, 31, Assembler::AVX_128bit); // packed right shifting << 31 + vpslld(xmm9, tmp0, 30, Assembler::AVX_128bit); // packed right shifting << 30 + vpslld(xmm10, tmp0, 25, Assembler::AVX_128bit); // packed right shifting << 25 + // xor the shifted versions + vpxor(xmm8, xmm8, xmm10, Assembler::AVX_128bit); + vpxor(xmm8, xmm8, xmm9, Assembler::AVX_128bit); + + vpslldq(xmm9, xmm8, 12, Assembler::AVX_128bit); + vpsrldq(xmm8, xmm8, 4, Assembler::AVX_128bit); + + vpxor(tmp0, tmp0, xmm9, Assembler::AVX_128bit); // first phase of reduction is complete + // second phase of the reduction + vpsrld(xmm9, tmp0, 1, Assembler::AVX_128bit); // packed left shifting >> 1 + vpsrld(xmm10, tmp0, 2, Assembler::AVX_128bit); // packed left shifting >> 2 + vpsrld(tmp2, tmp0, 7, Assembler::AVX_128bit); // packed left shifting >> 7 + // xor the shifted versions + vpxor(xmm9, xmm9, xmm10, Assembler::AVX_128bit); + vpxor(xmm9, xmm9, tmp2, Assembler::AVX_128bit); + vpxor(xmm9, xmm9, xmm8, Assembler::AVX_128bit); + vpxor(tmp0, xmm9, tmp0, Assembler::AVX_128bit); + // Final result is in state + vpxor(state, tmp0, tmp1, Assembler::AVX_128bit); + + lea(input_data, Address(input_data, 16 * 8)); + cmpl(blocks, 8); + jcc(Assembler::below, ONE_BLK_INIT); + jmp(PROCESS_8_BLOCKS); + + // Since this is one block operation we will only use H * 2 i.e. the first power of H + bind(ONE_BLK_INIT); + movdqu(tmp0, Address(htbl, 1 * 16)); + movdqu(bswap_mask, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr())); + + //Do one (128 bit x 128 bit) carry-less multiplication at a time followed by a reduction. + bind(PROCESS_1_BLOCK); + cmpl(blocks, 0); + jcc(Assembler::equal, SAVE_STATE); + subl(blocks, 1); + movdqu(data, Address(input_data, 0)); + vpshufb(data, data, bswap_mask, Assembler::AVX_128bit); + vpxor(state, state, data, Assembler::AVX_128bit); + // gfmul(H*2, state) + call(GFMUL, relocInfo::none); + addptr(input_data, 16); + jmp(PROCESS_1_BLOCK); + + bind(SAVE_STATE); + vpshufb(state, state, lswap_mask, Assembler::AVX_128bit); + movdqu(Address(input_state, 0), state); + jmp(EXIT_GHASH); + + bind(GFMUL); + gfmul(tmp0, state); + + bind(GENERATE_HTBL_1_BLK); + generateHtbl_one_block(htbl); + + bind(GENERATE_HTBL_8_BLKS); + generateHtbl_eight_blocks(htbl); + + bind(EXIT_GHASH); + // zero out xmm registers used for Htbl storage + vpxor(xmm0, xmm0, xmm0, Assembler::AVX_128bit); + vpxor(xmm1, xmm1, xmm1, Assembler::AVX_128bit); + vpxor(xmm3, xmm3, xmm3, Assembler::AVX_128bit); + vpxor(xmm15, xmm15, xmm15, Assembler::AVX_128bit); +} \ No newline at end of file
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -4388,6 +4388,45 @@ return start; } +// Polynomial x^128+x^127+x^126+x^121+1 +address ghash_polynomial_addr() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "_ghash_poly_addr"); + address start = __ pc(); + __ emit_data64(0x0000000000000001, relocInfo::none); + __ emit_data64(0xc200000000000000, relocInfo::none); + return start; +} + +address ghash_shufflemask_addr() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "_ghash_shuffmask_addr"); + address start = __ pc(); + __ emit_data64(0x0f0f0f0f0f0f0f0f, relocInfo::none); + __ emit_data64(0x0f0f0f0f0f0f0f0f, relocInfo::none); + return start; +} + +// Ghash single and multi block operations using AVX instructions +address generate_avx_ghash_processBlocks() { + __ align(CodeEntryAlignment); + + StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks"); + address start = __ pc(); + + // arguments + const Register state = c_rarg0; + const Register htbl = c_rarg1; + const Register data = c_rarg2; + const Register blocks = c_rarg3; + __ enter(); + // Save state before entering routine + __ avx_ghash(state, htbl, data, blocks); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + return start; +} + // byte swap x86 long address generate_ghash_long_swap_mask() { __ align(CodeEntryAlignment); @@ -5886,9 +5925,15 @@ // Generate GHASH intrinsics code if (UseGHASHIntrinsics) { - StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); - StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask(); - StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks(); + StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); + StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask(); + if (VM_Version::supports_avx()) { + StubRoutines::x86::_ghash_shuffmask_addr = ghash_shufflemask_addr(); + StubRoutines::x86::_ghash_poly_addr = ghash_polynomial_addr(); + StubRoutines::_ghash_processBlocks = generate_avx_ghash_processBlocks(); + } else { + StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks(); + } } if (UseBASE64Intrinsics) {
--- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -38,6 +38,8 @@ address StubRoutines::x86::_counter_shuffle_mask_addr = NULL; address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL; address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL; +address StubRoutines::x86::_ghash_poly_addr = NULL; +address StubRoutines::x86::_ghash_shuffmask_addr = NULL; address StubRoutines::x86::_upper_word_mask_addr = NULL; address StubRoutines::x86::_shuffle_byte_flip_mask_addr = NULL; address StubRoutines::x86::_k256_adr = NULL;
--- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -128,6 +128,8 @@ // swap mask for ghash static address _ghash_long_swap_mask_addr; static address _ghash_byte_swap_mask_addr; + static address _ghash_poly_addr; + static address _ghash_shuffmask_addr; // upper word mask for sha1 static address _upper_word_mask_addr; @@ -205,6 +207,8 @@ static address crc_by128_masks_addr() { return (address)_crc_by128_masks; } static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; } static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; } + static address ghash_shufflemask_addr() { return _ghash_shuffmask_addr; } + static address ghash_polynomial_addr() { return _ghash_poly_addr; } static address upper_word_mask_addr() { return _upper_word_mask_addr; } static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; } static address k256_addr() { return _k256_adr; }
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -1289,7 +1289,7 @@ if (FLAG_IS_DEFAULT(UseXMMForArrayCopy)) { UseXMMForArrayCopy = true; // use SSE2 movq on new Intel cpus } - if (supports_sse4_2() && supports_ht()) { // Newest Intel cpus + if ((supports_sse4_2() && supports_ht()) || supports_avx()) { // Newest Intel cpus if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus }
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -336,6 +336,7 @@ #define CPU_AVX512_VPOPCNTDQ ((uint64_t)UCONST64(0x2000000000)) // Vector popcount #define CPU_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication #define CPU_VAES ((uint64_t)UCONST64(0x8000000000)) // Vector AES instructions +#define CPU_VNNI ((uint64_t)UCONST64(0x16000000000)) // Vector Neural Network Instructions enum Extended_Family { // AMD @@ -548,6 +549,8 @@ result |= CPU_VPCLMULQDQ; if (_cpuid_info.sef_cpuid7_ecx.bits.vaes != 0) result |= CPU_VAES; + if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vnni != 0) + result |= CPU_VNNI; } } if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0) @@ -828,6 +831,7 @@ static bool supports_vpopcntdq() { return (_features & CPU_AVX512_VPOPCNTDQ) != 0; } static bool supports_vpclmulqdq() { return (_features & CPU_VPCLMULQDQ) != 0; } static bool supports_vaes() { return (_features & CPU_VAES) != 0; } + static bool supports_vnni() { return (_features & CPU_VNNI) != 0; } // Intel features static bool is_intel_family_core() { return is_intel() &&
--- a/src/hotspot/cpu/x86/x86.ad Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/x86.ad Thu Dec 13 11:47:35 2018 -0800 @@ -1446,6 +1446,10 @@ if (VM_Version::supports_on_spin_wait() == false) ret_value = false; break; + case Op_MulAddVS2VI: + if (UseSSE < 2) + ret_value = false; + break; } return ret_value; // Per default match rules are supported. @@ -9855,6 +9859,118 @@ ins_pipe( pipe_slow ); %} +// --------------------------------- Vector Multiply Add -------------------------------------- + +instruct smuladd4S2I_reg(vecD dst, vecD src1) %{ + predicate(UseSSE >= 2 && UseAVX == 0 && n->as_Vector()->length() == 2); + match(Set dst (MulAddVS2VI dst src1)); + format %{ "pmaddwd $dst,$dst,$src1\t! muladd packed4Sto2I" %} + ins_encode %{ + __ pmaddwd($dst$$XMMRegister, $src1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulAddVS2VI src1 src2)); + format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed4Sto2I" %} + ins_encode %{ + int vector_len = 0; + __ vpmaddwd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct smuladd8S4I_reg(vecX dst, vecX src1) %{ + predicate(UseSSE >= 2 && UseAVX == 0 && n->as_Vector()->length() == 4); + match(Set dst (MulAddVS2VI dst src1)); + format %{ "pmaddwd $dst,$dst,$src1\t! muladd packed8Sto4I" %} + ins_encode %{ + __ pmaddwd($dst$$XMMRegister, $src1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulAddVS2VI src1 src2)); + format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed8Sto4I" %} + ins_encode %{ + int vector_len = 0; + __ vpmaddwd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (MulAddVS2VI src1 src2)); + format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed16Sto8I" %} + ins_encode %{ + int vector_len = 1; + __ vpmaddwd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (MulAddVS2VI src1 src2)); + format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed32Sto16I" %} + ins_encode %{ + int vector_len = 2; + __ vpmaddwd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- Vector Multiply Add Add ---------------------------------- + +instruct vmuladdadd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 2); + match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); + format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed4Sto2I" %} + ins_encode %{ + int vector_len = 0; + __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladdadd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 4); + match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); + format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed8Sto4I" %} + ins_encode %{ + int vector_len = 0; + __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladdadd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); + format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed16Sto8I" %} + ins_encode %{ + int vector_len = 1; + __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmuladdadd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ + predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); + format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed32Sto16I" %} + ins_encode %{ + int vector_len = 2; + __ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + // --------------------------------- PopCount -------------------------------------- instruct vpopcount2I(vecD dst, vecD src) %{
--- a/src/hotspot/cpu/x86/x86_32.ad Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/x86_32.ad Thu Dec 13 11:47:35 2018 -0800 @@ -7755,6 +7755,16 @@ ins_pipe( ialu_reg_mem_alu0 ); %} +instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, eFlagsReg cr) +%{ + match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3))); + effect(KILL cr, KILL src2); + + expand %{ mulI_rReg(dst, src1, cr); + mulI_rReg(src2, src3, cr); + addI_rReg(dst, src2, cr); %} +%} + // Multiply Register Int to Long instruct mulI2L(eADXRegL dst, eAXRegI src, nadxRegI src1, eFlagsReg flags) %{ // Basic Idea: long = (long)int * (long)int
--- a/src/hotspot/cpu/x86/x86_64.ad Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/cpu/x86/x86_64.ad Thu Dec 13 11:47:35 2018 -0800 @@ -8175,6 +8175,16 @@ ins_pipe(ialu_reg_mem_alu0); %} +instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg cr) +%{ + match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3))); + effect(KILL cr, KILL src2); + + expand %{ mulI_rReg(dst, src1, cr); + mulI_rReg(src2, src3, cr); + addI_rReg(dst, src2, cr); %} +%} + instruct mulL_rReg(rRegL dst, rRegL src, rFlagsReg cr) %{ match(Set dst (MulL dst src));
--- a/src/hotspot/os/linux/globals_linux.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/os/linux/globals_linux.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -67,6 +67,11 @@ " of quotas (if set), when true. Otherwise, use the CPU" \ " shares value, provided it is less than quota.") \ \ + diagnostic(bool, DumpPrivateMappingsInCore, true, \ + "If true, sets bit 2 of /proc/PID/coredump_filter, thus " \ + "resulting in file-backed private mappings of the process to "\ + "be dumped into the corefile, if UseSharedSpaces is true.") \ + \ diagnostic(bool, UseCpuAllocPath, false, \ "Use CPU_ALLOC code path in os::active_processor_count ")
--- a/src/hotspot/os/linux/os_linux.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/os/linux/os_linux.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -128,8 +128,12 @@ // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) -#define LARGEPAGES_BIT (1 << 6) -#define DAX_SHARED_BIT (1 << 8) +enum CoredumpFilterBit { + FILE_BACKED_PVT_BIT = 1 << 2, + LARGEPAGES_BIT = 1 << 6, + DAX_SHARED_BIT = 1 << 8 +}; + //////////////////////////////////////////////////////////////////////////////// // global variables julong os::Linux::_physical_memory = 0; @@ -1350,6 +1354,9 @@ void os::abort(bool dump_core, void* siginfo, const void* context) { os::shutdown(); if (dump_core) { + if (UseSharedSpaces && DumpPrivateMappingsInCore) { + ClassLoader::close_jrt_image(); + } #ifndef PRODUCT fdStream out(defaultStream::output_fd()); out.print_raw("Current thread is "); @@ -3401,10 +3408,9 @@ // - (bit 7) dax private memory // - (bit 8) dax shared memory // -static void set_coredump_filter(bool largepages, bool dax_shared) { +static void set_coredump_filter(CoredumpFilterBit bit) { FILE *f; long cdm; - bool filter_changed = false; if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { return; @@ -3415,17 +3421,11 @@ return; } + long saved_cdm = cdm; rewind(f); - - if (largepages && (cdm & LARGEPAGES_BIT) == 0) { - cdm |= LARGEPAGES_BIT; - filter_changed = true; - } - if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) { - cdm |= DAX_SHARED_BIT; - filter_changed = true; - } - if (filter_changed) { + cdm |= bit; + + if (cdm != saved_cdm) { fprintf(f, "%#lx", cdm); } @@ -3564,7 +3564,7 @@ size_t large_page_size = Linux::setup_large_page_size(); UseLargePages = Linux::setup_large_page_type(large_page_size); - set_coredump_filter(true /*largepages*/, false /*dax_shared*/); + set_coredump_filter(LARGEPAGES_BIT); } #ifndef SHM_HUGETLB @@ -5072,8 +5072,13 @@ prio_init(); if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { - set_coredump_filter(false /*largepages*/, true /*dax_shared*/); - } + set_coredump_filter(DAX_SHARED_BIT); + } + + if (UseSharedSpaces && DumpPrivateMappingsInCore) { + set_coredump_filter(FILE_BACKED_PVT_BIT); + } + return JNI_OK; }
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -74,15 +74,17 @@ // * 63-47 Fixed (17-bits, always zero) // -const size_t ZPlatformPageSizeSmallShift = 21; // 2M +const size_t ZPlatformPageSizeSmallShift = 21; // 2M -const size_t ZPlatformAddressOffsetBits = 42; // 4TB +const size_t ZPlatformAddressOffsetBits = 42; // 4TB -const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits; +const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits; -const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits; -const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4; +const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits; +const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4; -const size_t ZPlatformCacheLineSize = 64; +const size_t ZPlatformNMethodDisarmedOffset = 4; + +const size_t ZPlatformCacheLineSize = 64; #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP
--- a/src/hotspot/share/adlc/formssel.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/adlc/formssel.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -4181,6 +4181,7 @@ "AddReductionVF", "AddReductionVD", "MulReductionVI", "MulReductionVL", "MulReductionVF", "MulReductionVD", + "MulAddVS2VI", "LShiftCntV","RShiftCntV", "LShiftVB","LShiftVS","LShiftVI","LShiftVL", "RShiftVB","RShiftVS","RShiftVI","RShiftVL",
--- a/src/hotspot/share/classfile/classFileParser.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/classFileParser.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -5703,7 +5703,8 @@ ik->major_version() != JAVA_MIN_SUPPORTED_VERSION && log_is_enabled(Info, class, preview)) { ResourceMark rm; - log_info(class, preview)("Loading preview feature type %s", ik->external_name()); + log_info(class, preview)("Loading class %s that depends on preview features (class file version %d.65535)", + ik->external_name(), ik->major_version()); } if (log_is_enabled(Debug, class, resolve)) {
--- a/src/hotspot/share/classfile/classLoader.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/classLoader.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -363,6 +363,13 @@ } } +void ClassPathImageEntry::close_jimage() { + if (_jimage != NULL) { + (*JImageClose)(_jimage); + _jimage = NULL; + } +} + ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) : ClassPathEntry(), _jimage(jimage) { @@ -614,6 +621,12 @@ void ClassLoader::setup_module_search_path(const char* path, TRAPS) { update_module_path_entry_list(path, THREAD); } + +void ClassLoader::close_jrt_image() { + assert(ClassLoader::has_jrt_entry(), "Not applicable for exploded builds"); + _jrt_entry->close_jimage(); +} + #endif // INCLUDE_CDS // Construct the array of module/path pairs as specified to --patch-module
--- a/src/hotspot/share/classfile/classLoader.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/classLoader.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -55,6 +55,7 @@ virtual bool is_jar_file() const = 0; virtual const char* name() const = 0; virtual JImageFile* jimage() const = 0; + virtual void close_jimage() = 0; // Constructor ClassPathEntry() : _next(NULL) {} // Attempt to locate file_name through this class path entry. @@ -70,6 +71,7 @@ bool is_jar_file() const { return false; } const char* name() const { return _dir; } JImageFile* jimage() const { return NULL; } + void close_jimage() {} ClassPathDirEntry(const char* dir); virtual ~ClassPathDirEntry() {} ClassFileStream* open_stream(const char* name, TRAPS); @@ -98,6 +100,7 @@ bool is_jar_file() const { return true; } const char* name() const { return _zip_name; } JImageFile* jimage() const { return NULL; } + void close_jimage() {} ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append); virtual ~ClassPathZipEntry(); u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); @@ -117,6 +120,7 @@ bool is_open() const { return _jimage != NULL; } const char* name() const { return _name == NULL ? "" : _name; } JImageFile* jimage() const { return _jimage; } + void close_jimage(); ClassPathImageEntry(JImageFile* jimage, const char* name); virtual ~ClassPathImageEntry(); ClassFileStream* open_stream(const char* name, TRAPS); @@ -333,6 +337,7 @@ // Modular java runtime image is present vs. a build with exploded modules static bool has_jrt_entry() { return (_jrt_entry != NULL); } static ClassPathEntry* get_jrt_entry() { return _jrt_entry; } + static void close_jrt_image(); // Add a module's exploded directory to the boot loader's exploded module build list static void add_to_exploded_build_list(Symbol* module_name, TRAPS);
--- a/src/hotspot/share/classfile/symbolTable.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/symbolTable.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -116,14 +116,17 @@ return SymbolTableHash::BaseConfig::allocate_node(size, value); } static void free_node(void* memory, Symbol* const& value) { - // We get here either because #1 some threads lost a race - // to insert a newly created Symbol, or #2 we are freeing - // a symbol during normal cleanup deletion. - // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT), - // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry) - // If #2, then the symbol must have refcount==0 - assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0), + // We get here because #1 some threads lost a race to insert a newly created Symbol + // or #2 we're cleaning up unused symbol. + // If #1, then the symbol can be either permanent (refcount==PERM_REFCOUNT), + // or regular newly created one (refcount==1) + // If #2, then the symbol is dead (refcount==0) + assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 1) || (value->refcount() == 0), "refcount %d", value->refcount()); + if (value->refcount() == 1) { + value->decrement_refcount(); + assert(value->refcount() == 0, "expected dead symbol"); + } SymbolTable::delete_symbol(value); SymbolTableHash::BaseConfig::free_node(memory, value); SymbolTable::item_removed(); @@ -162,6 +165,12 @@ } } +void SymbolTable::update_needs_rehash(bool rehash) { + if (rehash) { + _needs_rehashing = true; + } +} + void SymbolTable::item_added() { Atomic::inc(&(SymbolTable::the_table()->_items_count)); } @@ -398,9 +407,7 @@ SymbolTableGet stg; bool rehash_warning = false; _local_table->get(thread, lookup, stg, &rehash_warning); - if (rehash_warning) { - _needs_rehashing = true; - } + update_needs_rehash(rehash_warning); Symbol* sym = stg.get_res_sym(); assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); return sym; @@ -462,71 +469,26 @@ } } -class SymbolTableCreateEntry : public StackObj { -private: - Thread* _thread; - const char* _name; - int _len; - bool _heap; - Symbol* _return; - Symbol* _created; - - void assert_for_name(Symbol* sym, const char* where) const { -#ifdef ASSERT - assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len); - for (int i = 0; i < _len; i++) { - assert(sym->char_at(i) == _name[i], - "%s [%d,%d,%d]", where, i, sym->char_at(i), _name[i]); - } -#endif - } - -public: - SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap) - : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) { - assert(_name != NULL, "expected valid name"); - } - Symbol* operator()() { - _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread); - assert(_created != NULL, "expected created symbol"); - assert_for_name(_created, "operator()()"); - assert(_created->equals(_name, _len), - "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap); - return _created; - } - void operator()(bool inserted, Symbol** value) { - assert(value != NULL, "expected valid value"); - assert(*value != NULL, "value should point to a symbol"); - if (!inserted && (_created != NULL)) { - // We created our symbol, but someone else inserted - // theirs first, so ours will be destroyed. - // Since symbols are created with refcount of 1, - // we must decrement it here to 0 to delete, - // unless it's a permanent one. - if (_created->refcount() != PERM_REFCOUNT) { - assert(_created->refcount() == 1, "expected newly created symbol"); - _created->decrement_refcount(); - assert(_created->refcount() == 0, "expected dead symbol"); - } - } - _return = *value; - assert_for_name(_return, "operator()"); - } - Symbol* get_new_sym() const { - assert_for_name(_return, "get_new_sym"); - return _return; - } -}; - Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) { SymbolTableLookup lookup(THREAD, name, len, hash); - SymbolTableCreateEntry stce(THREAD, name, len, heap); + SymbolTableGet stg; + bool clean_hint = false; bool rehash_warning = false; - bool clean_hint = false; - _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint); - if (rehash_warning) { - _needs_rehashing = true; - } + Symbol* sym = NULL; + + do { + if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { + sym = stg.get_res_sym(); + break; + } + sym = SymbolTable::the_table()->allocate_symbol(name, len, heap, THREAD); + if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { + break; + } + } while(true); + + update_needs_rehash(rehash_warning); + if (clean_hint) { // we just found out that there is a dead item, // which we were unable to clean right now, @@ -536,8 +498,8 @@ mark_item_clean_count(); check_concurrent_work(); } - Symbol* sym = stce.get_new_sym(); - assert(sym->refcount() != 0, "zero is invalid"); + + assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); return sym; }
--- a/src/hotspot/share/classfile/symbolTable.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/symbolTable.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -169,6 +169,7 @@ void try_rehash_table(); bool do_rehash(); + inline void update_needs_rehash(bool rehash); public: // The symbol table
--- a/src/hotspot/share/classfile/vmSymbols.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/vmSymbols.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -379,6 +379,10 @@ case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_fmaD: case vmIntrinsics::_fmaF: + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: return true; default: return false; @@ -828,6 +832,12 @@ case vmIntrinsics::_subtractExactL: if (!UseMathExactIntrinsics || !InlineMathNatives) return true; break; + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + if (!UseCharacterCompareIntrinsics) return true; + break; #endif // COMPILER2 default: return false;
--- a/src/hotspot/share/classfile/vmSymbols.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -71,6 +71,7 @@ template(java_lang_Boolean, "java/lang/Boolean") \ template(java_lang_Character, "java/lang/Character") \ template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \ + template(java_lang_CharacterDataLatin1, "java/lang/CharacterDataLatin1") \ template(java_lang_Float, "java/lang/Float") \ template(java_lang_Double, "java/lang/Double") \ template(java_lang_Byte, "java/lang/Byte") \ @@ -933,6 +934,15 @@ do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \ do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \ \ + do_intrinsic(_isDigit, java_lang_CharacterDataLatin1, isDigit_name, int_bool_signature, F_R) \ + do_name( isDigit_name, "isDigit") \ + do_intrinsic(_isLowerCase, java_lang_CharacterDataLatin1, isLowerCase_name, int_bool_signature, F_R) \ + do_name( isLowerCase_name, "isLowerCase") \ + do_intrinsic(_isUpperCase, java_lang_CharacterDataLatin1, isUpperCase_name, int_bool_signature, F_R) \ + do_name( isUpperCase_name, "isUpperCase") \ + do_intrinsic(_isWhitespace, java_lang_CharacterDataLatin1, isWhitespace_name, int_bool_signature, F_R) \ + do_name( isWhitespace_name, "isWhitespace") \ + \ do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S) \ do_signature(Preconditions_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \ \
--- a/src/hotspot/share/code/vtableStubs.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/code/vtableStubs.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -51,6 +51,7 @@ void* VtableStub::operator new(size_t size, int code_size) throw() { + assert_lock_strong(VtableStubs_lock); assert(size == sizeof(VtableStub), "mismatched size"); // compute real VtableStub size (rounded to nearest word) const int real_size = align_up(code_size + (int)sizeof(VtableStub), wordSize); @@ -208,31 +209,35 @@ address VtableStubs::find_stub(bool is_vtable_stub, int vtable_index) { assert(vtable_index >= 0, "must be positive"); - VtableStub* s = ShareVtableStubs ? lookup(is_vtable_stub, vtable_index) : NULL; - if (s == NULL) { - if (is_vtable_stub) { - s = create_vtable_stub(vtable_index); - } else { - s = create_itable_stub(vtable_index); - } + VtableStub* s; + { + MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag); + s = ShareVtableStubs ? lookup(is_vtable_stub, vtable_index) : NULL; + if (s == NULL) { + if (is_vtable_stub) { + s = create_vtable_stub(vtable_index); + } else { + s = create_itable_stub(vtable_index); + } - // Creation of vtable or itable can fail if there is not enough free space in the code cache. - if (s == NULL) { - return NULL; - } + // Creation of vtable or itable can fail if there is not enough free space in the code cache. + if (s == NULL) { + return NULL; + } - enter(is_vtable_stub, vtable_index, s); - if (PrintAdapterHandlers) { - tty->print_cr("Decoding VtableStub %s[%d]@" INTX_FORMAT, - is_vtable_stub? "vtbl": "itbl", vtable_index, p2i(VtableStub::receiver_location())); - Disassembler::decode(s->code_begin(), s->code_end()); - } - // Notify JVMTI about this stub. The event will be recorded by the enclosing - // JvmtiDynamicCodeEventCollector and posted when this thread has released - // all locks. - if (JvmtiExport::should_post_dynamic_code_generated()) { - JvmtiExport::post_dynamic_code_generated_while_holding_locks(is_vtable_stub? "vtable stub": "itable stub", - s->code_begin(), s->code_end()); + enter(is_vtable_stub, vtable_index, s); + if (PrintAdapterHandlers) { + tty->print_cr("Decoding VtableStub %s[%d]@" INTX_FORMAT, + is_vtable_stub? "vtbl": "itbl", vtable_index, p2i(VtableStub::receiver_location())); + Disassembler::decode(s->code_begin(), s->code_end()); + } + // Notify JVMTI about this stub. The event will be recorded by the enclosing + // JvmtiDynamicCodeEventCollector and posted when this thread has released + // all locks. + if (JvmtiExport::should_post_dynamic_code_generated()) { + JvmtiExport::post_dynamic_code_generated_while_holding_locks(is_vtable_stub? "vtable stub": "itable stub", + s->code_begin(), s->code_end()); + } } } return s->entry_point(); @@ -247,7 +252,7 @@ VtableStub* VtableStubs::lookup(bool is_vtable_stub, int vtable_index) { - MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag); + assert_lock_strong(VtableStubs_lock); unsigned hash = VtableStubs::hash(is_vtable_stub, vtable_index); VtableStub* s = _table[hash]; while( s && !s->matches(is_vtable_stub, vtable_index)) s = s->next(); @@ -256,7 +261,7 @@ void VtableStubs::enter(bool is_vtable_stub, int vtable_index, VtableStub* s) { - MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag); + assert_lock_strong(VtableStubs_lock); assert(s->matches(is_vtable_stub, vtable_index), "bad vtable stub"); unsigned int h = VtableStubs::hash(is_vtable_stub, vtable_index); // enter s at the beginning of the corresponding list
--- a/src/hotspot/share/gc/cms/cmsHeap.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -70,19 +70,24 @@ Generation::ParNew, Generation::ConcurrentMarkSweep, "ParNew:CMS"), + _workers(NULL), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { - _workers = new WorkGang("GC Thread", ParallelGCThreads, - /* are_GC_task_threads */true, - /* are_ConcurrentGC_threads */false); - _workers->initialize_workers(); } jint CMSHeap::initialize() { jint status = GenCollectedHeap::initialize(); if (status != JNI_OK) return status; + _workers = new WorkGang("GC Thread", ParallelGCThreads, + /* are_GC_task_threads */true, + /* are_ConcurrentGC_threads */false); + if (_workers == NULL) { + return JNI_ENOMEM; + } + _workers->initialize_workers(); + // If we are running CMS, create the collector responsible // for collecting the CMS generations. if (!create_cms_collector()) {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -1531,10 +1531,6 @@ _is_subject_to_discovery_cm(this), _in_cset_fast_test() { - _workers = new WorkGang("GC Thread", ParallelGCThreads, - true /* are_GC_task_threads */, - false /* are_ConcurrentGC_threads */); - _workers->initialize_workers(); _verifier = new G1HeapVerifier(this); _allocator = new G1Allocator(this); @@ -1767,6 +1763,14 @@ _humongous_reclaim_candidates.initialize(start, end, granularity); } + _workers = new WorkGang("GC Thread", ParallelGCThreads, + true /* are_GC_task_threads */, + false /* are_ConcurrentGC_threads */); + if (_workers == NULL) { + return JNI_ENOMEM; + } + _workers->initialize_workers(); + // Create the G1ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1026,6 +1026,9 @@ // The number of regions that are completely free. uint num_free_regions() const { return _hrm.num_free_regions(); } + // The number of regions that can be allocated into. + uint num_free_or_available_regions() const { return num_free_regions() + _hrm.available(); } + MemoryUsage get_auxiliary_data_memory_usage() const { return _hrm.get_auxiliary_data_memory_usage(); }
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -89,7 +89,7 @@ Data after(_g1_heap); size_t eden_capacity_length_after_gc = _g1_heap->g1_policy()->young_list_target_length() - after._survivor_length; - size_t survivor_capacity_length_after_gc = _g1_heap->g1_policy()->max_survivor_regions(); + size_t survivor_capacity_length_before_gc = _g1_heap->g1_policy()->max_survivor_regions(); DetailedUsage usage; if (log_is_enabled(Trace, gc, heap)) { @@ -112,7 +112,7 @@ log_trace(gc, heap)(" Used: 0K, Waste: 0K"); log_info(gc, heap)("Survivor regions: " SIZE_FORMAT "->" SIZE_FORMAT "(" SIZE_FORMAT ")", - _before._survivor_length, after._survivor_length, survivor_capacity_length_after_gc); + _before._survivor_length, after._survivor_length, survivor_capacity_length_before_gc); log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K", usage._survivor_used / K, ((after._survivor_length * HeapRegion::GrainBytes) - usage._survivor_used) / K);
--- a/src/hotspot/share/gc/g1/g1Policy.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1Policy.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -470,6 +470,10 @@ // every time we calculate / recalculate the target young length. update_survivors_policy(); + assert(max_survivor_regions() + _g1h->num_used_regions() <= _g1h->max_regions(), + "Maximum survivor regions %u plus used regions %u exceeds max regions %u", + max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions()); + assert(_g1h->used() == _g1h->recalculate_used(), "sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT, _g1h->used(), _g1h->recalculate_used()); @@ -899,8 +903,8 @@ return _young_gen_sizer.adaptive_young_list_length(); } -size_t G1Policy::desired_survivor_size() const { - size_t const survivor_capacity = HeapRegion::GrainWords * _max_survivor_regions; +size_t G1Policy::desired_survivor_size(uint max_regions) const { + size_t const survivor_capacity = HeapRegion::GrainWords * max_regions; return (size_t)((((double)survivor_capacity) * TargetSurvivorRatio) / 100); } @@ -927,15 +931,22 @@ void G1Policy::update_survivors_policy() { double max_survivor_regions_d = (double) _young_list_target_length / (double) SurvivorRatio; - // We use ceiling so that if max_survivor_regions_d is > 0.0 (but - // smaller than 1.0) we'll get 1. - _max_survivor_regions = (uint) ceil(max_survivor_regions_d); - _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold(desired_survivor_size()); + // Calculate desired survivor size based on desired max survivor regions (unconstrained + // by remaining heap). Otherwise we may cause undesired promotions as we are + // already getting close to end of the heap, impacting performance even more. + uint const desired_max_survivor_regions = ceil(max_survivor_regions_d); + size_t const survivor_size = desired_survivor_size(desired_max_survivor_regions); + + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold(survivor_size); if (UsePerfData) { _policy_counters->tenuring_threshold()->set_value(_tenuring_threshold); - _policy_counters->desired_survivor_size()->set_value(desired_survivor_size() * oopSize); + _policy_counters->desired_survivor_size()->set_value(survivor_size * oopSize); } + // The real maximum survivor size is bounded by the number of regions that can + // be allocated into. + _max_survivor_regions = MIN2(desired_max_survivor_regions, + _g1h->num_free_or_available_regions()); } bool G1Policy::force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause) {
--- a/src/hotspot/share/gc/g1/g1Policy.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1Policy.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -399,7 +399,7 @@ AgeTable _survivors_age_table; - size_t desired_survivor_size() const; + size_t desired_survivor_size(uint max_regions) const; public: // Fraction used when predicting how many optional regions to include in // the CSet. This fraction of the available time is used for optional regions,
--- a/src/hotspot/share/gc/shared/barrierSet.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/shared/barrierSet.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -26,47 +26,24 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "runtime/thread.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" BarrierSet* BarrierSet::_barrier_set = NULL; -class SetBarrierSetNonJavaThread : public ThreadClosure { - BarrierSet* _barrier_set; - size_t _count; - -public: - SetBarrierSetNonJavaThread(BarrierSet* barrier_set) : - _barrier_set(barrier_set), _count(0) {} - - virtual void do_thread(Thread* thread) { - _barrier_set->on_thread_create(thread); - ++_count; - } - - size_t count() const { return _count; } -}; - void BarrierSet::set_barrier_set(BarrierSet* barrier_set) { assert(_barrier_set == NULL, "Already initialized"); _barrier_set = barrier_set; - // Some threads are created before the barrier set, so the call to - // BarrierSet::on_thread_create had to be deferred for them. Now that - // we have the barrier set, do those deferred calls. - - // First do any non-JavaThreads. - SetBarrierSetNonJavaThread njt_closure(_barrier_set); - Threads::non_java_threads_do(&njt_closure); - - // Do the current (main) thread. Ensure it's the one and only - // JavaThread so far. Also verify that it isn't yet on the thread + // Notify barrier set of the current (main) thread. Normally the + // Thread constructor deals with this, but the main thread is + // created before we get here. Verify it isn't yet on the thread // list, else we'd also need to call BarrierSet::on_thread_attach. + // This is the only thread that can exist at this point; the Thread + // constructor objects to other threads being created before the + // barrier set is available. assert(Thread::current()->is_Java_thread(), "Expected main thread to be a JavaThread"); - assert((njt_closure.count() + 1) == Threads::threads_before_barrier_set(), - "Unexpected JavaThreads before barrier set initialization: " - "Non-JavaThreads: " SIZE_FORMAT ", all: " SIZE_FORMAT, - njt_closure.count(), Threads::threads_before_barrier_set()); assert(!JavaThread::current()->on_thread_list(), "Main thread already on thread list."); _barrier_set->on_thread_create(Thread::current());
--- a/src/hotspot/share/gc/z/zArguments.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zArguments.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -80,10 +80,6 @@ FLAG_SET_DEFAULT(UseCompressedOops, false); FLAG_SET_DEFAULT(UseCompressedClassPointers, false); - // ClassUnloading not (yet) supported - FLAG_SET_DEFAULT(ClassUnloading, false); - FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false); - // Verification before startup and after exit not (yet) supported FLAG_SET_DEFAULT(VerifyDuringStartup, false); FLAG_SET_DEFAULT(VerifyBeforeExit, false);
--- a/src/hotspot/share/gc/z/zBarrier.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zBarrier.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -81,6 +81,7 @@ static void load_barrier_on_oop_fields(oop o); static oop load_barrier_on_weak_oop_field_preloaded(volatile oop* p, oop o); static oop load_barrier_on_phantom_oop_field_preloaded(volatile oop* p, oop o); + static void load_barrier_on_root_oop_field(oop* p); // Weak load barrier static oop weak_load_barrier_on_oop_field(volatile oop* p); @@ -99,6 +100,7 @@ // Keep alive barrier static void keep_alive_barrier_on_weak_oop_field(volatile oop* p); static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p); + static void keep_alive_barrier_on_phantom_root_oop_field(oop* p); // Mark barrier static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);
--- a/src/hotspot/share/gc/z/zBarrier.inline.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -111,11 +111,12 @@ const uintptr_t good_addr = slow_path(addr); // Non-atomic healing helps speed up root scanning. This is safe to do - // since we are always healing roots in a safepoint, which means we are - // never racing with mutators modifying roots while we are healing them. - // It's also safe in case multiple GC threads try to heal the same root, - // since they would always heal the root in the same way and it does not - // matter in which order it happens. + // since we are always healing roots in a safepoint, or under a lock, + // which ensures we are never racing with mutators modifying roots while + // we are healing them. It's also safe in case multiple GC threads try + // to heal the same root if it is aligned, since they would always heal + // the root in the same way and it does not matter in which order it + // happens. For misaligned oops, there needs to be mutual exclusion. *p = ZOop::to_oop(good_addr); } @@ -188,6 +189,11 @@ return load_barrier_on_oop_field_preloaded(p, o); } +inline void ZBarrier::load_barrier_on_root_oop_field(oop* p) { + const oop o = *p; + root_barrier<is_good_or_null_fast_path, load_barrier_on_oop_slow_path>(p, o); +} + // // Weak load barrier // @@ -269,6 +275,13 @@ barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); } +inline void ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(oop* p) { + // This operation is only valid when resurrection is blocked. + assert(ZResurrection::is_blocked(), "Invalid phase"); + const oop o = *p; + root_barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); +} + // // Mark barrier //
--- a/src/hotspot/share/gc/z/zBarrierSet.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zBarrierSet.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/z/zBarrierSet.hpp" #include "gc/z/zBarrierSetAssembler.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHeap.inline.hpp" #include "gc/z/zThreadLocalData.hpp" @@ -39,11 +40,20 @@ class ZBarrierSetC1; class ZBarrierSetC2; +static BarrierSetNMethod* make_barrier_set_nmethod() { + // NMethod barriers are only used when class unloading is enabled + if (!ClassUnloading) { + return NULL; + } + + return new ZBarrierSetNMethod(); +} + ZBarrierSet::ZBarrierSet() : BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(), make_barrier_set_c1<ZBarrierSetC1>(), make_barrier_set_c2<ZBarrierSetC2>(), - NULL /* barrier_set_nmethod */, + make_barrier_set_nmethod(), BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {} ZBarrierSetAssembler* ZBarrierSet::assembler() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "code/nmethod.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zLock.inline.hpp" +#include "gc/z/zOopClosures.hpp" +#include "gc/z/zNMethodTable.hpp" +#include "gc/z/zThreadLocalData.hpp" +#include "logging/log.hpp" + +bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { + ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm)); + log_trace(nmethod, barrier)("Entered critical zone for %p", nm); + + if (!is_armed(nm)) { + // Some other thread got here first and healed the oops + // and disarmed the nmethod. + return true; + } + + if (nm->is_unloading()) { + // We can end up calling nmethods that are unloading + // since we clear compiled ICs lazily. Returning false + // will re-resovle the call and update the compiled IC. + return false; + } + + // Heal oops and disarm + ZNMethodOopClosure cl; + nm->oops_do(&cl); + nm->fix_oop_relocations(); + + OrderAccess::release(); + + disarm(nm); + + return true; +} + +int ZBarrierSetNMethod::disarmed_value() const { + // We override the default BarrierSetNMethod::disarmed_value() since + // this can be called by GC threads, which doesn't keep an up to date + // address_bad_mask. + const uintptr_t disarmed_addr = ((uintptr_t)&ZAddressBadMask) + ZNMethodDisarmedOffset; + return *((int*)disarmed_addr); +} + +ByteSize ZBarrierSetNMethod::thread_disarmed_offset() const { + return ZThreadLocalData::nmethod_disarmed_offset(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP +#define SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP + +#include "gc/shared/barrierSetNMethod.hpp" +#include "memory/allocation.hpp" + +class nmethod; + +class ZBarrierSetNMethod : public BarrierSetNMethod { +protected: + virtual int disarmed_value() const; + virtual bool nmethod_entry_barrier(nmethod* nm); + +public: + virtual ByteSize thread_disarmed_offset() const; +}; + +#endif // SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -259,12 +259,10 @@ } void ZCollectedHeap::register_nmethod(nmethod* nm) { - assert_locked_or_safepoint(CodeCache_lock); ZNMethodTable::register_nmethod(nm); } void ZCollectedHeap::unregister_nmethod(nmethod* nm) { - assert_locked_or_safepoint(CodeCache_lock); ZNMethodTable::unregister_nmethod(nm); }
--- a/src/hotspot/share/gc/z/zGlobals.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zGlobals.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -91,6 +91,9 @@ const uintptr_t ZAddressSpaceSize = ZPlatformAddressSpaceSize; const uintptr_t ZAddressSpaceEnd = ZAddressSpaceStart + ZAddressSpaceSize; +// NMethod entry barrier +const size_t ZNMethodDisarmedOffset = ZPlatformNMethodDisarmedOffset; + // Cache line size const size_t ZCacheLineSize = ZPlatformCacheLineSize;
--- a/src/hotspot/share/gc/z/zHeap.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zHeap.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -69,6 +69,7 @@ _weak_roots_processor(&_workers), _relocate(&_workers), _relocation_set(), + _unload(&_workers), _serviceability(heap_min_size(), heap_max_size()) { // Install global heap instance assert(_heap == NULL, "Already initialized"); @@ -353,9 +354,6 @@ // Enter mark completed phase ZGlobalPhase = ZPhaseMarkCompleted; - // Resize metaspace - MetaspaceGC::compute_new_size(); - // Update statistics ZStatSample(ZSamplerHeapUsedAfterMark, used()); ZStatHeap::set_at_mark_end(capacity(), allocated(), used()); @@ -366,6 +364,9 @@ // Process weak roots _weak_roots_processor.process_weak_roots(); + // Prepare to unload unused classes and code + _unload.prepare(); + return true; } @@ -380,6 +381,9 @@ // Process concurrent weak roots _weak_roots_processor.process_concurrent_weak_roots(); + // Unload unused classes and code + _unload.unload(); + // Unblock resurrection of weak/phantom references ZResurrection::unblock(); @@ -463,8 +467,8 @@ void ZHeap::relocate_start() { assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); - // Update statistics - ZStatSample(ZSamplerHeapUsedBeforeRelocation, used()); + // Finish unloading of classes and code + _unload.finish(); // Flip address view ZAddressMasks::flip_to_remapped(); @@ -474,6 +478,7 @@ ZGlobalPhase = ZPhaseRelocate; // Update statistics + ZStatSample(ZSamplerHeapUsedBeforeRelocation, used()); ZStatHeap::set_at_relocate_start(capacity(), allocated(), used()); // Remap/Relocate roots
--- a/src/hotspot/share/gc/z/zHeap.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zHeap.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -41,6 +41,7 @@ #include "gc/z/zRootsIterator.hpp" #include "gc/z/zWeakRootsProcessor.hpp" #include "gc/z/zServiceability.hpp" +#include "gc/z/zUnload.hpp" #include "gc/z/zWorkers.hpp" #include "memory/allocation.hpp" @@ -59,6 +60,7 @@ ZWeakRootsProcessor _weak_roots_processor; ZRelocate _relocate; ZRelocationSet _relocation_set; + ZUnload _unload; ZServiceability _serviceability; size_t heap_min_size() const;
--- a/src/hotspot/share/gc/z/zMark.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zMark.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -287,6 +287,14 @@ } void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { + if (finalizable) { + ZMarkBarrierOopClosure<true /* finalizable */> cl; + cl.do_klass(obj->klass()); + } else { + ZMarkBarrierOopClosure<false /* finalizable */> cl; + cl.do_klass(obj->klass()); + } + const uintptr_t addr = (uintptr_t)obj->base(); const size_t size = (size_t)obj->length() * oopSize;
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zNMethodTable.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -23,45 +23,62 @@ #include "precompiled.hpp" #include "code/relocInfo.hpp" -#include "code/nativeInst.hpp" #include "code/nmethod.hpp" +#include "code/icBuffer.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" +#include "gc/z/zArray.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHash.inline.hpp" +#include "gc/z/zLock.inline.hpp" #include "gc/z/zNMethodTable.hpp" +#include "gc/z/zOopClosures.inline.hpp" +#include "gc/z/zTask.hpp" +#include "gc/z/zWorkers.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" -#include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "utilities/debug.hpp" -class ZNMethodWithImmediateOops { +class ZNMethodDataImmediateOops { private: - nmethod* const _nm; - const size_t _nimmediate_oops; + const size_t _nimmediate_oops; static size_t header_size(); - ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops); + ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops); public: - static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops); - static void destroy(ZNMethodWithImmediateOops* nmi); + static ZNMethodDataImmediateOops* create(const GrowableArray<oop*>& immediate_oops); + static void destroy(ZNMethodDataImmediateOops* data_immediate_oops); - nmethod* method() const; size_t immediate_oops_count() const; oop** immediate_oops_begin() const; oop** immediate_oops_end() const; }; -size_t ZNMethodWithImmediateOops::header_size() { - const size_t size = sizeof(ZNMethodWithImmediateOops); +size_t ZNMethodDataImmediateOops::header_size() { + const size_t size = sizeof(ZNMethodDataImmediateOops); assert(is_aligned(size, sizeof(oop*)), "Header misaligned"); return size; } -ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) : - _nm(nm), +ZNMethodDataImmediateOops* ZNMethodDataImmediateOops::create(const GrowableArray<oop*>& immediate_oops) { + // Allocate memory for the ZNMethodDataImmediateOops object + // plus the immediate oop* array that follows right after. + const size_t size = ZNMethodDataImmediateOops::header_size() + (sizeof(oop*) * immediate_oops.length()); + void* const data_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); + return ::new (data_immediate_oops) ZNMethodDataImmediateOops(immediate_oops); +} + +void ZNMethodDataImmediateOops::destroy(ZNMethodDataImmediateOops* data_immediate_oops) { + ZNMethodTable::safe_delete(data_immediate_oops); +} + +ZNMethodDataImmediateOops::ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops) : _nimmediate_oops(immediate_oops.length()) { // Save all immediate oops for (size_t i = 0; i < _nimmediate_oops; i++) { @@ -69,41 +86,97 @@ } } -ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) { - // Allocate memory for the ZNMethodWithImmediateOops object - // plus the immediate oop* array that follows right after. - const size_t size = header_size() + (sizeof(oop*) * immediate_oops.length()); - void* const method_with_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); - return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops); -} - -void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) { - FREE_C_HEAP_ARRAY(uint8_t, nmi); -} - -nmethod* ZNMethodWithImmediateOops::method() const { - return _nm; -} - -size_t ZNMethodWithImmediateOops::immediate_oops_count() const { +size_t ZNMethodDataImmediateOops::immediate_oops_count() const { return _nimmediate_oops; } -oop** ZNMethodWithImmediateOops::immediate_oops_begin() const { +oop** ZNMethodDataImmediateOops::immediate_oops_begin() const { // The immediate oop* array starts immediately after this object return (oop**)((uintptr_t)this + header_size()); } -oop** ZNMethodWithImmediateOops::immediate_oops_end() const { +oop** ZNMethodDataImmediateOops::immediate_oops_end() const { return immediate_oops_begin() + immediate_oops_count(); } +class ZNMethodData { +private: + ZReentrantLock _lock; + ZNMethodDataImmediateOops* volatile _immediate_oops; + + ZNMethodData(nmethod* nm); + +public: + static ZNMethodData* create(nmethod* nm); + static void destroy(ZNMethodData* data); + + ZReentrantLock* lock(); + + ZNMethodDataImmediateOops* immediate_oops() const; + ZNMethodDataImmediateOops* swap_immediate_oops(const GrowableArray<oop*>& immediate_oops); +}; + +ZNMethodData* ZNMethodData::create(nmethod* nm) { + void* const method = NEW_C_HEAP_ARRAY(uint8_t, sizeof(ZNMethodData), mtGC); + return ::new (method) ZNMethodData(nm); +} + +void ZNMethodData::destroy(ZNMethodData* data) { + ZNMethodDataImmediateOops::destroy(data->immediate_oops()); + ZNMethodTable::safe_delete(data); +} + +ZNMethodData::ZNMethodData(nmethod* nm) : + _lock(), + _immediate_oops(NULL) {} + +ZReentrantLock* ZNMethodData::lock() { + return &_lock; +} + +ZNMethodDataImmediateOops* ZNMethodData::immediate_oops() const { + return OrderAccess::load_acquire(&_immediate_oops); +} + +ZNMethodDataImmediateOops* ZNMethodData::swap_immediate_oops(const GrowableArray<oop*>& immediate_oops) { + ZNMethodDataImmediateOops* const data_immediate_oops = + immediate_oops.is_empty() ? NULL : ZNMethodDataImmediateOops::create(immediate_oops); + return Atomic::xchg(data_immediate_oops, &_immediate_oops); +} + +static ZNMethodData* gc_data(const nmethod* nm) { + return nm->gc_data<ZNMethodData>(); +} + +static void set_gc_data(nmethod* nm, ZNMethodData* data) { + return nm->set_gc_data<ZNMethodData>(data); +} + ZNMethodTableEntry* ZNMethodTable::_table = NULL; size_t ZNMethodTable::_size = 0; +ZLock ZNMethodTable::_iter_lock; +ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL; +size_t ZNMethodTable::_iter_table_size = 0; +ZArray<void*> ZNMethodTable::_iter_deferred_deletes; size_t ZNMethodTable::_nregistered = 0; size_t ZNMethodTable::_nunregistered = 0; volatile size_t ZNMethodTable::_claimed = 0; +void ZNMethodTable::safe_delete(void* data) { + if (data == NULL) { + return; + } + + ZLocker<ZLock> locker(&_iter_lock); + if (_iter_table != NULL) { + // Iteration in progress, defer delete + _iter_deferred_deletes.add(data); + } else { + // Iteration not in progress, delete now + FREE_C_HEAP_ARRAY(uint8_t, data); + } +} + ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) { GrowableArray<oop*> immediate_oops; bool non_immediate_oops = false; @@ -132,29 +205,27 @@ } } - // oops_count() returns the number of oops in the oop table plus one - if (immediate_oops.is_empty() && nm->oops_count() == 1) { - // No oops found, return empty entry - return ZNMethodTableEntry(); + // Attach GC data to nmethod + ZNMethodData* data = gc_data(nm); + if (data == NULL) { + data = ZNMethodData::create(nm); + set_gc_data(nm, data); } - if (immediate_oops.is_empty()) { - // No immediate oops found, return entry without immediate oops - return ZNMethodTableEntry(nm, non_immediate_oops); - } + // Attach immediate oops in GC data + ZNMethodDataImmediateOops* const old_data_immediate_oops = data->swap_immediate_oops(immediate_oops); + ZNMethodDataImmediateOops::destroy(old_data_immediate_oops); - // Return entry with immediate oops - return ZNMethodTableEntry(ZNMethodWithImmediateOops::create(nm, immediate_oops), non_immediate_oops); + // Create entry + return ZNMethodTableEntry(nm, non_immediate_oops, !immediate_oops.is_empty()); } -void ZNMethodTable::destroy_entry(ZNMethodTableEntry entry) { - if (entry.immediate_oops()) { - ZNMethodWithImmediateOops::destroy(entry.method_with_immediate_oops()); +ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) { + ZNMethodData* const data = gc_data(nm); + if (data == NULL) { + return NULL; } -} - -nmethod* ZNMethodTable::method(ZNMethodTableEntry entry) { - return entry.immediate_oops() ? entry.method_with_immediate_oops()->method() : entry.method(); + return data->lock(); } size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) { @@ -171,7 +242,7 @@ } bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry) { - const nmethod* const nm = method(entry); + const nmethod* const nm = entry.method(); size_t index = first_index(nm, size); for (;;) { @@ -183,9 +254,8 @@ return true; } - if (table_entry.registered() && method(table_entry) == nm) { + if (table_entry.registered() && table_entry.method() == nm) { // Replace existing entry - destroy_entry(table_entry); table[index] = entry; return false; } @@ -194,7 +264,7 @@ } } -bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, const nmethod* nm) { +bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) { if (size == 0) { // Table is empty return false; @@ -210,10 +280,13 @@ return false; } - if (table_entry.registered() && method(table_entry) == nm) { + if (table_entry.registered() && table_entry.method() == nm) { // Remove entry - destroy_entry(table_entry); table[index] = ZNMethodTableEntry(true /* unregistered */); + + // Destroy GC data + ZNMethodData::destroy(gc_data(nm)); + set_gc_data(nm, NULL); return true; } @@ -222,6 +295,7 @@ } void ZNMethodTable::rebuild(size_t new_size) { + ZLocker<ZLock> locker(&_iter_lock); assert(is_power_of_2(new_size), "Invalid size"); log_debug(gc, nmethod)("Rebuilding NMethod Table: " @@ -243,8 +317,10 @@ } } - // Delete old table - delete [] _table; + if (_iter_table != _table) { + // Delete old table + delete [] _table; + } // Install new table _table = new_table; @@ -294,8 +370,8 @@ p2i(nm), nm->compiler_name(), nm->oops_count() - 1, - entry.immediate_oops() ? entry.method_with_immediate_oops()->immediate_oops_count() : 0, - BOOL_TO_STR(entry.non_immediate_oops())); + entry.immediate_oops() ? gc_data(nm)->immediate_oops()->immediate_oops_count() : 0, + entry.non_immediate_oops() ? "Yes" : "No"); LogTarget(Trace, gc, nmethod, oops) log_oops; if (!log_oops.is_enabled()) { @@ -312,12 +388,14 @@ if (entry.immediate_oops()) { // Print nmethod immediate oops - const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); - oop** const begin = nmi->immediate_oops_begin(); - oop** const end = nmi->immediate_oops_end(); - for (oop** p = begin; p < end; p++) { - log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)", - (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name()); + const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops(); + if (nmi != NULL) { + oop** const begin = nmi->immediate_oops_begin(); + oop** const end = nmi->immediate_oops_end(); + for (oop** p = begin; p < end; p++) { + log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)", + (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name()); + } } } } @@ -343,21 +421,17 @@ } void ZNMethodTable::register_nmethod(nmethod* nm) { + assert(CodeCache_lock->owned_by_self(), "Lock must be held"); ResourceMark rm; + // Grow/Shrink/Prune table if needed + rebuild_if_needed(); + // Create entry const ZNMethodTableEntry entry = create_entry(nm); log_register(nm, entry); - if (!entry.registered()) { - // Method doesn't have any oops, ignore it - return; - } - - // Grow/Shrink/Prune table if needed - rebuild_if_needed(); - // Insert new entry if (register_entry(_table, _size, entry)) { // New entry registered. When register_entry() instead returns @@ -365,11 +439,31 @@ // to increase number of registered entries in that case. _nregistered++; } + + // Disarm nmethod entry barrier + disarm_nmethod(nm); +} + +void ZNMethodTable::sweeper_wait_for_iteration() { + // The sweeper must wait for any ongoing iteration to complete + // before it can unregister an nmethod. + if (!Thread::current()->is_Code_cache_sweeper_thread()) { + return; + } + + assert(CodeCache_lock->owned_by_self(), "Lock must be held"); + + while (_iter_table != NULL) { + MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + os::naked_short_sleep(1); + } } void ZNMethodTable::unregister_nmethod(nmethod* nm) { ResourceMark rm; + sweeper_wait_for_iteration(); + log_unregister(nm); // Remove entry @@ -383,20 +477,45 @@ } } -void ZNMethodTable::gc_prologue() { - _claimed = 0; +void ZNMethodTable::disarm_nmethod(nmethod* nm) { + BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs != NULL) { + bs->disarm(nm); + } } -void ZNMethodTable::gc_epilogue() { - assert(_claimed >= _size, "Failed to claim all table entries"); +void ZNMethodTable::nmethod_entries_do_begin() { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + ZLocker<ZLock> locker(&_iter_lock); + + // Prepare iteration + _iter_table = _table; + _iter_table_size = _size; + _claimed = 0; + assert(_iter_deferred_deletes.is_empty(), "Should be emtpy"); +} + +void ZNMethodTable::nmethod_entries_do_end() { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + ZLocker<ZLock> locker(&_iter_lock); + + // Finish iteration + if (_iter_table != _table) { + delete [] _iter_table; + } + _iter_table = NULL; + assert(_claimed >= _iter_table_size, "Failed to claim all table entries"); + + // Process deferred deletes + ZArrayIterator<void*> iter(&_iter_deferred_deletes); + for (void* data; iter.next(&data);) { + FREE_C_HEAP_ARRAY(uint8_t, data); + } + _iter_deferred_deletes.clear(); } void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) { - nmethod* const nm = method(entry); - if (!nm->is_alive()) { - // No need to visit oops - return; - } + nmethod* const nm = entry.method(); // Process oops table oop* const begin = nm->oops_begin(); @@ -407,29 +526,52 @@ } } + // Process immediate oops if (entry.immediate_oops()) { - // Process immediate oops - const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); - oop** const begin = nmi->immediate_oops_begin(); - oop** const end = nmi->immediate_oops_end(); - for (oop** p = begin; p < end; p++) { - cl->do_oop(*p); + const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops(); + if (nmi != NULL) { + oop** const begin = nmi->immediate_oops_begin(); + oop** const end = nmi->immediate_oops_end(); + for (oop** p = begin; p < end; p++) { + if (**p != Universe::non_oop_word()) { + cl->do_oop(*p); + } + } } } + // Process non-immediate oops if (entry.non_immediate_oops()) { - // Process non-immediate oops + nmethod* const nm = entry.method(); nm->fix_oop_relocations(); } } +class ZNMethodTableEntryToOopsDo : public ZNMethodTableEntryClosure { +private: + OopClosure* _cl; + +public: + ZNMethodTableEntryToOopsDo(OopClosure* cl) : + _cl(cl) {} + + void do_nmethod_entry(ZNMethodTableEntry entry) { + ZNMethodTable::entry_oops_do(entry, _cl); + } +}; + void ZNMethodTable::oops_do(OopClosure* cl) { + ZNMethodTableEntryToOopsDo entry_cl(cl); + nmethod_entries_do(&entry_cl); +} + +void ZNMethodTable::nmethod_entries_do(ZNMethodTableEntryClosure* cl) { for (;;) { // Claim table partition. Each partition is currently sized to span // two cache lines. This number is just a guess, but seems to work well. const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry); - const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size); - const size_t partition_end = MIN2(partition_start + partition_size, _size); + const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size); + const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size); if (partition_start == partition_end) { // End of table break; @@ -437,10 +579,141 @@ // Process table partition for (size_t i = partition_start; i < partition_end; i++) { - const ZNMethodTableEntry entry = _table[i]; + const ZNMethodTableEntry entry = _iter_table[i]; if (entry.registered()) { - entry_oops_do(entry, cl); + cl->do_nmethod_entry(entry); } } } } + +class ZNMethodTableUnlinkClosure : public ZNMethodTableEntryClosure { +private: + bool _unloading_occurred; + volatile bool _failed; + + void set_failed() { + Atomic::store(true, &_failed); + } + +public: + ZNMethodTableUnlinkClosure(bool unloading_occurred) : + _unloading_occurred(unloading_occurred), + _failed(false) {} + + virtual void do_nmethod_entry(ZNMethodTableEntry entry) { + if (failed()) { + return; + } + + nmethod* const nm = entry.method(); + if (!nm->is_alive()) { + return; + } + + if (nm->is_unloading()) { + // Unlinking of the dependencies must happen before the + // handshake separating unlink and purge. + nm->flush_dependencies(false /* delete_immediately */); + return; + } + + ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm)); + + // Heal oops and disarm + ZNMethodOopClosure cl; + ZNMethodTable::entry_oops_do(entry, &cl); + ZNMethodTable::disarm_nmethod(nm); + + // Clear compiled ICs and exception caches + if (!nm->unload_nmethod_caches(_unloading_occurred)) { + set_failed(); + } + } + + bool failed() const { + return Atomic::load(&_failed); + } +}; + +class ZNMethodTableUnlinkTask : public ZTask { +private: + ZNMethodTableUnlinkClosure _cl; + ICRefillVerifier* _verifier; + +public: + ZNMethodTableUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) : + ZTask("ZNMethodTableUnlinkTask"), + _cl(unloading_occurred), + _verifier(verifier) { + ZNMethodTable::nmethod_entries_do_begin(); + } + + ~ZNMethodTableUnlinkTask() { + ZNMethodTable::nmethod_entries_do_end(); + } + + virtual void work() { + ICRefillVerifierMark mark(_verifier); + ZNMethodTable::nmethod_entries_do(&_cl); + } + + bool success() const { + return !_cl.failed(); + } +}; + +void ZNMethodTable::unlink(ZWorkers* workers, bool unloading_occurred) { + for (;;) { + ICRefillVerifier verifier; + + { + ZNMethodTableUnlinkTask task(unloading_occurred, &verifier); + workers->run_concurrent(&task); + if (task.success()) { + return; + } + } + + // Cleaning failed because we ran out of transitional IC stubs, + // so we have to refill and try again. Refilling requires taking + // a safepoint, so we temporarily leave the suspendible thread set. + SuspendibleThreadSetLeaver sts; + InlineCacheBuffer::refill_ic_stubs(); + } +} + +class ZNMethodTablePurgeClosure : public ZNMethodTableEntryClosure { +public: + virtual void do_nmethod_entry(ZNMethodTableEntry entry) { + nmethod* const nm = entry.method(); + if (nm->is_alive() && nm->is_unloading()) { + nm->make_unloaded(); + } + } +}; + +class ZNMethodTablePurgeTask : public ZTask { +private: + ZNMethodTablePurgeClosure _cl; + +public: + ZNMethodTablePurgeTask() : + ZTask("ZNMethodTablePurgeTask"), + _cl() { + ZNMethodTable::nmethod_entries_do_begin(); + } + + ~ZNMethodTablePurgeTask() { + ZNMethodTable::nmethod_entries_do_end(); + } + + virtual void work() { + ZNMethodTable::nmethod_entries_do(&_cl); + } +}; + +void ZNMethodTable::purge(ZWorkers* workers) { + ZNMethodTablePurgeTask task; + workers->run_concurrent(&task); +}
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zNMethodTable.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -24,28 +24,40 @@ #ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP #define SHARE_GC_Z_ZNMETHODTABLE_HPP +#include "gc/z/zArray.hpp" #include "gc/z/zGlobals.hpp" +#include "gc/z/zLock.hpp" #include "gc/z/zNMethodTableEntry.hpp" #include "memory/allocation.hpp" +class ZWorkers; + +class ZNMethodTableEntryClosure { +public: + virtual void do_nmethod_entry(ZNMethodTableEntry entry) = 0; +}; + class ZNMethodTable : public AllStatic { private: static ZNMethodTableEntry* _table; static size_t _size; + static ZLock _iter_lock; + static ZNMethodTableEntry* _iter_table; + static size_t _iter_table_size; + static ZArray<void*> _iter_deferred_deletes; static size_t _nregistered; static size_t _nunregistered; static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize); static ZNMethodTableEntry create_entry(nmethod* nm); - static void destroy_entry(ZNMethodTableEntry entry); - - static nmethod* method(ZNMethodTableEntry entry); static size_t first_index(const nmethod* nm, size_t size); static size_t next_index(size_t prev_index, size_t size); + static void sweeper_wait_for_iteration(); + static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry); - static bool unregister_entry(ZNMethodTableEntry* table, size_t size, const nmethod* nm); + static bool unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm); static void rebuild(size_t new_size); static void rebuild_if_needed(); @@ -53,19 +65,28 @@ static void log_register(const nmethod* nm, ZNMethodTableEntry entry); static void log_unregister(const nmethod* nm); - static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl); +public: + static void safe_delete(void* data); -public: static size_t registered_nmethods(); static size_t unregistered_nmethods(); static void register_nmethod(nmethod* nm); static void unregister_nmethod(nmethod* nm); + static void disarm_nmethod(nmethod* nm); - static void gc_prologue(); - static void gc_epilogue(); + static ZReentrantLock* lock_for_nmethod(nmethod* nm); static void oops_do(OopClosure* cl); + + static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl); + + static void nmethod_entries_do_begin(); + static void nmethod_entries_do_end(); + static void nmethod_entries_do(ZNMethodTableEntryClosure* cl); + + static void unlink(ZWorkers* workers, bool unloading_occurred); + static void purge(ZWorkers* workers); }; #endif // SHARE_GC_Z_ZNMETHODTABLE_HPP
--- a/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,38 +43,30 @@ // | | // | 0-0 Registered Flag (1-bits) * // | -// * 63-3 NMethod/ZNMethodWithImmediateOops Address (61-bits) +// * 63-3 NMethod Address (61-bits) // class nmethod; -class ZNMethodWithImmediateOops; class ZNMethodTableEntry : public CHeapObj<mtGC> { private: - typedef ZBitField<uint64_t, bool, 0, 1> field_registered; - typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered; - typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops; - typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops; - typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method; - typedef ZBitField<uint64_t, ZNMethodWithImmediateOops*, 3, 61, 3> field_method_with_immediate_oops; + typedef ZBitField<uint64_t, bool, 0, 1> field_registered; + typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered; + typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops; + typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops; + typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method; uint64_t _entry; public: - ZNMethodTableEntry(bool unregistered = false) : + explicit ZNMethodTableEntry(bool unregistered = false) : _entry(field_unregistered::encode(unregistered) | field_registered::encode(false)) {} - ZNMethodTableEntry(nmethod* method, bool non_immediate_oops) : + ZNMethodTableEntry(nmethod* method, bool non_immediate_oops, bool immediate_oops) : _entry(field_method::encode(method) | field_non_immediate_oops::encode(non_immediate_oops) | - field_immediate_oops::encode(false) | - field_registered::encode(true)) {} - - ZNMethodTableEntry(ZNMethodWithImmediateOops* method_with_immediate_oops, bool non_immediate_oops) : - _entry(field_method_with_immediate_oops::encode(method_with_immediate_oops) | - field_non_immediate_oops::encode(non_immediate_oops) | - field_immediate_oops::encode(true) | + field_immediate_oops::encode(immediate_oops) | field_registered::encode(true)) {} bool registered() const { @@ -96,10 +88,6 @@ nmethod* method() const { return field_method::decode(_entry); } - - ZNMethodWithImmediateOops* method_with_immediate_oops() const { - return field_method_with_immediate_oops::decode(_entry); - } }; #endif // SHARE_GC_Z_ZNMETHODTABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zOopClosures.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zOopClosures.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -39,14 +39,23 @@ #endif }; +class ZNMethodOopClosure : public OopClosure { +public: + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); +}; + template <bool finalizable> -class ZMarkBarrierOopClosure : public BasicOopIterateClosure { +class ZMarkBarrierOopClosure : public MetadataVisitingOopIterateClosure { public: ZMarkBarrierOopClosure(); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); + virtual void do_klass(Klass* k); + virtual void do_cld(ClassLoaderData* cld); + #ifdef ASSERT virtual bool should_verify_oops() { return false;
--- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -24,6 +24,7 @@ #ifndef SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP #define SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP +#include "classfile/classLoaderData.hpp" #include "gc/z/zBarrier.inline.hpp" #include "gc/z/zHeap.inline.hpp" #include "gc/z/zOop.inline.hpp" @@ -40,9 +41,21 @@ ShouldNotReachHere(); } +inline void ZNMethodOopClosure::do_oop(oop* p) { + if (ZResurrection::is_blocked()) { + ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(p); + } else { + ZBarrier::load_barrier_on_root_oop_field(p); + } +} + +inline void ZNMethodOopClosure::do_oop(narrowOop* p) { + ShouldNotReachHere(); +} + template <bool finalizable> inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() : - BasicOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {} + MetadataVisitingOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {} template <bool finalizable> inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) { @@ -54,6 +67,18 @@ ShouldNotReachHere(); } +template <bool finalizable> +inline void ZMarkBarrierOopClosure<finalizable>::do_klass(Klass* k) { + ClassLoaderData* const cld = k->class_loader_data(); + ZMarkBarrierOopClosure<finalizable>::do_cld(cld); +} + +template <bool finalizable> +inline void ZMarkBarrierOopClosure<finalizable>::do_cld(ClassLoaderData* cld) { + const int claim = finalizable ? ClassLoaderData::_claim_finalizable : ClassLoaderData::_claim_strong; + cld->oops_do(this, claim); +} + inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) { return ZBarrier::is_alive_barrier_on_phantom_oop(o); }
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zRootsIterator.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -27,8 +27,11 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "compiler/oopMap.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMethodTable.hpp" #include "gc/z/zOopClosures.inline.hpp" @@ -132,6 +135,30 @@ } } +class ZCodeBlobClosure : public CodeBlobToOopClosure { +private: + BarrierSetNMethod* _bs; + +public: + ZCodeBlobClosure(OopClosure* cl) : + CodeBlobToOopClosure(cl, true /* fix_relocations */), + _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {} + + virtual void do_code_blob(CodeBlob* cb) { + nmethod* const nm = cb->as_nmethod_or_null(); + if (nm == NULL || nm->test_set_oops_do_mark()) { + return; + } + CodeBlobToOopClosure::do_code_blob(cb); + _bs->disarm(nm); + } +}; + +void ZRootsIteratorClosure::do_thread(Thread* thread) { + ZCodeBlobClosure code_cl(this); + thread->oops_do(this, ClassUnloading ? &code_cl : NULL); +} + ZRootsIterator::ZRootsIterator() : _universe(this), _object_synchronizer(this), @@ -145,16 +172,23 @@ ZStatTimer timer(ZSubPhasePauseRootsSetup); Threads::change_thread_claim_parity(); COMPILER2_PRESENT(DerivedPointerTable::clear()); - CodeCache::gc_prologue(); - ZNMethodTable::gc_prologue(); + if (ClassUnloading) { + nmethod::oops_do_marking_prologue(); + } else { + ZNMethodTable::nmethod_entries_do_begin(); + } } ZRootsIterator::~ZRootsIterator() { ZStatTimer timer(ZSubPhasePauseRootsTeardown); ResourceMark rm; - ZNMethodTable::gc_epilogue(); - CodeCache::gc_epilogue(); + if (ClassUnloading) { + nmethod::oops_do_marking_epilogue(); + } else { + ZNMethodTable::nmethod_entries_do_end(); + } JvmtiExport::gc_epilogue(); + COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); Threads::assert_all_threads_claimed(); } @@ -209,7 +243,9 @@ _jvmti_export.oops_do(cl); _system_dictionary.oops_do(cl); _threads.oops_do(cl); - _code_cache.oops_do(cl); + if (!ClassUnloading) { + _code_cache.oops_do(cl); + } if (visit_jvmti_weak_export) { _jvmti_weak_export.oops_do(cl); } @@ -242,8 +278,13 @@ void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) { ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph); - CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none); - ClassLoaderDataGraph::cld_do(&cld_cl); + if (_marking) { + CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_strong); + ClassLoaderDataGraph::always_strong_cld_do(&cld_cl); + } else { + CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_none); + ClassLoaderDataGraph::cld_do(&cld_cl); + } } void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
--- a/src/hotspot/share/gc/z/zRootsIterator.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zRootsIterator.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -33,9 +33,7 @@ class ZRootsIteratorClosure : public OopClosure, public ThreadClosure { public: - virtual void do_thread(Thread* thread) { - thread->oops_do(this, NULL); - } + virtual void do_thread(Thread* thread); }; typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
--- a/src/hotspot/share/gc/z/zThreadLocalData.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/gc/z/zThreadLocalData.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZTHREADLOCALDATA_HPP #include "gc/z/zMarkStack.hpp" +#include "gc/z/zGlobals.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" #include "utilities/sizes.hpp" @@ -62,6 +63,10 @@ static ByteSize address_bad_mask_offset() { return Thread::gc_data_offset() + byte_offset_of(ZThreadLocalData, _address_bad_mask); } + + static ByteSize nmethod_disarmed_offset() { + return address_bad_mask_offset() + in_ByteSize(ZNMethodDisarmedOffset); + } }; #endif // SHARE_GC_Z_ZTHREADLOCALDATA_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zUnload.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "classfile/classLoaderDataGraph.hpp" +#include "classfile/systemDictionary.hpp" +#include "code/codeBehaviours.hpp" +#include "code/codeCache.hpp" +#include "code/dependencyContext.hpp" +#include "gc/shared/gcBehaviours.hpp" +#include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/z/zLock.inline.hpp" +#include "gc/z/zNMethodTable.hpp" +#include "gc/z/zOopClosures.hpp" +#include "gc/z/zStat.hpp" +#include "gc/z/zUnload.hpp" +#include "oops/access.inline.hpp" + +static const ZStatSubPhase ZSubPhaseConcurrentClassesUnload("Concurrent Classes Unload"); + +class ZIsUnloadingOopClosure : public OopClosure { +private: + ZPhantomIsAliveObjectClosure _is_alive; + bool _is_unloading; + +public: + ZIsUnloadingOopClosure() : + _is_alive(), + _is_unloading(false) {} + + virtual void do_oop(oop* p) { + const oop o = RawAccess<>::oop_load(p); + if (o != NULL && !_is_alive.do_object_b(o)) { + _is_unloading = true; + } + } + + virtual void do_oop(narrowOop* p) { + ShouldNotReachHere(); + } + + bool is_unloading() const { + return _is_unloading; + } +}; + +class ZIsUnloadingBehaviour : public IsUnloadingBehaviour { +private: + bool is_unloading(nmethod* nm) const { + ZIsUnloadingOopClosure cl; + nm->oops_do(&cl, true /* allow_zombie */); + return cl.is_unloading(); + } + +public: + virtual bool is_unloading(CompiledMethod* method) const { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock == NULL) { + return is_unloading(nm); + } else { + ZLocker<ZReentrantLock> locker(lock); + return is_unloading(nm); + } + } +}; + +class ZCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour { +public: + virtual bool lock(CompiledMethod* method) { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock != NULL) { + lock->lock(); + } + return true; + } + + virtual void unlock(CompiledMethod* method) { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock != NULL) { + lock->unlock(); + } + } + + virtual bool is_safe(CompiledMethod* method) { + if (SafepointSynchronize::is_at_safepoint()) { + return true; + } + + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + return lock == NULL || lock->is_owned(); + } +}; + +ZUnload::ZUnload(ZWorkers* workers) : + _workers(workers) { + + if (!ClassUnloading) { + return; + } + + static ZIsUnloadingBehaviour is_unloading_behaviour; + IsUnloadingBehaviour::set_current(&is_unloading_behaviour); + + static ZCompiledICProtectionBehaviour ic_protection_behaviour; + CompiledICProtectionBehaviour::set_current(&ic_protection_behaviour); +} + +void ZUnload::prepare() { + if (!ClassUnloading) { + return; + } + + CodeCache::increment_unloading_cycle(); + DependencyContext::cleaning_start(); +} + +void ZUnload::unlink() { + SuspendibleThreadSetJoiner sts; + bool unloading_occurred; + + { + MutexLockerEx ml(ClassLoaderDataGraph_lock); + unloading_occurred = SystemDictionary::do_unloading(ZStatPhase::timer()); + } + + Klass::clean_weak_klass_links(unloading_occurred); + + ZNMethodTable::unlink(_workers, unloading_occurred); + + DependencyContext::cleaning_end(); +} + +void ZUnload::purge() { + { + SuspendibleThreadSetJoiner sts; + ZNMethodTable::purge(_workers); + } + + ClassLoaderDataGraph::purge(); + CodeCache::purge_exception_caches(); +} + +class ZUnloadRendezvousClosure : public ThreadClosure { +public: + void do_thread(Thread* thread) {} +}; + +void ZUnload::unload() { + if (!ClassUnloading) { + return; + } + + ZStatTimer timer(ZSubPhaseConcurrentClassesUnload); + + // Unlink stale metadata and nmethods + unlink(); + + // Make sure stale metadata and nmethods are no longer observable + ZUnloadRendezvousClosure cl; + Handshake::execute(&cl); + + // Purge stale metadata and nmethods that were unlinked + purge(); +} + +void ZUnload::finish() { + // Resize and verify metaspace + MetaspaceGC::compute_new_size(); + MetaspaceUtils::verify_metrics(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zUnload.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZUNLOAD_HPP +#define SHARE_GC_Z_ZUNLOAD_HPP + +class ZWorkers; + +class ZUnload { +private: + ZWorkers* const _workers; + + void unlink(); + void purge(); + +public: + ZUnload(ZWorkers* workers); + + void prepare(); + void unload(); + void finish(); +}; + +#endif // SHARE_GC_Z_ZUNLOAD_HPP
--- a/src/hotspot/share/interpreter/invocationCounter.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/interpreter/invocationCounter.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -153,9 +153,9 @@ // don't need the shift by number_of_noncount_bits, but we do need to adjust // the factor by which we scale the threshold. if (ProfileInterpreter) { - InterpreterBackwardBranchLimit = (CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; + InterpreterBackwardBranchLimit = (int)((int64_t)CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); } else { - InterpreterBackwardBranchLimit = ((CompileThreshold * OnStackReplacePercentage) / 100) << number_of_noncount_bits; + InterpreterBackwardBranchLimit = (int)(((int64_t)CompileThreshold * OnStackReplacePercentage / 100) << number_of_noncount_bits); } assert(0 <= InterpreterBackwardBranchLimit,
--- a/src/hotspot/share/jfr/metadata/metadata.xml Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/jfr/metadata/metadata.xml Thu Dec 13 11:47:35 2018 -0800 @@ -40,7 +40,8 @@ <Event name="ThreadPark" category="Java Application" label="Java Thread Park" thread="true" stackTrace="true"> <Field type="Class" name="parkedClass" label="Class Parked On" /> - <Field type="long" contentType="millis" name="timeout" label="Park Timeout" /> + <Field type="long" contentType="nanos" name="timeout" label="Park Timeout" /> + <Field type="long" contentType="epochmillis" name="until" label="Park Until" /> <Field type="ulong" contentType="address" name="address" label="Address of Object Parked" relation="JavaMonitorAddress" /> </Event> @@ -1140,5 +1141,6 @@ <XmlContentType name="address" annotationType="jdk.jfr.MemoryAddress" /> <XmlContentType name="percentage" annotationType="jdk.jfr.Percentage" /> <XmlContentType name="millis" annotationType="jdk.jfr.Timespan" annotationValue="MILLISECONDS" /> - + <XmlContentType name="nanos" annotationType="jdk.jfr.Timespan" annotationValue="NANOSECONDS" /> + </Metadata>
--- a/src/hotspot/share/oops/methodCounters.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/oops/methodCounters.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -103,9 +103,9 @@ // If interpreter profiling is enabled, the backward branch limit // is compared against the method data counter rather than an invocation // counter, therefore no shifting of bits is required. - _interpreter_backward_branch_limit = (compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; + _interpreter_backward_branch_limit = (int)((int64_t)compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); } else { - _interpreter_backward_branch_limit = ((compile_threshold * OnStackReplacePercentage) / 100) << InvocationCounter::count_shift; + _interpreter_backward_branch_limit = (int)(((int64_t)compile_threshold * OnStackReplacePercentage / 100) << InvocationCounter::count_shift); } _interpreter_profile_limit = ((compile_threshold * InterpreterProfilePercentage) / 100) << InvocationCounter::count_shift; _invoke_mask = right_n_bits(CompilerConfig::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
--- a/src/hotspot/share/opto/c2_globals.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/c2_globals.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -710,6 +710,9 @@ diagnostic(bool, UseMathExactIntrinsics, true, \ "Enables intrinsification of various java.lang.Math functions") \ \ + diagnostic(bool, UseCharacterCompareIntrinsics, false, \ + "Enables intrinsification of java.lang.Character functions") \ + \ diagnostic(bool, UseMultiplyToLenIntrinsic, false, \ "Enables intrinsification of BigInteger.multiplyToLen()") \ \
--- a/src/hotspot/share/opto/c2compiler.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/c2compiler.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -428,6 +428,18 @@ case vmIntrinsics::_fmaF: if (!UseFMA || !Matcher::match_rule_supported(Op_FmaF)) return false; break; + case vmIntrinsics::_isDigit: + if (!Matcher::match_rule_supported(Op_Digit)) return false; + break; + case vmIntrinsics::_isLowerCase: + if (!Matcher::match_rule_supported(Op_LowerCase)) return false; + break; + case vmIntrinsics::_isUpperCase: + if (!Matcher::match_rule_supported(Op_UpperCase)) return false; + break; + case vmIntrinsics::_isWhitespace: + if (!Matcher::match_rule_supported(Op_Whitespace)) return false; + break; case vmIntrinsics::_hashCode: case vmIntrinsics::_identityHashCode: case vmIntrinsics::_getClass:
--- a/src/hotspot/share/opto/classes.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/classes.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -201,6 +201,7 @@ macro(LoopLimit) macro(Mach) macro(MachProj) +macro(MulAddS2I) macro(MaxI) macro(MemBarAcquire) macro(LoadFence) @@ -341,6 +342,7 @@ macro(MulReductionVF) macro(MulVD) macro(MulReductionVD) +macro(MulAddVS2VI) macro(FmaVD) macro(FmaVF) macro(DivVF) @@ -394,3 +396,7 @@ macro(ExtractL) macro(ExtractF) macro(ExtractD) +macro(Digit) +macro(LowerCase) +macro(UpperCase) +macro(Whitespace)
--- a/src/hotspot/share/opto/intrinsicnode.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/intrinsicnode.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,4 +180,40 @@ virtual const Type* Value(PhaseGVN* phase) const; }; +//-------------------------------DigitNode---------------------------------------- +class DigitNode : public Node { +public: + DigitNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------LowerCaseNode------------------------------------ +class LowerCaseNode : public Node { +public: + LowerCaseNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------UpperCaseNode------------------------------------ +class UpperCaseNode : public Node { +public: + UpperCaseNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------WhitespaceCode----------------------------------- +class WhitespaceNode : public Node { +public: + WhitespaceNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + #endif // SHARE_VM_OPTO_INTRINSICNODE_HPP
--- a/src/hotspot/share/opto/library_call.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/library_call.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -324,6 +324,7 @@ bool inline_montgomerySquare(); bool inline_vectorizedMismatch(); bool inline_fma(vmIntrinsics::ID id); + bool inline_character_compare(vmIntrinsics::ID id); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -867,6 +868,12 @@ case vmIntrinsics::_fmaF: return inline_fma(intrinsic_id()); + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + return inline_character_compare(intrinsic_id()); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -6555,6 +6562,32 @@ return true; } +bool LibraryCallKit::inline_character_compare(vmIntrinsics::ID id) { + // argument(0) is receiver + Node* codePoint = argument(1); + Node* n = NULL; + + switch (id) { + case vmIntrinsics::_isDigit : + n = new DigitNode(control(), codePoint); + break; + case vmIntrinsics::_isLowerCase : + n = new LowerCaseNode(control(), codePoint); + break; + case vmIntrinsics::_isUpperCase : + n = new UpperCaseNode(control(), codePoint); + break; + case vmIntrinsics::_isWhitespace : + n = new WhitespaceNode(control(), codePoint); + break; + default: + fatal_unexpected_iid(id); + } + + set_result(_gvn.transform(n)); + return true; +} + bool LibraryCallKit::inline_profileBoolean() { Node* counts = argument(1); const TypeAryPtr* ary = NULL;
--- a/src/hotspot/share/opto/loopnode.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/loopnode.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -1249,6 +1249,9 @@ // important (common) to do address expressions. Node *remix_address_expressions( Node *n ); + // Convert add to muladd to generate MuladdS2I under certain criteria + Node * convert_add_to_muladd(Node * n); + // Attempt to use a conditional move instead of a phi/branch Node *conditional_move( Node *n );
--- a/src/hotspot/share/opto/loopopts.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/loopopts.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -493,6 +493,54 @@ return NULL; } +// Optimize ((in1[2*i] * in2[2*i]) + (in1[2*i+1] * in2[2*i+1])) +Node *PhaseIdealLoop::convert_add_to_muladd(Node* n) { + assert(n->Opcode() == Op_AddI, "sanity"); + Node * nn = NULL; + Node * in1 = n->in(1); + Node * in2 = n->in(2); + if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) { + IdealLoopTree* loop_n = get_loop(get_ctrl(n)); + if (loop_n->_head->as_Loop()->is_valid_counted_loop() && + Matcher::match_rule_supported(Op_MulAddS2I) && + Matcher::match_rule_supported(Op_MulAddVS2VI)) { + Node* mul_in1 = in1->in(1); + Node* mul_in2 = in1->in(2); + Node* mul_in3 = in2->in(1); + Node* mul_in4 = in2->in(2); + if (mul_in1->Opcode() == Op_LoadS && + mul_in2->Opcode() == Op_LoadS && + mul_in3->Opcode() == Op_LoadS && + mul_in4->Opcode() == Op_LoadS) { + IdealLoopTree* loop1 = get_loop(get_ctrl(mul_in1)); + IdealLoopTree* loop2 = get_loop(get_ctrl(mul_in2)); + IdealLoopTree* loop3 = get_loop(get_ctrl(mul_in3)); + IdealLoopTree* loop4 = get_loop(get_ctrl(mul_in4)); + IdealLoopTree* loop5 = get_loop(get_ctrl(in1)); + IdealLoopTree* loop6 = get_loop(get_ctrl(in2)); + // All nodes should be in the same counted loop. + if (loop_n == loop1 && loop_n == loop2 && loop_n == loop3 && + loop_n == loop4 && loop_n == loop5 && loop_n == loop6) { + Node* adr1 = mul_in1->in(MemNode::Address); + Node* adr2 = mul_in2->in(MemNode::Address); + Node* adr3 = mul_in3->in(MemNode::Address); + Node* adr4 = mul_in4->in(MemNode::Address); + if (adr1->is_AddP() && adr2->is_AddP() && adr3->is_AddP() && adr4->is_AddP()) { + if ((adr1->in(AddPNode::Base) == adr3->in(AddPNode::Base)) && + (adr2->in(AddPNode::Base) == adr4->in(AddPNode::Base))) { + nn = new MulAddS2INode(mul_in1, mul_in2, mul_in3, mul_in4); + register_new_node(nn, get_ctrl(n)); + _igvn.replace_node(n, nn); + return nn; + } + } + } + } + } + } + return nn; +} + //------------------------------conditional_move------------------------------- // Attempt to replace a Phi with a conditional move. We have some pretty // strict profitability requirements. All Phis at the merge point must @@ -927,6 +975,11 @@ Node *m = remix_address_expressions( n ); if( m ) return m; + if (n_op == Op_AddI) { + Node *nn = convert_add_to_muladd( n ); + if ( nn ) return nn; + } + if (n->is_ConstraintCast()) { Node* dom_cast = n->as_ConstraintCast()->dominating_cast(&_igvn, this); // ConstraintCastNode::dominating_cast() uses node control input to determine domination.
--- a/src/hotspot/share/opto/matcher.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/matcher.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -2352,6 +2352,15 @@ n->del_req(3); break; } + case Op_MulAddS2I: { + Node* pair1 = new BinaryNode(n->in(1), n->in(2)); + Node* pair2 = new BinaryNode(n->in(3), n->in(4)); + n->set_req(1, pair1); + n->set_req(2, pair2); + n->del_req(4); + n->del_req(3); + break; + } default: break; }
--- a/src/hotspot/share/opto/mulnode.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/mulnode.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -285,4 +285,15 @@ virtual const Type* Value(PhaseGVN* phase) const; }; +//------------------------------MulAddS2INode---------------------------------- +// Multiply shorts into integers and add them. +// Semantics: I_OUT = S1 * S2 + S3 * S4 +class MulAddS2INode : public Node { +public: + MulAddS2INode(Node* in1, Node *in2, Node *in3, Node* in4) : Node(0, in1, in2, in3, in4) {} + virtual int Opcode() const; + const Type *bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + #endif // SHARE_VM_OPTO_MULNODE_HPP
--- a/src/hotspot/share/opto/parseHelper.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/parseHelper.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -471,15 +471,15 @@ if (osr_site) { ciProfileData* data = md->bci_to_data(cur_bci); assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch"); - int limit = (CompileThreshold - * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; + int limit = (int)((int64_t)CompileThreshold + * (OnStackReplacePercentage - InterpreterProfilePercentage) / 100); test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit); } } else { // With method data update off, use the invocation counter to trigger an // OSR compilation, as done in the interpreter. if (osr_site) { - int limit = (CompileThreshold * OnStackReplacePercentage) / 100; + int limit = (int)((int64_t)CompileThreshold * OnStackReplacePercentage / 100); increment_and_test_invocation_counter(limit); } }
--- a/src/hotspot/share/opto/superword.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/superword.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -645,6 +645,10 @@ // with a different alignment were created before. for (uint i = 0; i < align_to_refs.size(); i++) { MemNode* mr = align_to_refs.at(i)->as_Mem(); + if (mr == mem_ref) { + // Skip when we are looking at same memory operation. + continue; + } if (same_velt_type(mr, mem_ref) && memory_alignment(mr, iv_adjustment) != 0) create_pack = false; @@ -846,6 +850,27 @@ return NULL; } +//------------------span_works_for_memory_size----------------------------- +static bool span_works_for_memory_size(MemNode* mem, int span, int mem_size, int offset) { + bool span_matches_memory = false; + if ((mem_size == type2aelembytes(T_BYTE) || mem_size == type2aelembytes(T_SHORT)) + && ABS(span) == type2aelembytes(T_INT)) { + // There is a mismatch on span size compared to memory. + for (DUIterator_Fast jmax, j = mem->fast_outs(jmax); j < jmax; j++) { + Node* use = mem->fast_out(j); + if (!VectorNode::is_type_transition_to_int(use)) { + return false; + } + } + // If all uses transition to integer, it means that we can successfully align even on mismatch. + return true; + } + else { + span_matches_memory = ABS(span) == mem_size; + } + return span_matches_memory && (ABS(offset) % mem_size) == 0; +} + //------------------------------ref_is_alignable--------------------------- // Can the preloop align the reference to position zero in the vector? bool SuperWord::ref_is_alignable(SWPointer& p) { @@ -862,7 +887,7 @@ int offset = p.offset_in_bytes(); // Stride one accesses are alignable if offset is aligned to memory operation size. // Offset can be unaligned when UseUnalignedAccesses is used. - if (ABS(span) == mem_size && (ABS(offset) % mem_size) == 0) { + if (span_works_for_memory_size(p.mem(), span, mem_size, offset)) { return true; } // If the initial offset from start of the object is computable, @@ -915,6 +940,28 @@ } return false; } +//---------------------------get_vw_bytes_special------------------------ +int SuperWord::get_vw_bytes_special(MemNode* s) { + // Get the vector width in bytes. + int vw = vector_width_in_bytes(s); + + // Check for special case where there is an MulAddS2I usage where short vectors are going to need combined. + BasicType btype = velt_basic_type(s); + if (type2aelembytes(btype) == 2) { + bool should_combine_adjacent = true; + for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { + Node* user = s->fast_out(i); + if (!VectorNode::is_muladds2i(user)) { + should_combine_adjacent = false; + } + } + if (should_combine_adjacent) { + vw = MIN2(Matcher::max_vector_size(btype)*type2aelembytes(btype), vw * 2); + } + } + + return vw; +} //---------------------------get_iv_adjustment--------------------------- // Calculate loop's iv adjustment for this memory ops. @@ -923,7 +970,7 @@ int offset = align_to_ref_p.offset_in_bytes(); int scale = align_to_ref_p.scale_in_bytes(); int elt_size = align_to_ref_p.memory_size(); - int vw = vector_width_in_bytes(mem_ref); + int vw = get_vw_bytes_special(mem_ref); assert(vw > 1, "sanity"); int iv_adjustment; if (scale != 0) { @@ -2303,6 +2350,12 @@ const TypePtr* atyp = n->adr_type(); vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen); vlen_in_bytes = vn->as_StoreVector()->memory_size(); + } else if (VectorNode::is_muladds2i(n)) { + assert(n->req() == 5u, "MulAddS2I should have 4 operands."); + Node* in1 = vector_opd(p, 1); + Node* in2 = vector_opd(p, 2); + vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); + vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else if (n->req() == 3 && !is_cmov_pack(p)) { // Promote operands to vector Node* in1 = NULL; @@ -2615,6 +2668,16 @@ } assert(opd_bt == in->bottom_type()->basic_type(), "all same type"); pk->add_opd(in); + if (VectorNode::is_muladds2i(pi)) { + Node* in2 = pi->in(opd_idx + 2); + assert(my_pack(in2) == NULL, "Should already have been unpacked"); + if (my_pack(in2) != NULL) { + NOT_PRODUCT(if (is_trace_loop_reverse() || TraceLoopOpts) { tty->print_cr("Should already have been unpacked"); }) + return NULL; + } + assert(opd_bt == in2->bottom_type()->basic_type(), "all same type"); + pk->add_opd(in2); + } } _igvn.register_new_node_with_optimizer(pk); _phase->set_ctrl(pk, _phase->get_ctrl(opd)); @@ -2692,6 +2755,21 @@ } return true; } + if (VectorNode::is_muladds2i(use)) { + // MulAddS2I takes shorts and produces ints - hence the special checks + // on alignment and size. + if (u_pk->size() * 2 != d_pk->size()) { + return false; + } + for (uint i = 0; i < MIN2(d_pk->size(), u_pk->size()); i++) { + Node* ui = u_pk->at(i); + Node* di = d_pk->at(i); + if (alignment(ui) != alignment(di) * 2) { + return false; + } + } + return true; + } if (u_pk->size() != d_pk->size()) return false; for (uint i = 0; i < u_pk->size(); i++) { @@ -3017,7 +3095,7 @@ NOT_PRODUCT(if(is_trace_alignment()) tty->print("SWPointer::memory_alignment: SWPointer p invalid, return bottom_align");) return bottom_align; } - int vw = vector_width_in_bytes(s); + int vw = get_vw_bytes_special(s); if (vw < 2) { NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SWPointer::memory_alignment: vector_width_in_bytes < 2, return bottom_align");) return bottom_align; // No vectors for this type
--- a/src/hotspot/share/opto/superword.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/superword.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -347,6 +347,7 @@ BasicType bt = velt_basic_type(n); return vector_width(n)*type2aelembytes(bt); } + int get_vw_bytes_special(MemNode* s); MemNode* align_to_ref() { return _align_to_ref; } void set_align_to_ref(MemNode* m) { _align_to_ref = m; }
--- a/src/hotspot/share/opto/vectornode.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/vectornode.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -196,6 +196,8 @@ case Op_StoreF: case Op_StoreD: return Op_StoreVector; + case Op_MulAddS2I: + return Op_MulAddVS2VI; default: return 0; // Unimplemented @@ -214,6 +216,25 @@ return false; } +bool VectorNode::is_type_transition_short_to_int(Node* n) { + switch (n->Opcode()) { + case Op_MulAddS2I: + return true; + } + return false; +} + +bool VectorNode::is_type_transition_to_int(Node* n) { + return is_type_transition_short_to_int(n); +} + +bool VectorNode::is_muladds2i(Node* n) { + if (n->Opcode() == Op_MulAddS2I) { + return true; + } + return false; +} + bool VectorNode::is_shift(Node* n) { switch (n->Opcode()) { case Op_LShiftI: @@ -277,6 +298,7 @@ case Op_AndI: case Op_AndL: case Op_OrI: case Op_OrL: case Op_XorI: case Op_XorL: + case Op_MulAddS2I: *start = 1; *end = 3; // 2 vector operands break; @@ -354,6 +376,8 @@ case Op_AndV: return new AndVNode(n1, n2, vt); case Op_OrV: return new OrVNode (n1, n2, vt); case Op_XorV: return new XorVNode(n1, n2, vt); + + case Op_MulAddVS2VI: return new MulAddVS2VINode(n1, n2, vt); default: fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); return NULL;
--- a/src/hotspot/share/opto/vectornode.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/opto/vectornode.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -67,6 +67,9 @@ static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); static bool is_shift(Node* n); + static bool is_type_transition_short_to_int(Node* n); + static bool is_type_transition_to_int(Node* n); + static bool is_muladds2i(Node* n); static bool is_invariant_vector(Node* n); // [Start, end) half-open range defining which operands are vectors static void vector_operands(Node* n, uint* start, uint* end); @@ -261,6 +264,14 @@ virtual int Opcode() const; }; +//------------------------------MulAddVS2VINode-------------------------------- +// Vector multiply shorts to int and add adjacent ints. +class MulAddVS2VINode : public VectorNode { + public: + MulAddVS2VINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + //------------------------------FmaVDNode-------------------------------------- // Vector multiply double class FmaVDNode : public VectorNode {
--- a/src/hotspot/share/prims/unsafe.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/prims/unsafe.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -926,11 +926,12 @@ } } UNSAFE_END -static void post_thread_park_event(EventThreadPark* event, const oop obj, jlong timeout) { +static void post_thread_park_event(EventThreadPark* event, const oop obj, jlong timeout_nanos, jlong until_epoch_millis) { assert(event != NULL, "invariant"); assert(event->should_commit(), "invariant"); event->set_parkedClass((obj != NULL) ? obj->klass() : NULL); - event->set_timeout(timeout); + event->set_timeout(timeout_nanos); + event->set_until(until_epoch_millis); event->set_address((obj != NULL) ? (u8)cast_from_oop<uintptr_t>(obj) : 0); event->commit(); } @@ -942,7 +943,16 @@ JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); if (event.should_commit()) { - post_thread_park_event(&event, thread->current_park_blocker(), time); + const oop obj = thread->current_park_blocker(); + if (time == 0) { + post_thread_park_event(&event, obj, min_jlong, min_jlong); + } else { + if (isAbsolute != 0) { + post_thread_park_event(&event, obj, min_jlong, time); + } else { + post_thread_park_event(&event, obj, time, min_jlong); + } + } } HOTSPOT_THREAD_PARK_END((uintptr_t) thread->parker()); } UNSAFE_END
--- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -145,47 +145,42 @@ } JVMFlag::Error OnStackReplacePercentageConstraintFunc(intx value, bool verbose) { - int backward_branch_limit; + int64_t max_percentage_limit = INT_MAX; + if (!ProfileInterpreter) { + max_percentage_limit = (max_percentage_limit>>InvocationCounter::count_shift); + } + max_percentage_limit = CompileThreshold == 0 ? max_percentage_limit*100 : max_percentage_limit*100/CompileThreshold; + if (ProfileInterpreter) { - if (OnStackReplacePercentage < InterpreterProfilePercentage) { + if (value < InterpreterProfilePercentage) { JVMFlag::printError(verbose, "OnStackReplacePercentage (" INTX_FORMAT ") must be " "larger than InterpreterProfilePercentage (" INTX_FORMAT ")\n", - OnStackReplacePercentage, InterpreterProfilePercentage); + value, InterpreterProfilePercentage); return JVMFlag::VIOLATES_CONSTRAINT; } - backward_branch_limit = ((CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100) - << InvocationCounter::count_shift; - - if (backward_branch_limit < 0) { + max_percentage_limit += InterpreterProfilePercentage; + if (value > max_percentage_limit) { JVMFlag::printError(verbose, - "CompileThreshold * (InterpreterProfilePercentage - OnStackReplacePercentage) / 100 = " - INTX_FORMAT " " - "must be between 0 and %d, try changing " - "CompileThreshold, InterpreterProfilePercentage, and/or OnStackReplacePercentage\n", - (CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100, - INT_MAX >> InvocationCounter::count_shift); + "OnStackReplacePercentage (" INTX_FORMAT ") must be between 0 and " INT64_FORMAT "\n", + value, + max_percentage_limit); return JVMFlag::VIOLATES_CONSTRAINT; } } else { - if (OnStackReplacePercentage < 0 ) { + if (value < 0) { JVMFlag::printError(verbose, "OnStackReplacePercentage (" INTX_FORMAT ") must be " - "non-negative\n", OnStackReplacePercentage); + "non-negative\n", value); return JVMFlag::VIOLATES_CONSTRAINT; } - backward_branch_limit = ((CompileThreshold * OnStackReplacePercentage) / 100) - << InvocationCounter::count_shift; - - if (backward_branch_limit < 0) { + if (value > max_percentage_limit) { JVMFlag::printError(verbose, - "CompileThreshold * OnStackReplacePercentage / 100 = " INTX_FORMAT " " - "must be between 0 and %d, try changing " - "CompileThreshold and/or OnStackReplacePercentage\n", - (CompileThreshold * OnStackReplacePercentage) / 100, - INT_MAX >> InvocationCounter::count_shift); + "OnStackReplacePercentage (" INTX_FORMAT ") must be between 0 and " INT64_FORMAT "\n", + value, + max_percentage_limit); return JVMFlag::VIOLATES_CONSTRAINT; } }
--- a/src/hotspot/share/runtime/thread.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/runtime/thread.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -306,15 +306,19 @@ } #endif // ASSERT - // Notify the barrier set that a thread is being created. Note that some - // threads are created before a barrier set is available. The call to - // BarrierSet::on_thread_create() for these threads is therefore deferred + // Notify the barrier set that a thread is being created. The initial + // thread is created before the barrier set is available. The call to + // BarrierSet::on_thread_create() for this thread is therefore deferred // to BarrierSet::set_barrier_set(). BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_create(this); } else { - DEBUG_ONLY(Threads::inc_threads_before_barrier_set();) +#ifdef ASSERT + static bool initial_thread_created = false; + assert(!initial_thread_created, "creating thread before barrier set"); + initial_thread_created = true; +#endif // ASSERT } } @@ -3395,7 +3399,6 @@ #ifdef ASSERT bool Threads::_vm_complete = false; -size_t Threads::_threads_before_barrier_set = 0; #endif static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {
--- a/src/hotspot/share/runtime/thread.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/runtime/thread.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -2156,7 +2156,6 @@ static int _thread_claim_parity; #ifdef ASSERT static bool _vm_complete; - static size_t _threads_before_barrier_set; #endif static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS); @@ -2226,14 +2225,6 @@ #ifdef ASSERT static bool is_vm_complete() { return _vm_complete; } - - static size_t threads_before_barrier_set() { - return _threads_before_barrier_set; - } - - static void inc_threads_before_barrier_set() { - ++_threads_before_barrier_set; - } #endif // ASSERT // Verification
--- a/src/hotspot/share/services/diagnosticCommand.cpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/services/diagnosticCommand.cpp Thu Dec 13 11:47:35 2018 -0800 @@ -37,6 +37,7 @@ #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/os.hpp" #include "services/diagnosticArgument.hpp" @@ -123,6 +124,11 @@ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags, true,false)); + // Debug on cmd (only makes sense with JVMTI since the agentlib needs it). +#if INCLUDE_JVMTI + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, false)); +#endif // INCLUDE_JVMTI + } #ifndef HAVE_EXTRA_DCMD @@ -1054,3 +1060,43 @@ int TouchedMethodsDCmd::num_arguments() { return 0; } + +#if INCLUDE_JVMTI +extern "C" typedef char const* (JNICALL *debugInit_startDebuggingViaCommandPtr)(JNIEnv* env, jthread thread, char const** transport_name, + char const** address, jboolean* first_start); +static debugInit_startDebuggingViaCommandPtr dvc_start_ptr = NULL; + +DebugOnCmdStartDCmd::DebugOnCmdStartDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap) { +} + +void DebugOnCmdStartDCmd::execute(DCmdSource source, TRAPS) { + char const* transport = NULL; + char const* addr = NULL; + jboolean is_first_start = JNI_FALSE; + JavaThread* thread = (JavaThread*) THREAD; + jthread jt = JNIHandles::make_local(thread->threadObj()); + ThreadToNativeFromVM ttn(thread); + const char *error = "Could not find jdwp agent."; + + if (!dvc_start_ptr) { + for (AgentLibrary* agent = Arguments::agents(); agent != NULL; agent = agent->next()) { + if ((strcmp("jdwp", agent->name()) == 0) && (dvc_start_ptr == NULL)) { + char const* func = "debugInit_startDebuggingViaCommand"; + dvc_start_ptr = (debugInit_startDebuggingViaCommandPtr) os::find_agent_function(agent, false, &func, 1); + } + } + } + + if (dvc_start_ptr) { + error = dvc_start_ptr(thread->jni_environment(), jt, &transport, &addr, &is_first_start); + } + + if (error != NULL) { + output()->print_cr("Debugging has not been started: %s", error); + } else { + output()->print_cr(is_first_start ? "Debugging has been started." : "Debugging is already active."); + output()->print_cr("Transport : %s", transport ? transport : "#unknown"); + output()->print_cr("Address : %s", addr ? addr : "#unknown"); + } +} +#endif // INCLUDE_JVMTI
--- a/src/hotspot/share/services/diagnosticCommand.hpp Thu Sep 13 01:49:48 2018 +0200 +++ b/src/hotspot/share/services/diagnosticCommand.hpp Thu Dec 13 11:47:35 2018 -0800 @@ -867,4 +867,26 @@ virtual void execute(DCmdSource source, TRAPS); }; +#if INCLUDE_JVMTI +class DebugOnCmdStartDCmd : public DCmdWithParser { +public: + DebugOnCmdStartDCmd(outputStream* output, bool heap); + static const char* name() { + return "VM.start_java_debugging"; + } + static const char* description() { + return "Starts up the Java debugging if the jdwp agentlib was enabled with the option onjcmd=y."; + } + static const char* impact() { + return "High: Switches the VM into Java debug mode."; + } + static const JavaPermission permission() { + JavaPermission p = { "java.lang.management.ManagementPermission", "monitor", NULL }; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; +#endif // INCLUDE_JVMTI + #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java Thu Sep 13 01:49:48 2018 +0200 +++ b/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java Thu Dec 13 11:47:35 2018 -0800 @@ -124,10 +124,10 @@ } - /* subkeyH and state are stored in long[] for GHASH intrinsic use */ + /* subkeyHtbl and state are stored in long[] for GHASH intrinsic use */ - // hash subkey H; should not change after the object has been constructed - private final long[] subkeyH; + // hashtable subkeyHtbl; holds 2*9 powers of subkeyH computed using carry-less multiplication + private long[] subkeyHtbl; // buffer for storing hash private final long[] state; @@ -149,9 +149,9 @@ throw new ProviderException("Internal error"); } state = new long[2]; - this.subkeyH = new long[2]; - this.subkeyH[0] = getLong(subkeyH, 0); - this.subkeyH[1] = getLong(subkeyH, 8); + subkeyHtbl = new long[2*9]; + subkeyHtbl[0] = getLong(subkeyH, 0); + subkeyHtbl[1] = getLong(subkeyH, 8); } /** @@ -194,8 +194,8 @@ if (inLen == 0) { return; } - ghashRangeCheck(in, inOfs, inLen, state, subkeyH); - processBlocks(in, inOfs, inLen/AES_BLOCK_SIZE, state, subkeyH); + ghashRangeCheck(in, inOfs, inLen, state, subkeyHtbl); + processBlocks(in, inOfs, inLen/AES_BLOCK_SIZE, state, subkeyHtbl); } private static void ghashRangeCheck(byte[] in, int inOfs, int inLen, long[] st, long[] subH) { @@ -219,8 +219,8 @@ throw new RuntimeException("internal state has invalid length: " + st.length); } - if (subH.length != 2) { - throw new RuntimeException("internal subkeyH has invalid length: " + + if (subH.length != 18) { + throw new RuntimeException("internal subkeyHtbl has invalid length: " + subH.length); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java Thu Dec 13 11:47:35 2018 -0800 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import java.util.Arrays; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import java.security.*; +import java.security.spec.*; + +/** + * This is an implementation of the HMAC algorithms as defined + * in PKCS#12 v1.1 standard (see RFC 7292 Appendix B.4). + * + * @author Valerie Peng + */ +abstract class HmacPKCS12PBECore extends HmacCore { + + public static final class HmacPKCS12PBE_SHA1 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA1() throws NoSuchAlgorithmException { + super("SHA1", 64); + } + } + + public static final class HmacPKCS12PBE_SHA224 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA224() throws NoSuchAlgorithmException { + super("SHA-224", 64); + } + } + + public static final class HmacPKCS12PBE_SHA256 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA256() throws NoSuchAlgorithmException { + super("SHA-256", 64); + } + } + + public static final class HmacPKCS12PBE_SHA384 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA384() throws NoSuchAlgorithmException { + super("SHA-384", 128); + } + } + + public static final class HmacPKCS12PBE_SHA512 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA512() throws NoSuchAlgorithmException { + super("SHA-512", 128); + } + } + + public static final class HmacPKCS12PBE_SHA512_224 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA512_224() throws NoSuchAlgorithmException { + super("SHA-512/224", 128); + } + } + + public static final class HmacPKCS12PBE_SHA512_256 extends HmacPKCS12PBECore { + public HmacPKCS12PBE_SHA512_256() throws NoSuchAlgorithmException { + super("SHA-512/256", 128); + } + } + + private final String algorithm; + private final int bl; + + /** + * Standard constructor, creates a new HmacSHA1 instance. + */ + public HmacPKCS12PBECore(String algorithm, int bl) throws NoSuchAlgorithmException { + super(algorithm, bl); + this.algorithm = algorithm; + this.bl = bl; + } + + /** + * Initializes the HMAC with the given secret key and algorithm parameters. + * + * @param key the secret key. + * @param params the algorithm parameters. + * + * @exception InvalidKeyException if the given key is inappropriate for + * initializing this MAC. + * @exception InvalidAlgorithmParameterException if the given algorithm + * parameters are inappropriate for this MAC. + */ + protected void engineInit(Key key, AlgorithmParameterSpec params) + throws InvalidKeyException, InvalidAlgorithmParameterException { + char[] passwdChars; + byte[] salt = null; + int iCount = 0; + if (key instanceof javax.crypto.interfaces.PBEKey) { + javax.crypto.interfaces.PBEKey pbeKey = + (javax.crypto.interfaces.PBEKey) key; + passwdChars = pbeKey.getPassword(); + salt = pbeKey.getSalt(); // maybe null if unspecified + iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified + } else if (key instanceof SecretKey) { + byte[] passwdBytes; + if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) || + (passwdBytes = key.getEncoded()) == null) { + throw new InvalidKeyException("Missing password"); + } + passwdChars = new char[passwdBytes.length]; + for (int i=0; i<passwdChars.length; i++) { + passwdChars[i] = (char) (passwdBytes[i] & 0x7f); + } + Arrays.fill(passwdBytes, (byte)0x00); + } else { + throw new InvalidKeyException("SecretKey of PBE type required"); + } + + byte[] derivedKey; + try { + if (params == null) { + // should not auto-generate default values since current + // javax.crypto.Mac api does not have any method for caller to + // retrieve the generated defaults. + if ((salt == null) || (iCount == 0)) { + throw new InvalidAlgorithmParameterException + ("PBEParameterSpec required for salt and iteration count"); + } + } else if (!(params instanceof PBEParameterSpec)) { + throw new InvalidAlgorithmParameterException + ("PBEParameterSpec type required"); + } else { + PBEParameterSpec pbeParams = (PBEParameterSpec) params; + // make sure the parameter values are consistent + if (salt != null) { + if (!Arrays.equals(salt, pbeParams.getSalt())) { + throw new InvalidAlgorithmParameterException + ("Inconsistent value of salt between key and params"); + } + } else { + salt = pbeParams.getSalt(); + } + if (iCount != 0) { + if (iCount != pbeParams.getIterationCount()) { + throw new InvalidAlgorithmParameterException + ("Different iteration count between key and params"); + } + } else { + iCount = pbeParams.getIterationCount(); + } + } + // For security purpose, we need to enforce a minimum length + // for salt; just require the minimum salt length to be 8-byte + // which is what PKCS#5 recommends and openssl does. + if (salt.length < 8) { + throw new InvalidAlgorithmParameterException + ("Salt must be at least 8 bytes long"); + } + if (iCount <= 0) { + throw new InvalidAlgorithmParameterException + ("IterationCount must be a positive number"); + } + derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt, + iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY, + algorithm, bl); + } finally { + Arrays.fill(passwdChars, '\0'); + } + SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1"); + super.engineInit(cipherKey, null); + } +}
--- a/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java Thu Sep 13 01:49:48 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.crypto.provider; - -import java.util.Arrays; -import java.nio.ByteBuffer; - -import javax.crypto.MacSpi; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import javax.crypto.spec.PBEParameterSpec; -import java.security.*; -import java.security.spec.*; - -/** - * This is an implementation of the HMAC-PBESHA1 algorithm as defined - * in PKCS#12 v1.0 standard. - * - * @author Valerie Peng - */ -public final class HmacPKCS12PBESHA1 extends HmacCore { - - /** - * Standard constructor, creates a new HmacSHA1 instance. - */ - public HmacPKCS12PBESHA1() throws NoSuchAlgorithmException { - super("SHA1", 64); - } - - /** - * Initializes the HMAC with the given secret key and algorithm parameters. - * - * @param key the secret key. - * @param params the algorithm parameters. - * - * @exception InvalidKeyException if the given key is inappropriate for - * initializing this MAC. - * @exception InvalidAlgorithmParameterException if the given algorithm - * parameters are inappropriate for this MAC. - */ - protected void engineInit(Key key, AlgorithmParameterSpec params) - throws InvalidKeyException, InvalidAlgorithmParameterException { - char[] passwdChars; - byte[] salt = null; - int iCount = 0; - if (key instanceof javax.crypto.interfaces.PBEKey) { - javax.crypto.interfaces.PBEKey pbeKey = - (javax.crypto.interfaces.PBEKey) key; - passwdChars = pbeKey.getPassword(); - salt = pbeKey.getSalt(); // maybe null if unspecified - iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified - } else if (key instanceof SecretKey) { - byte[] passwdBytes; - if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) || - (passwdBytes = key.getEncoded()) == null) { - throw new InvalidKeyException("Missing password"); - } - passwdChars = new char[passwdBytes.length]; - for (int i=0; i<passwdChars.length; i++) { - passwdChars[i] = (char) (passwdBytes[i] & 0x7f); - } - Arrays.fill(passwdBytes, (byte)0x00); - } else { - throw new InvalidKeyException("SecretKey of PBE type required"); - } - - byte[] derivedKey; - try { - if (params == null) { - // should not auto-generate default values since current - // javax.crypto.Mac api does not have any method for caller to - // retrieve the generated defaults. - if ((salt == null) || (iCount == 0)) { - throw new InvalidAlgorithmParameterException - ("PBEParameterSpec required for salt and iteration count"); - } - } else if (!(params instanceof PBEParameterSpec)) { - throw new InvalidAlgorithmParameterException - ("PBEParameterSpec type required"); - } else { - PBEParameterSpec pbeParams = (PBEParameterSpec) params; - // make sure the parameter values are consistent - if (salt != null) { - if (!Arrays.equals(salt, pbeParams.getSalt())) { - throw new InvalidAlgorithmParameterException - ("Inconsistent value of salt between key and params"); - } - } else { - salt = pbeParams.getSalt(); - } - if (iCount != 0) { - if (iCount != pbeParams.getIterationCount()) { - throw new InvalidAlgorithmParameterException - ("Different iteration count between key and params"); - } - } else { - iCount = pbeParams.getIterationCount(); - } - } - // For security purpose, we need to enforce a minimum length - // for salt; just require the minimum salt length to be 8-byte - // which is what PKCS#5 recommends and openssl does. - if (salt.length < 8) { - throw new InvalidAlgorithmParameterException - ("Salt must be at least 8 bytes long"); - } - if (iCount <= 0) { - throw new InvalidAlgorithmParameterException - ("IterationCount must be a positive number"); - } - derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt, - iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY); - } finally { - Arrays.fill(passwdChars, '\0'); - } - SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1"); - super.engineInit(cipherKey, null); - } -}
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Thu Sep 13 01:49:48 2018 +0200 +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Thu Dec 13 11:47:35 2018 -0800 @@ -314,41 +314,48 @@ + "not an ASN.1 OCTET STRING tag"); } iCount = pBKDF2_params.data.getInteger(); + + DerValue prf = null; // keyLength INTEGER (1..MAX) OPTIONAL, if (pBKDF2_params.data.available() > 0) { DerValue keyLength = pBKDF2_params.data.getDerValue(); if (keyLength.tag == DerValue.tag_Integer) { keysize = keyLength.getInteger() * 8; // keysize (in bits) + } else { + // Should be the prf + prf = keyLength; } } // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 String kdfAlgo = "HmacSHA1"; - if (pBKDF2_params.data.available() > 0) { - if (pBKDF2_params.tag == DerValue.tag_Sequence) { - DerValue prf = pBKDF2_params.data.getDerValue(); - kdfAlgo_OID = prf.data.getOID(); - if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA1"; - } else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA224"; - } else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA256"; - } else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA384"; - } else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA512"; - } else { + if (prf == null) { + if (pBKDF2_params.data.available() > 0) { + prf = pBKDF2_params.data.getDerValue(); + } + } + if (prf != null) { + kdfAlgo_OID = prf.data.getOID(); + if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA1"; + } else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA224"; + } else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA256"; + } else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA384"; + } else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA512"; + } else { + throw new IOException("PBE parameter parsing error: " + + "expecting the object identifier for a HmacSHA key " + + "derivation function"); + } + if (prf.data.available() != 0) { + // parameter is 'NULL' for all HmacSHA KDFs + DerValue parameter = prf.data.getDerValue(); + if (parameter.tag != DerValue.tag_Null) { throw new IOException("PBE parameter parsing error: " - + "expecting the object identifier for a HmacSHA key " - + "derivation function"); - } - if (prf.data.available() != 0) { - // parameter is 'NULL' for all HmacSHA KDFs - DerValue parameter = prf.data.getDerValue(); - if (parameter.tag != DerValue.tag_Null) { - throw new IOException("PBE parameter parsing error: " - + "not an ASN.1 NULL tag"); - } + + "not an ASN.1 NULL tag"); } } }
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Thu Sep 13 01:49:48 2018 +0200 +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Thu Dec 13 11:47:35 2018 -0800 @@ -28,8 +28,12 @@ import java.security.AccessController; import java.security.Provider; import java.security.SecureRandom; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.List; import static sun.security.util.SecurityConstants.PROVIDER_VER; - +import static sun.security.provider.SunEntries.createAliases; +import static sun.security.provider.SunEntries.createAliasesWithOid; /** * The "SunJCE" Cryptographic Service Provider. @@ -81,16 +85,6 @@ "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " + "Diffie-Hellman, HMAC, ChaCha20)"; - private static final String OID_PKCS12_RC4_128 = "1.2.840.113549.1.12.1.1"; - private static final String OID_PKCS12_RC4_40 = "1.2.840.113549.1.12.1.2"; - private static final String OID_PKCS12_DESede = "1.2.840.113549.1.12.1.3"; - private static final String OID_PKCS12_RC2_128 = "1.2.840.113549.1.12.1.5"; - private static final String OID_PKCS12_RC2_40 = "1.2.840.113549.1.12.1.6"; - private static final String OID_PKCS5_MD5_DES = "1.2.840.113549.1.5.3"; - private static final String OID_PKCS5_PBKDF2 = "1.2.840.113549.1.5.12"; - private static final String OID_PKCS5_PBES2 = "1.2.840.113549.1.5.13"; - private static final String OID_PKCS3 = "1.2.840.113549.1.3.1"; - /* Are we debugging? -- for developers */ static final boolean debug = false; @@ -105,10 +99,105 @@ } static SecureRandom getRandom() { return SecureRandomHolder.RANDOM; } + private void ps(String type, String algo, String cn, + List<String> aliases, HashMap<String, String> attrs) { + putService(new Provider.Service(this, type, algo, cn, aliases, attrs)); + } + public SunJCE() { /* We are the "SunJCE" provider */ super("SunJCE", PROVIDER_VER, info); + // if there is no security manager installed, put directly into + // the provider + if (System.getSecurityManager() == null) { + putEntries(); + } else { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + putEntries(); + return null; + } + }); + } + if (instance == null) { + instance = this; + } + } + + void putEntries() { + // common aliases and oids + List<String> aesAliases = createAliases("Rijndael"); + List<String> desEdeAliases = createAliases("TripleDES"); + List<String> arcFourAliases = createAliases("RC4"); + List<String> sunTlsMSAliases = createAliases( + "SunTls12MasterSecret", "SunTlsExtendedMasterSecret" + ); + List<String> sunTlsKMAliases = createAliases("SunTls12KeyMaterial"); + List<String> sunTlsRsaPMSAliases = createAliases("SunTls12RsaPremasterSecret"); + + String aes128Oid = "2.16.840.1.101.3.4.1."; + String aes192Oid = "2.16.840.1.101.3.4.1.2"; + String aes256Oid = "2.16.840.1.101.3.4.1.4"; + + List<String> pkcs12RC4_128Aliases = + createAliasesWithOid("1.2.840.113549.1.12.1.1"); + + List<String> pkcs12RC4_40Aliases = + createAliasesWithOid("1.2.840.113549.1.12.1.2"); + + List<String> pkcs12DESedeAliases = + createAliasesWithOid("1.2.840.113549.1.12.1.3"); + + List<String> pkcs12RC2_128Aliases = + createAliasesWithOid("1.2.840.113549.1.12.1.5"); + + List<String> pkcs12RC2_40Aliases = + createAliasesWithOid("1.2.840.113549.1.12.1.6"); + + List<String> pkcs5MD5_DESAliases = + createAliasesWithOid("1.2.840.113549.1.5.3", "PBE"); + + List<String> pkcs5PBKDF2Aliases = + createAliasesWithOid("1.2.840.113549.1.5.12"); + + List<String> pkcs5PBES2Aliases = + createAliasesWithOid("1.2.840.113549.1.5.13"); + + List<String> diffieHellmanAliases = + createAliasesWithOid("1.2.840.113549.1.3.1", "DH"); + + List<String> chachaPolyAliases = + createAliasesWithOid("1.2.840.113549.1.9.16.3.18"); + + String macOidBase = "1.2.840.113549.2."; + List<String> macSHA1Aliases = createAliasesWithOid(macOidBase + "7"); + List<String> macSHA224Aliases = createAliasesWithOid(macOidBase + "8"); + List<String> macSHA256Aliases = createAliasesWithOid(macOidBase + "9"); + List<String> macSHA384Aliases = createAliasesWithOid(macOidBase + "10"); + List<String> macSHA512Aliases = createAliasesWithOid(macOidBase + "11"); + + // reuse attribute map and reset before each reuse + HashMap<String, String> attrs = new HashMap<>(3); + attrs.put("SupportedModes", "ECB"); + attrs.put("SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPPADDING" + + "|OAEPWITHMD5ANDMGF1PADDING" + + "|OAEPWITHSHA1ANDMGF1PADDING" + + "|OAEPWITHSHA-1ANDMGF1PADDING" + + "|OAEPWITHSHA-224ANDMGF1PADDING" + + "|OAEPWITHSHA-256ANDMGF1PADDING" + + "|OAEPWITHSHA-384ANDMGF1PADDING" + + "|OAEPWITHSHA-512ANDMGF1PADDING" + + "|OAEPWITHSHA-512/224ANDMGF1PADDING" + + "|OAEPWITHSHA-512/256ANDMGF1PADDING"); + attrs.put("SupportedKeyClasses", + "java.security.interfaces.RSAPublicKey" + + "|java.security.interfaces.RSAPrivateKey"); + ps("Cipher", "RSA", + "com.sun.crypto.provider.RSACipher", null, attrs); + + // common block cipher modes, pads final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" + "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" + "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64"; @@ -117,699 +206,557 @@ "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128"; final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING"; - AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { + attrs.clear(); + attrs.put("SupportedModes", BLOCK_MODES); + attrs.put("SupportedPaddings", BLOCK_PADS); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "DES", + "com.sun.crypto.provider.DESCipher", null, attrs); + ps("Cipher", "DESede", "com.sun.crypto.provider.DESedeCipher", + desEdeAliases, attrs); + ps("Cipher", "Blowfish", + "com.sun.crypto.provider.BlowfishCipher", null, attrs); - /* - * Cipher engines - */ - put("Cipher.RSA", "com.sun.crypto.provider.RSACipher"); - put("Cipher.RSA SupportedModes", "ECB"); - put("Cipher.RSA SupportedPaddings", - "NOPADDING|PKCS1PADDING|OAEPPADDING" - + "|OAEPWITHMD5ANDMGF1PADDING" - + "|OAEPWITHSHA1ANDMGF1PADDING" - + "|OAEPWITHSHA-1ANDMGF1PADDING" - + "|OAEPWITHSHA-224ANDMGF1PADDING" - + "|OAEPWITHSHA-256ANDMGF1PADDING" - + "|OAEPWITHSHA-384ANDMGF1PADDING" - + "|OAEPWITHSHA-512ANDMGF1PADDING" - + "|OAEPWITHSHA-512/224ANDMGF1PADDING" - + "|OAEPWITHSHA-512/256ANDMGF1PADDING"); - put("Cipher.RSA SupportedKeyClasses", - "java.security.interfaces.RSAPublicKey" + - "|java.security.interfaces.RSAPrivateKey"); + ps("Cipher", "RC2", + "com.sun.crypto.provider.RC2Cipher", null, attrs); - put("Cipher.DES", "com.sun.crypto.provider.DESCipher"); - put("Cipher.DES SupportedModes", BLOCK_MODES); - put("Cipher.DES SupportedPaddings", BLOCK_PADS); - put("Cipher.DES SupportedKeyFormats", "RAW"); + attrs.clear(); + attrs.put("SupportedModes", BLOCK_MODES128); + attrs.put("SupportedPaddings", BLOCK_PADS); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "AES", "com.sun.crypto.provider.AESCipher$General", + aesAliases, attrs); - put("Cipher.DESede", "com.sun.crypto.provider.DESedeCipher"); - put("Alg.Alias.Cipher.TripleDES", "DESede"); - put("Cipher.DESede SupportedModes", BLOCK_MODES); - put("Cipher.DESede SupportedPaddings", BLOCK_PADS); - put("Cipher.DESede SupportedKeyFormats", "RAW"); + attrs.clear(); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "AES_128/ECB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding", + createAliasesWithOid(aes128Oid+"1"), attrs); + ps("Cipher", "AES_128/CBC/NoPadding", + "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding", + createAliasesWithOid(aes128Oid+"2"), attrs); + ps("Cipher", "AES_128/OFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding", + createAliasesWithOid(aes128Oid+"3"), attrs); + ps("Cipher", "AES_128/CFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding", + createAliasesWithOid(aes128Oid+"4"), attrs); + ps("Cipher", "AES_128/GCM/NoPadding", + "com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding", + createAliasesWithOid(aes128Oid+"6"), attrs); - put("Cipher.DESedeWrap", - "com.sun.crypto.provider.DESedeWrapCipher"); - put("Cipher.DESedeWrap SupportedModes", "CBC"); - put("Cipher.DESedeWrap SupportedPaddings", "NOPADDING"); - put("Cipher.DESedeWrap SupportedKeyFormats", "RAW"); + ps("Cipher", "AES_192/ECB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding", + createAliasesWithOid(aes192Oid+"1"), attrs); + ps("Cipher", "AES_192/CBC/NoPadding", + "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding", + createAliasesWithOid(aes192Oid+"2"), attrs); + ps("Cipher", "AES_192/OFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding", + createAliasesWithOid(aes192Oid+"3"), attrs); + ps("Cipher", "AES_192/CFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding", + createAliasesWithOid(aes192Oid+"4"), attrs); + ps("Cipher", "AES_192/GCM/NoPadding", + "com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding", + createAliasesWithOid(aes192Oid+"6"), attrs); - // PBES1 + ps("Cipher", "AES_256/ECB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding", + createAliasesWithOid(aes256Oid+"1"), attrs); + ps("Cipher", "AES_256/CBC/NoPadding", + "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding", + createAliasesWithOid(aes256Oid+"2"), attrs); + ps("Cipher", "AES_256/OFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding", + createAliasesWithOid(aes256Oid+"3"), attrs); + ps("Cipher", "AES_256/CFB/NoPadding", + "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding", + createAliasesWithOid(aes256Oid+"4"), attrs); + ps("Cipher", "AES_256/GCM/NoPadding", + "com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding", + createAliasesWithOid(aes256Oid+"6"), attrs); - put("Cipher.PBEWithMD5AndDES", - "com.sun.crypto.provider.PBEWithMD5AndDESCipher"); - put("Alg.Alias.Cipher.OID."+OID_PKCS5_MD5_DES, - "PBEWithMD5AndDES"); - put("Alg.Alias.Cipher."+OID_PKCS5_MD5_DES, - "PBEWithMD5AndDES"); + attrs.clear(); + attrs.put("SupportedModes", "CBC"); + attrs.put("SupportedPaddings", "NOPADDING"); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "DESedeWrap", + "com.sun.crypto.provider.DESedeWrapCipher", null, attrs); - put("Cipher.PBEWithMD5AndTripleDES", - "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher"); + attrs.clear(); + attrs.put("SupportedModes", "ECB"); + attrs.put("SupportedPaddings", "NOPADDING"); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "ARCFOUR", "com.sun.crypto.provider.ARCFOURCipher", + arcFourAliases, attrs); + ps("Cipher", "AESWrap", "com.sun.crypto.provider.AESWrapCipher$General", + null, attrs); + ps("Cipher", "AESWrap_128", + "com.sun.crypto.provider.AESWrapCipher$AES128", + createAliasesWithOid(aes128Oid+"5"), attrs); + ps("Cipher", "AESWrap_192", + "com.sun.crypto.provider.AESWrapCipher$AES192", + createAliasesWithOid(aes192Oid+"5"), attrs); + ps("Cipher", "AESWrap_256", + "com.sun.crypto.provider.AESWrapCipher$AES256", + createAliasesWithOid(aes256Oid+"5"), attrs); - put("Cipher.PBEWithSHA1AndDESede", - "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndDESede"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); - put("Alg.Alias.Cipher." + OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); + attrs.clear(); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Cipher", "ChaCha20", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only", + null, attrs); + ps("Cipher", "ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + chachaPolyAliases, attrs); - put("Cipher.PBEWithSHA1AndRC2_40", - "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndRC2_40"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC2_40, - "PBEWithSHA1AndRC2_40"); - put("Alg.Alias.Cipher." + OID_PKCS12_RC2_40, - "PBEWithSHA1AndRC2_40"); + // PBES1 + ps("Cipher", "PBEWithMD5AndDES", + "com.sun.crypto.provider.PBEWithMD5AndDESCipher", + pkcs5MD5_DESAliases, null); + ps("Cipher", "PBEWithMD5AndTripleDES", + "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher", + null, null); + ps("Cipher", "PBEWithSHA1AndDESede", + "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede", + pkcs12DESedeAliases, null); + ps("Cipher", "PBEWithSHA1AndRC2_40", + "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40", + pkcs12RC2_40Aliases, null); + ps("Cipher", "PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_128", + pkcs12RC2_128Aliases, null); + ps("Cipher", "PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_40", + pkcs12RC4_40Aliases, null); - put("Cipher.PBEWithSHA1AndRC2_128", - "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndRC2_128"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC2_128, - "PBEWithSHA1AndRC2_128"); - put("Alg.Alias.Cipher." + OID_PKCS12_RC2_128, - "PBEWithSHA1AndRC2_128"); + ps("Cipher", "PBEWithSHA1AndRC4_128", + "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_128", + pkcs12RC4_128Aliases, null); - put("Cipher.PBEWithSHA1AndRC4_40", - "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndRC4_40"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_40, - "PBEWithSHA1AndRC4_40"); - put("Alg.Alias.Cipher." + OID_PKCS12_RC4_40, - "PBEWithSHA1AndRC4_40"); + // PBES2 + ps("Cipher", "PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128", + null, null); - put("Cipher.PBEWithSHA1AndRC4_128", - "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndRC4_128"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_128, - "PBEWithSHA1AndRC4_128"); - put("Alg.Alias.Cipher." + OID_PKCS12_RC4_128, - "PBEWithSHA1AndRC4_128"); + ps("Cipher", "PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_128", + null, null); - //PBES2 + ps("Cipher", "PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_128", + null, null); - put("Cipher.PBEWithHmacSHA1AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128"); + ps("Cipher", "PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_128", + null, null); - put("Cipher.PBEWithHmacSHA224AndAES_128", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA224AndAES_128"); + ps("Cipher", "PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_128", + null, null); - put("Cipher.PBEWithHmacSHA256AndAES_128", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA256AndAES_128"); + ps("Cipher", "PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256", + null, null); - put("Cipher.PBEWithHmacSHA384AndAES_128", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA384AndAES_128"); + ps("Cipher", "PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_256", + null, null); - put("Cipher.PBEWithHmacSHA512AndAES_128", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA512AndAES_128"); + ps("Cipher", "PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256", + null, null); - put("Cipher.PBEWithHmacSHA1AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256"); + ps("Cipher", "PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_256", + null, null); - put("Cipher.PBEWithHmacSHA224AndAES_256", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA224AndAES_256"); + ps("Cipher", "PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_256", + null, null); - put("Cipher.PBEWithHmacSHA256AndAES_256", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA256AndAES_256"); + /* + * Key(pair) Generator engines + */ + ps("KeyGenerator", "DES", + "com.sun.crypto.provider.DESKeyGenerator", + null, null); + ps("KeyGenerator", "DESede", + "com.sun.crypto.provider.DESedeKeyGenerator", + desEdeAliases, null); + ps("KeyGenerator", "Blowfish", + "com.sun.crypto.provider.BlowfishKeyGenerator", + null, null); + ps("KeyGenerator", "AES", + "com.sun.crypto.provider.AESKeyGenerator", + aesAliases, null); + ps("KeyGenerator", "RC2", + "com.sun.crypto.provider.KeyGeneratorCore$RC2KeyGenerator", + null, null); + ps("KeyGenerator", "ARCFOUR", + "com.sun.crypto.provider.KeyGeneratorCore$ARCFOURKeyGenerator", + arcFourAliases, null); + ps("KeyGenerator", "ChaCha20", + "com.sun.crypto.provider.KeyGeneratorCore$ChaCha20KeyGenerator", + null, null); + ps("KeyGenerator", "HmacMD5", + "com.sun.crypto.provider.HmacMD5KeyGenerator", + null, null); - put("Cipher.PBEWithHmacSHA384AndAES_256", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA384AndAES_256"); + ps("KeyGenerator", "HmacSHA1", + "com.sun.crypto.provider.HmacSHA1KeyGenerator", + macSHA1Aliases, null); + ps("KeyGenerator", "HmacSHA224", + "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA224", + macSHA224Aliases, null); + ps("KeyGenerator", "HmacSHA256", + "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA256", + macSHA256Aliases, null); + ps("KeyGenerator", "HmacSHA384", + "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA384", + macSHA384Aliases, null); + ps("KeyGenerator", "HmacSHA512", + "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA512", + macSHA512Aliases, null); - put("Cipher.PBEWithHmacSHA512AndAES_256", - "com.sun.crypto.provider.PBES2Core$" + - "HmacSHA512AndAES_256"); + ps("KeyPairGenerator", "DiffieHellman", + "com.sun.crypto.provider.DHKeyPairGenerator", + diffieHellmanAliases, null); - put("Cipher.Blowfish", - "com.sun.crypto.provider.BlowfishCipher"); - put("Cipher.Blowfish SupportedModes", BLOCK_MODES); - put("Cipher.Blowfish SupportedPaddings", BLOCK_PADS); - put("Cipher.Blowfish SupportedKeyFormats", "RAW"); + /* + * Algorithm parameter generation engines + */ + ps("AlgorithmParameterGenerator", + "DiffieHellman", "com.sun.crypto.provider.DHParameterGenerator", + diffieHellmanAliases, null); - put("Cipher.AES", "com.sun.crypto.provider.AESCipher$General"); - put("Alg.Alias.Cipher.Rijndael", "AES"); - put("Cipher.AES SupportedModes", BLOCK_MODES128); - put("Cipher.AES SupportedPaddings", BLOCK_PADS); - put("Cipher.AES SupportedKeyFormats", "RAW"); + /* + * Key Agreement engines + */ + attrs.clear(); + attrs.put("SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey" + + "|javax.crypto.interfaces.DHPrivateKey"); + ps("KeyAgreement", "DiffieHellman", + "com.sun.crypto.provider.DHKeyAgreement", + diffieHellmanAliases, attrs); - put("Cipher.AES_128/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding"); - put("Cipher.AES_128/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding"); - put("Cipher.AES_128/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding"); - put("Cipher.AES_128/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding"); - put("Cipher.AES_128/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding"); + /* + * Algorithm Parameter engines + */ + ps("AlgorithmParameters", "DiffieHellman", + "com.sun.crypto.provider.DHParameters", + diffieHellmanAliases, null); - put("Cipher.AES_192/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding"); - put("Cipher.AES_192/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding"); - put("Cipher.AES_192/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding"); - put("Cipher.AES_192/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding"); - put("Cipher.AES_192/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding"); + ps("AlgorithmParameters", "DES", + "com.sun.crypto.provider.DESParameters", + null, null); - put("Cipher.AES_256/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding"); - put("Cipher.AES_256/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding"); - put("Cipher.AES_256/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding"); - put("Cipher.AES_256/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding"); - put("Cipher.AES_256/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding"); + ps("AlgorithmParameters", "DESede", + "com.sun.crypto.provider.DESedeParameters", + desEdeAliases, null); - put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher$General"); - put("Cipher.AESWrap SupportedModes", "ECB"); - put("Cipher.AESWrap SupportedPaddings", "NOPADDING"); - put("Cipher.AESWrap SupportedKeyFormats", "RAW"); + ps("AlgorithmParameters", "PBEWithMD5AndDES", + "com.sun.crypto.provider.PBEParameters", + pkcs5MD5_DESAliases, null); - put("Cipher.AESWrap_128", "com.sun.crypto.provider.AESWrapCipher$AES128"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.5", "AESWrap_128"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.5", "AESWrap_128"); - put("Cipher.AESWrap_192", "com.sun.crypto.provider.AESWrapCipher$AES192"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.25", "AESWrap_192"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.25", "AESWrap_192"); - put("Cipher.AESWrap_256", "com.sun.crypto.provider.AESWrapCipher$AES256"); - put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.45", "AESWrap_256"); - put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.45", "AESWrap_256"); + ps("AlgorithmParameters", "PBEWithMD5AndTripleDES", + "com.sun.crypto.provider.PBEParameters", + null, null); - put("Cipher.RC2", - "com.sun.crypto.provider.RC2Cipher"); - put("Cipher.RC2 SupportedModes", BLOCK_MODES); - put("Cipher.RC2 SupportedPaddings", BLOCK_PADS); - put("Cipher.RC2 SupportedKeyFormats", "RAW"); + ps("AlgorithmParameters", "PBEWithSHA1AndDESede", + "com.sun.crypto.provider.PBEParameters", + pkcs12DESedeAliases, null); - put("Cipher.ARCFOUR", - "com.sun.crypto.provider.ARCFOURCipher"); - put("Alg.Alias.Cipher.RC4", "ARCFOUR"); - put("Cipher.ARCFOUR SupportedModes", "ECB"); - put("Cipher.ARCFOUR SupportedPaddings", "NOPADDING"); - put("Cipher.ARCFOUR SupportedKeyFormats", "RAW"); + ps("AlgorithmParameters", "PBEWithSHA1AndRC2_40", + "com.sun.crypto.provider.PBEParameters", + pkcs12RC2_40Aliases, null); - put("Cipher.ChaCha20", - "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only"); - put("Cipher.ChaCha20 SupportedKeyFormats", "RAW"); - put("Cipher.ChaCha20-Poly1305", - "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305"); - put("Cipher.ChaCha20-Poly1305 SupportedKeyFormats", "RAW"); - put("Alg.Alias.Cipher.1.2.840.113549.1.9.16.3.18", "ChaCha20-Poly1305"); - put("Alg.Alias.Cipher.OID.1.2.840.113549.1.9.16.3.18", "ChaCha20-Poly1305"); + ps("AlgorithmParameters", "PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PBEParameters", + pkcs12RC2_128Aliases, null); - /* - * Key(pair) Generator engines - */ - put("KeyGenerator.DES", - "com.sun.crypto.provider.DESKeyGenerator"); + ps("AlgorithmParameters", "PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PBEParameters", + pkcs12RC4_40Aliases, null); - put("KeyGenerator.DESede", - "com.sun.crypto.provider.DESedeKeyGenerator"); - put("Alg.Alias.KeyGenerator.TripleDES", "DESede"); + ps("AlgorithmParameters", "PBEWithSHA1AndRC4_128", + "com.sun.crypto.provider.PBEParameters", + pkcs12RC4_128Aliases, null); - put("KeyGenerator.Blowfish", - "com.sun.crypto.provider.BlowfishKeyGenerator"); + ps("AlgorithmParameters", "PBES2", + "com.sun.crypto.provider.PBES2Parameters$General", + pkcs5PBES2Aliases, null); - put("KeyGenerator.AES", - "com.sun.crypto.provider.AESKeyGenerator"); - put("Alg.Alias.KeyGenerator.Rijndael", "AES"); + ps("AlgorithmParameters", "PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128", + null, null); - put("KeyGenerator.RC2", - "com.sun.crypto.provider.KeyGeneratorCore$" + - "RC2KeyGenerator"); - put("KeyGenerator.ARCFOUR", - "com.sun.crypto.provider.KeyGeneratorCore$" + - "ARCFOURKeyGenerator"); - put("Alg.Alias.KeyGenerator.RC4", "ARCFOUR"); + ps("AlgorithmParameters", "PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128", + null, null); - put("KeyGenerator.ChaCha20", - "com.sun.crypto.provider.KeyGeneratorCore$" + - "ChaCha20KeyGenerator"); + ps("AlgorithmParameters", "PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128", + null, null); - put("KeyGenerator.HmacMD5", - "com.sun.crypto.provider.HmacMD5KeyGenerator"); + ps("AlgorithmParameters", "PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128", + null, null); - put("KeyGenerator.HmacSHA1", - "com.sun.crypto.provider.HmacSHA1KeyGenerator"); - put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.7", "HmacSHA1"); - put("Alg.Alias.KeyGenerator.1.2.840.113549.2.7", "HmacSHA1"); + ps("AlgorithmParameters", "PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128", + null, null); - put("KeyGenerator.HmacSHA224", - "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA224"); - put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.8", "HmacSHA224"); - put("Alg.Alias.KeyGenerator.1.2.840.113549.2.8", "HmacSHA224"); + ps("AlgorithmParameters", "PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256", + null, null); - put("KeyGenerator.HmacSHA256", - "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA256"); - put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.9", "HmacSHA256"); - put("Alg.Alias.KeyGenerator.1.2.840.113549.2.9", "HmacSHA256"); + ps("AlgorithmParameters", "PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256", + null, null); - put("KeyGenerator.HmacSHA384", - "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA384"); - put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.10", "HmacSHA384"); - put("Alg.Alias.KeyGenerator.1.2.840.113549.2.10", "HmacSHA384"); + ps("AlgorithmParameters", "PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256", + null, null); - put("KeyGenerator.HmacSHA512", - "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA512"); - put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.11", "HmacSHA512"); - put("Alg.Alias.KeyGenerator.1.2.840.113549.2.11", "HmacSHA512"); + ps("AlgorithmParameters", "PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256", + null, null); - put("KeyPairGenerator.DiffieHellman", - "com.sun.crypto.provider.DHKeyPairGenerator"); - put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman"); - put("Alg.Alias.KeyPairGenerator.OID."+OID_PKCS3, - "DiffieHellman"); - put("Alg.Alias.KeyPairGenerator."+OID_PKCS3, - "DiffieHellman"); + ps("AlgorithmParameters", "PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256", + null, null); - /* - * Algorithm parameter generation engines - */ - put("AlgorithmParameterGenerator.DiffieHellman", - "com.sun.crypto.provider.DHParameterGenerator"); - put("Alg.Alias.AlgorithmParameterGenerator.DH", - "DiffieHellman"); - put("Alg.Alias.AlgorithmParameterGenerator.OID."+OID_PKCS3, - "DiffieHellman"); - put("Alg.Alias.AlgorithmParameterGenerator."+OID_PKCS3, - "DiffieHellman"); + ps("AlgorithmParameters", "Blowfish", + "com.sun.crypto.provider.BlowfishParameters", + null, null); - /* - * Key Agreement engines - */ - put("KeyAgreement.DiffieHellman", - "com.sun.crypto.provider.DHKeyAgreement"); - put("Alg.Alias.KeyAgreement.DH", "DiffieHellman"); - put("Alg.Alias.KeyAgreement.OID."+OID_PKCS3, "DiffieHellman"); - put("Alg.Alias.KeyAgreement."+OID_PKCS3, "DiffieHellman"); + ps("AlgorithmParameters", "AES", + "com.sun.crypto.provider.AESParameters", + aesAliases, null); - put("KeyAgreement.DiffieHellman SupportedKeyClasses", - "javax.crypto.interfaces.DHPublicKey" + - "|javax.crypto.interfaces.DHPrivateKey"); + ps("AlgorithmParameters", "GCM", + "com.sun.crypto.provider.GCMParameters", + null, null); - /* - * Algorithm Parameter engines - */ - put("AlgorithmParameters.DiffieHellman", - "com.sun.crypto.provider.DHParameters"); - put("Alg.Alias.AlgorithmParameters.DH", "DiffieHellman"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS3, - "DiffieHellman"); - put("Alg.Alias.AlgorithmParameters."+OID_PKCS3, - "DiffieHellman"); + ps("AlgorithmParameters", "RC2", + "com.sun.crypto.provider.RC2Parameters", + null, null); - put("AlgorithmParameters.DES", - "com.sun.crypto.provider.DESParameters"); + ps("AlgorithmParameters", "OAEP", + "com.sun.crypto.provider.OAEPParameters", + null, null); - put("AlgorithmParameters.DESede", - "com.sun.crypto.provider.DESedeParameters"); - put("Alg.Alias.AlgorithmParameters.TripleDES", "DESede"); + ps("AlgorithmParameters", "ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Poly1305Parameters", + chachaPolyAliases, null); - put("AlgorithmParameters.PBE", - "com.sun.crypto.provider.PBEParameters"); + /* + * Key factories + */ + ps("KeyFactory", "DiffieHellman", + "com.sun.crypto.provider.DHKeyFactory", + diffieHellmanAliases, null); - put("AlgorithmParameters.PBEWithMD5AndDES", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_MD5_DES, - "PBEWithMD5AndDES"); - put("Alg.Alias.AlgorithmParameters."+OID_PKCS5_MD5_DES, - "PBEWithMD5AndDES"); + /* + * Secret-key factories + */ + ps("SecretKeyFactory", "DES", + "com.sun.crypto.provider.DESKeyFactory", + null, null); - put("AlgorithmParameters.PBEWithMD5AndTripleDES", - "com.sun.crypto.provider.PBEParameters"); + ps("SecretKeyFactory", "DESede", + "com.sun.crypto.provider.DESedeKeyFactory", + desEdeAliases, null); - put("AlgorithmParameters.PBEWithSHA1AndDESede", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); - put("Alg.Alias.AlgorithmParameters."+OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); + ps("SecretKeyFactory", "PBEWithMD5AndDES", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES", + pkcs5MD5_DESAliases, null); - put("AlgorithmParameters.PBEWithSHA1AndRC2_40", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC2_40, - "PBEWithSHA1AndRC2_40"); - put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_40, - "PBEWithSHA1AndRC2_40"); + /* + * Internal in-house crypto algorithm used for + * the JCEKS keystore type. Since this was developed + * internally, there isn't an OID corresponding to this + * algorithm. + */ + ps("SecretKeyFactory", "PBEWithMD5AndTripleDES", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndTripleDES", + null, null); - put("AlgorithmParameters.PBEWithSHA1AndRC2_128", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC2_128, - "PBEWithSHA1AndRC2_128"); - put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_128, - "PBEWithSHA1AndRC2_128"); + ps("SecretKeyFactory", "PBEWithSHA1AndDESede", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndDESede", + pkcs12DESedeAliases, null); - put("AlgorithmParameters.PBEWithSHA1AndRC4_40", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_40, - "PBEWithSHA1AndRC4_40"); - put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_40, - "PBEWithSHA1AndRC4_40"); + ps("SecretKeyFactory", "PBEWithSHA1AndRC2_40", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_40", + pkcs12RC2_40Aliases, null); - put("AlgorithmParameters.PBEWithSHA1AndRC4_128", - "com.sun.crypto.provider.PBEParameters"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_128, - "PBEWithSHA1AndRC4_128"); - put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_128, - "PBEWithSHA1AndRC4_128"); + ps("SecretKeyFactory", "PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_128", + pkcs12RC2_128Aliases, null); - put("AlgorithmParameters.PBES2", - "com.sun.crypto.provider.PBES2Parameters$General"); - put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_PBES2, - "PBES2"); - put("Alg.Alias.AlgorithmParameters." + OID_PKCS5_PBES2, - "PBES2"); + ps("SecretKeyFactory", "PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_40", + pkcs12RC4_40Aliases,null); - put("AlgorithmParameters.PBEWithHmacSHA1AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128"); + ps("SecretKeyFactory", "PBEWithSHA1AndRC4_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_128", + pkcs12RC4_128Aliases, null); - put("AlgorithmParameters.PBEWithHmacSHA224AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128"); + ps("SecretKeyFactory", "PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_128", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA256AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128"); + ps("SecretKeyFactory", "PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_128", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA384AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128"); + ps("SecretKeyFactory", "PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_128", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA512AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128"); + ps("SecretKeyFactory", "PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_128", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA1AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256"); + ps("SecretKeyFactory", "PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_128", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA224AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256"); + ps("SecretKeyFactory", "PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_256", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA256AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256"); + ps("SecretKeyFactory", "PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_256", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA384AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256"); + ps("SecretKeyFactory", "PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_256", + null, null); - put("AlgorithmParameters.PBEWithHmacSHA512AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256"); + ps("SecretKeyFactory", "PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_256", + null, null); - put("AlgorithmParameters.Blowfish", - "com.sun.crypto.provider.BlowfishParameters"); + ps("SecretKeyFactory", "PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256", + null, null); - put("AlgorithmParameters.AES", - "com.sun.crypto.provider.AESParameters"); - put("Alg.Alias.AlgorithmParameters.Rijndael", "AES"); - put("AlgorithmParameters.GCM", - "com.sun.crypto.provider.GCMParameters"); + // PBKDF2 + ps("SecretKeyFactory", "PBKDF2WithHmacSHA1", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA1", + pkcs5PBKDF2Aliases, null); + ps("SecretKeyFactory", "PBKDF2WithHmacSHA224", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA224", + null, null); + ps("SecretKeyFactory", "PBKDF2WithHmacSHA256", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA256", + null, null); + ps("SecretKeyFactory", "PBKDF2WithHmacSHA384", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA384", + null, null); + ps("SecretKeyFactory", "PBKDF2WithHmacSHA512", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA512", + null, null); + /* + * MAC + */ + attrs.clear(); + attrs.put("SupportedKeyFormats", "RAW"); + ps("Mac", "HmacMD5", "com.sun.crypto.provider.HmacMD5", null, attrs); + ps("Mac", "HmacSHA1", "com.sun.crypto.provider.HmacSHA1", + macSHA1Aliases, attrs); + ps("Mac", "HmacSHA224", "com.sun.crypto.provider.HmacCore$HmacSHA224", + macSHA224Aliases, attrs); + ps("Mac", "HmacSHA256", "com.sun.crypto.provider.HmacCore$HmacSHA256", + macSHA256Aliases, attrs); + ps("Mac", "HmacSHA384", "com.sun.crypto.provider.HmacCore$HmacSHA384", + macSHA384Aliases, attrs); + ps("Mac", "HmacSHA512", "com.sun.crypto.provider.HmacCore$HmacSHA512", + macSHA512Aliases, attrs); + // TODO: aliases with OIDs + ps("Mac", "HmacSHA512/224", + "com.sun.crypto.provider.HmacCore$HmacSHA512_224", + null, attrs); + ps("Mac", "HmacSHA512/256", + "com.sun.crypto.provider.HmacCore$HmacSHA512_256", + null, attrs); + ps("Mac", "HmacPBESHA1", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA1", + null, attrs); + ps("Mac", "HmacPBESHA224", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA224", + null, attrs); + ps("Mac", "HmacPBESHA256", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA256", + null, attrs); + ps("Mac", "HmacPBESHA384", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA384", + null, attrs); + ps("Mac", "HmacPBESHA512", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512", + null, attrs); + ps("Mac", "HmacPBESHA512/224", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_224", + null, attrs); + ps("Mac", "HmacPBESHA512/256", + "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_256", + null, attrs); - put("AlgorithmParameters.RC2", - "com.sun.crypto.provider.RC2Parameters"); - put("AlgorithmParameters.OAEP", - "com.sun.crypto.provider.OAEPParameters"); + // PBMAC1 + ps("Mac", "PBEWithHmacSHA1", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA1", null, attrs); + ps("Mac", "PBEWithHmacSHA224", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA224", null, attrs); + ps("Mac", "PBEWithHmacSHA256", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA256", null, attrs); + ps("Mac", "PBEWithHmacSHA384", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA384", null, attrs); + ps("Mac", "PBEWithHmacSHA512", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA512", null, attrs); + ps("Mac", "SslMacMD5", + "com.sun.crypto.provider.SslMacCore$SslMacMD5", null, attrs); + ps("Mac", "SslMacSHA1", + "com.sun.crypto.provider.SslMacCore$SslMacSHA1", null, attrs); - put("AlgorithmParameters.ChaCha20-Poly1305", - "com.sun.crypto.provider.ChaCha20Poly1305Parameters"); + /* + * KeyStore + */ + ps("KeyStore", "JCEKS", + "com.sun.crypto.provider.JceKeyStore", + null, null); - /* - * Key factories - */ - put("KeyFactory.DiffieHellman", - "com.sun.crypto.provider.DHKeyFactory"); - put("Alg.Alias.KeyFactory.DH", "DiffieHellman"); - put("Alg.Alias.KeyFactory.OID."+OID_PKCS3, - "DiffieHellman"); - put("Alg.Alias.KeyFactory."+OID_PKCS3, "DiffieHellman"); + /* + * SSL/TLS mechanisms + * + * These are strictly internal implementations and may + * be changed at any time. These names were chosen + * because PKCS11/SunPKCS11 does not yet have TLS1.2