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='&#x6f;&#112;&#x65;&#110;&#106;&#100;&#x6b;&#46;&#106;&#x61;&#118;&#x61;&#46;&#110;&#x65;&#116;';a='&#64;';n='&#98;&#x75;&#x69;&#108;&#100;&#x2d;&#100;&#x65;&#118;';e=n+a+h;
-document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
-// -->
-</script><noscript>&#98;&#x75;&#x69;&#108;&#100;&#x2d;&#100;&#x65;&#118;&#32;&#x61;&#116;&#32;&#x6f;&#112;&#x65;&#110;&#106;&#100;&#x6b;&#32;&#100;&#x6f;&#116;&#32;&#106;&#x61;&#118;&#x61;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;</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)
+                                  ? "&nbsp;&nbsp;&nbsp;&nbsp;with %s"
+                                  : ",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %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>&nbsp;&nbsp;&nbsp;&nbsp;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