Merge JDK-8200758-branch
authorherrick
Wed, 12 Dec 2018 08:38:45 -0500
branchJDK-8200758-branch
changeset 57072 29604aafa0fc
parent 57071 94e9270166f0 (current diff)
parent 52979 7384e00d5860 (diff)
child 57076 687505381ca4
Merge
make/CompileJavaModules.gmk
make/scripts/pandoc-manpage-filter.js
make/scripts/pandoc-manpage-filter.sh.template
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
test/jdk/sun/text/IntHashtable/Bug4170614Test.sh
test/jdk/sun/text/IntHashtable/patch-src/java/text/Bug4170614Test.java
--- a/doc/building.html	Wed Dec 12 08:27:16 2018 -0500
+++ b/doc/building.html	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/doc/building.md	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/doc/testing.html	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/CompileJavaModules.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -321,7 +321,7 @@
 
 ################################################################################
 
-jdk.internal.le_COPY += .properties
+jdk.internal.le_COPY += .properties .caps .txt
 
 ################################################################################
 
--- a/make/CompileToolsJdk.gmk	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/CompileToolsJdk.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/Docs.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -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))
@@ -556,6 +556,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 +574,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/ToolsJdk.gmk	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/ToolsJdk.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/common/ProcessMarkdown.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterData00.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterData01.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterData02.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterData0E.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterDataLatin1.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterDataPrivateUse.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/data/characterdata/CharacterDataUndefined.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -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();
--- a/make/launcher/LauncherCommon.gmk	Wed Dec 12 08:27:16 2018 -0500
+++ b/make/launcher/LauncherCommon.gmk	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ /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	Wed Dec 12 08:27:16 2018 -0500
+++ /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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/ppc/ppc.ad	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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/os/linux/globals_linux.hpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/os/linux/globals_linux.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/os/linux/os_linux.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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    ZPlatformNMethodDisarmedOffset = 4;
 
-const size_t    ZPlatformCacheLineSize        = 64;
+const size_t    ZPlatformCacheLineSize         = 64;
 
 #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP
--- a/src/hotspot/share/classfile/classFileParser.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -5733,7 +5733,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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/classLoader.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/classLoader.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/symbolTable.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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);
-  bool rehash_warning = false;
+  SymbolTableGet stg;
   bool clean_hint = false;
-  _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
-  if (rehash_warning) {
-    _needs_rehashing = true;
-  }
+  bool rehash_warning = false;
+  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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/symbolTable.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/vmSymbols.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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/gc/cms/cmsHeap.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/shared/barrierSet.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zArguments.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zBarrier.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zBarrierSet.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zGlobals.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zHeap.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zHeap.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zMark.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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();
-  }
-
-  if (immediate_oops.is_empty()) {
-    // No immediate oops found, return entry without immediate oops
-    return ZNMethodTableEntry(nm, non_immediate_oops);
+  // Attach GC data to nmethod
+  ZNMethodData* data = gc_data(nm);
+  if (data == NULL) {
+    data = ZNMethodData::create(nm);
+    set_gc_data(nm, data);
   }
 
-  // Return entry with immediate oops
-  return ZNMethodTableEntry(ZNMethodWithImmediateOops::create(nm, immediate_oops), 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);
+
+  // 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() {
+void ZNMethodTable::disarm_nmethod(nmethod* nm) {
+  BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
+  if (bs != NULL) {
+    bs->disarm(nm);
+  }
+}
+
+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::gc_epilogue() {
-  assert(_claimed >= _size, "Failed to claim all table entries");
+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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zNMethodTable.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zNMethodTableEntry.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zOopClosures.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zRootsIterator.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/gc/z/zThreadLocalData.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:38:45 2018 -0500
@@ -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/opto/c2_globals.hpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/opto/c2_globals.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/opto/c2compiler.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/opto/classes.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -394,3 +394,7 @@
 macro(ExtractL)
 macro(ExtractF)
 macro(ExtractD)
+macro(Digit)
+macro(LowerCase)
+macro(UpperCase)
+macro(Whitespace)
--- a/src/hotspot/share/opto/intrinsicnode.hpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/opto/intrinsicnode.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/opto/library_call.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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/runtime/thread.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/runtime/thread.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/runtime/thread.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/services/diagnosticCommand.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/hotspot/share/services/diagnosticCommand.hpp	Wed Dec 12 08:38:45 2018 -0500
@@ -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/java/lang/Character.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Character.java	Wed Dec 12 08:38:45 2018 -0500
@@ -681,11 +681,12 @@
      */
     public static final class UnicodeBlock extends Subset {
         /**
-         * 649  - the expected number of entities
+         * 667  - the expected number of entities
          * 0.75 - the default load factor of HashMap
          */
+        private static final int NUM_ENTITIES = 667;
         private static Map<String, UnicodeBlock> map =
-                new HashMap<>((int)(649 / 0.75f + 1.0f));
+                new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f));
 
         /**
          * Creates a UnicodeBlock with the given identifier name.
@@ -9084,7 +9085,7 @@
      * @since   1.5
      */
     public static boolean isLowerCase(int codePoint) {
-        return getType(codePoint) == Character.LOWERCASE_LETTER ||
+        return CharacterData.of(codePoint).isLowerCase(codePoint) ||
                CharacterData.of(codePoint).isOtherLowercase(codePoint);
     }
 
@@ -9150,7 +9151,7 @@
      * @since   1.5
      */
     public static boolean isUpperCase(int codePoint) {
-        return getType(codePoint) == Character.UPPERCASE_LETTER ||
+        return CharacterData.of(codePoint).isUpperCase(codePoint) ||
                CharacterData.of(codePoint).isOtherUppercase(codePoint);
     }
 
@@ -9301,7 +9302,7 @@
      * @since   1.5
      */
     public static boolean isDigit(int codePoint) {
-        return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
+        return CharacterData.of(codePoint).isDigit(codePoint);
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/CharacterData.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/CharacterData.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -28,6 +28,9 @@
 abstract class CharacterData {
     abstract int getProperties(int ch);
     abstract int getType(int ch);
+    abstract boolean isDigit(int ch);
+    abstract boolean isLowerCase(int ch);
+    abstract boolean isUpperCase(int ch);
     abstract boolean isWhitespace(int ch);
     abstract boolean isMirrored(int ch);
     abstract boolean isJavaIdentifierStart(int ch);
--- a/src/java.base/share/classes/java/lang/Object.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Object.java	Wed Dec 12 08:38:45 2018 -0500
@@ -94,12 +94,10 @@
      *     programmer should be aware that producing distinct integer results
      *     for unequal objects may improve the performance of hash tables.
      * </ul>
-     * <p>
-     * As much as is reasonably practical, the hashCode method defined
-     * by class {@code Object} does return distinct integers for
-     * distinct objects. (The hashCode may or may not be implemented
-     * as some function of an object's memory address at some point
-     * in time.)
+     *
+     * @implSpec
+     * As far as is reasonably practical, the {@code hashCode} method defined
+     * by class {@code Object} returns distinct integers for distinct objects.
      *
      * @return  a hash code value for this object.
      * @see     java.lang.Object#equals(java.lang.Object)
--- a/src/java.base/share/classes/java/lang/System.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/System.java	Wed Dec 12 08:38:45 2018 -0500
@@ -801,8 +801,9 @@
         }
 
         if (props == null) {
-            props = SystemProps.initProperties();
-            VersionProps.init(props);
+            Map<String, String> tempProps = SystemProps.initProperties();
+            VersionProps.init(tempProps);
+            props = createProperties(tempProps);
         }
         System.props = props;
     }
@@ -1960,17 +1961,41 @@
     }
 
     /**
+     * Create the Properties object from a map - masking out system properties
+     * that are not intended for public access.
+     */
+    private static Properties createProperties(Map<String, String> initialProps) {
+        Properties properties = new Properties(initialProps.size());
+        for (var entry : initialProps.entrySet()) {
+            String prop = entry.getKey();
+            switch (prop) {
+                // Do not add private system properties to the Properties
+                case "sun.nio.MaxDirectMemorySize":
+                case "sun.nio.PageAlignDirectMemory":
+                    // used by java.lang.Integer.IntegerCache
+                case "java.lang.Integer.IntegerCache.high":
+                    // used by sun.launcher.LauncherHelper
+                case "sun.java.launcher.diag":
+                    // used by jdk.internal.loader.ClassLoaders
+                case "jdk.boot.class.path.append":
+                    break;
+                default:
+                    properties.put(prop, entry.getValue());
+            }
+        }
+        return properties;
+    }
+
+    /**
      * Initialize the system class.  Called after thread initialization.
      */
     private static void initPhase1() {
-
         // VM might invoke JNU_NewStringPlatform() to set those encoding
         // sensitive properties (user.home, user.name, boot.class.path, etc.)
         // during "props" initialization.
         // The charset is initialized in System.c and does not depend on the Properties.
-        props = SystemProps.initProperties();
-        VersionProps.init(props);
-        StaticProperty.javaHome();          // Load StaticProperty to cache the property values
+        Map<String, String> tempProps = SystemProps.initProperties();
+        VersionProps.init(tempProps);
 
         // There are certain system configurations that may be controlled by
         // VM options such as the maximum amount of direct memory and
@@ -1978,15 +2003,14 @@
         // of autoboxing.  Typically, the library will obtain these values
         // from the properties set by the VM.  If the properties are for
         // internal implementation use only, these properties should be
-        // removed from the system properties.
-        //
-        // See java.lang.Integer.IntegerCache and the
-        // VM.saveAndRemoveProperties method for example.
+        // masked from the system properties.
         //
         // Save a private copy of the system properties object that
-        // can only be accessed by the internal implementation.  Remove
-        // certain system properties that are not intended for public access.
-        VM.saveAndRemoveProperties(props);
+        // can only be accessed by the internal implementation.
+        VM.saveProperties(tempProps);
+        props = createProperties(tempProps);
+
+        StaticProperty.javaHome();          // Load StaticProperty to cache the property values
 
         lineSeparator = props.getProperty("line.separator");
 
--- a/src/java.base/share/classes/java/lang/VersionProps.java.template	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/VersionProps.java.template	Wed Dec 12 08:38:45 2018 -0500
@@ -28,8 +28,8 @@
 import java.io.PrintStream;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
-import java.util.Properties;
 
 class VersionProps {
 
@@ -88,25 +88,25 @@
     /**
      * Initialize system properties using build provided values.
      *
-     * @param props Properties instance in which to insert the properties
+     * @param props Map instance in which to insert the properties
      */
-    public static void init(Properties props) {
-        props.setProperty("java.version", java_version);
-        props.setProperty("java.version.date", java_version_date);
-        props.setProperty("java.runtime.version", java_runtime_version);
-        props.setProperty("java.runtime.name", java_runtime_name);
+    public static void init(Map<String, String> props) {
+        props.put("java.version", java_version);
+        props.put("java.version.date", java_version_date);
+        props.put("java.runtime.version", java_runtime_version);
+        props.put("java.runtime.name", java_runtime_name);
         if (VENDOR_VERSION_STRING.length() > 0)
-            props.setProperty("java.vendor.version", VENDOR_VERSION_STRING);
+            props.put("java.vendor.version", VENDOR_VERSION_STRING);
 
-        props.setProperty("java.class.version", CLASSFILE_MAJOR_MINOR);
+        props.put("java.class.version", CLASSFILE_MAJOR_MINOR);
 
-        props.setProperty("java.specification.version", VERSION_SPECIFICATION);
-        props.setProperty("java.specification.name", "Java Platform API Specification");
-        props.setProperty("java.specification.vendor", "Oracle Corporation");
+        props.put("java.specification.version", VERSION_SPECIFICATION);
+        props.put("java.specification.name", "Java Platform API Specification");
+        props.put("java.specification.vendor", "Oracle Corporation");
 
-        props.setProperty("java.vendor", VENDOR);
-        props.setProperty("java.vendor.url", VENDOR_URL);
-        props.setProperty("java.vendor.url.bug", VENDOR_URL_BUG);
+        props.put("java.vendor", VENDOR);
+        props.put("java.vendor.url", VENDOR_URL);
+        props.put("java.vendor.url.bug", VENDOR_URL_BUG);
     }
 
     private static int parseVersionNumber(String version, int prevIndex, int index) {
--- a/src/java.base/share/classes/java/net/URI.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/net/URI.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,6 +25,7 @@
 
 package java.net;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
@@ -36,6 +37,7 @@
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.CharacterCodingException;
+import java.nio.file.Path;
 import java.text.Normalizer;
 import jdk.internal.access.JavaNetUriAccess;
 import jdk.internal.access.SharedSecrets;
@@ -458,6 +460,27 @@
  * resolution as well as the network I/O operations of looking up the host and
  * opening a connection to the specified resource.
  *
+ * @apiNote
+ *
+ * Applications working with file paths and file URIs should take great
+ * care to use the appropriate methods to convert between the two.
+ * The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
+ * constructor can be used to create {@link Path} or {@link File}
+ * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
+ * can be used to create a {@link URI} from a file path.
+ * Applications should never try to {@linkplain
+ * #URI(String, String, String, int, String, String, String)
+ * construct}, {@linkplain #URI(String) parse}, or
+ * {@linkplain #resolve(String) resolve} a {@code URI}
+ * from the direct string representation of a {@code File} or {@code Path}
+ * instance.
+ * <p>
+ * Some components of a URL or URI, such as <i>userinfo</i>, may
+ * be abused to construct misleading URLs or URIs. Applications
+ * that deal with URLs or URIs should take into account
+ * the recommendations advised in <a
+ * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
+ * Section 7, Security Considerations</a>.
  *
  * @author Mark Reinhold
  * @since 1.4
--- a/src/java.base/share/classes/java/net/URL.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/net/URL.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,9 +25,11 @@
 
 package java.net;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.spi.URLStreamHandlerProvider;
+import java.nio.file.Path;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Hashtable;
@@ -145,6 +147,27 @@
  * used, but only for HTML form encoding, which is not the same
  * as the encoding scheme defined in RFC2396.
  *
+ * @apiNote
+ *
+ * Applications working with file paths and file URIs should take great
+ * care to use the appropriate methods to convert between the two.
+ * The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
+ * constructor can be used to create {@link Path} or {@link File}
+ * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
+ * can be used to create a {@link URI} from a file path, which can be
+ * converted to URL using {@link URI#toURL()}.
+ * Applications should never try to {@linkplain #URL(String, String, String)
+ * construct} or {@linkplain #URL(String) parse} a {@code URL}
+ * from the direct string representation of a {@code File} or {@code Path}
+ * instance.
+ * <p>
+ * Some components of a URL or URI, such as <i>userinfo</i>, may
+ * be abused to construct misleading URLs or URIs. Applications
+ * that deal with URLs or URIs should take into account
+ * the recommendations advised in <a
+ * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
+ * Section 7, Security Considerations</a>.
+ *
  * @author  James Gosling
  * @since 1.0
  */
--- a/src/java.base/share/classes/java/util/SplittableRandom.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java	Wed Dec 12 08:38:45 2018 -0500
@@ -80,7 +80,7 @@
  * in security-sensitive applications. Additionally,
  * default-constructed instances do not use a cryptographically random
  * seed unless the {@linkplain System#getProperty system property}
- * {@code java.util.secureRandomSeed} is set to {@code true}.
+ * {@systemProperty java.util.secureRandomSeed} is set to {@code true}.
  *
  * @author  Guy Steele
  * @author  Doug Lea
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Dec 12 08:38:45 2018 -0500
@@ -2334,17 +2334,15 @@
             Node<K,V>[] tab, nt; int n, sc;
             while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
                    (n = tab.length) < MAXIMUM_CAPACITY) {
-                int rs = resizeStamp(n);
+                int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
                 if (sc < 0) {
-                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
-                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
-                        transferIndex <= 0)
+                    if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
+                        (nt = nextTable) == null || transferIndex <= 0)
                         break;
                     if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
                         transfer(tab, nt);
                 }
-                else if (U.compareAndSetInt(this, SIZECTL, sc,
-                                             (rs << RESIZE_STAMP_SHIFT) + 2))
+                else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
                     transfer(tab, null);
                 s = sumCount();
             }
@@ -2358,11 +2356,11 @@
         Node<K,V>[] nextTab; int sc;
         if (tab != null && (f instanceof ForwardingNode) &&
             (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
-            int rs = resizeStamp(tab.length);
+            int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT;
             while (nextTab == nextTable && table == tab &&
                    (sc = sizeCtl) < 0) {
-                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
-                    sc == rs + MAX_RESIZERS || transferIndex <= 0)
+                if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
+                    transferIndex <= 0)
                     break;
                 if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
                     transfer(tab, nextTab);
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Dec 12 08:38:45 2018 -0500
@@ -136,17 +136,17 @@
  * <p>The parameters used to construct the common pool may be controlled by
  * setting the following {@linkplain System#getProperty system properties}:
  * <ul>
- * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism}
+ * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.parallelism}
  * - the parallelism level, a non-negative integer
- * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory}
+ * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.threadFactory}
  * - the class name of a {@link ForkJoinWorkerThreadFactory}.
  * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
  * is used to load this class.
- * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
+ * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.exceptionHandler}
  * - the class name of a {@link UncaughtExceptionHandler}.
  * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
  * is used to load this class.
- * <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
+ * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.maximumSpares}
  * - the maximum number of allowed extra threads to maintain target
  * parallelism (default 256).
  * </ul>
@@ -445,8 +445,7 @@
      * if to its current value).  This would be extremely costly. So
      * we relax it in several ways: (1) Producers only signal when
      * their queue is possibly empty at some point during a push
-     * operation (which requires conservatively checking size zero or
-     * one to cover races). (2) Other workers propagate this signal
+     * operation. (2) Other workers propagate this signal
      * when they find tasks in a queue with size greater than one. (3)
      * Workers only enqueue after scanning (see below) and not finding
      * any tasks.  (4) Rather than CASing ctl to its current value in
@@ -762,10 +761,8 @@
 
     /**
      * The maximum number of top-level polls per worker before
-     * checking other queues, expressed as a bit shift to, in effect,
-     * multiply by pool size, and then use as random value mask, so
-     * average bound is about poolSize*(1<<TOP_BOUND_SHIFT).  See
-     * above for rationale.
+     * checking other queues, expressed as a bit shift.  See above for
+     * rationale.
      */
     static final int TOP_BOUND_SHIFT = 10;
 
@@ -841,18 +838,17 @@
          */
         final void push(ForkJoinTask<?> task) {
             ForkJoinTask<?>[] a;
-            int s = top, d, cap, m;
+            int s = top, d = s - base, cap, m;
             ForkJoinPool p = pool;
             if ((a = array) != null && (cap = a.length) > 0) {
                 QA.setRelease(a, (m = cap - 1) & s, task);
                 top = s + 1;
-                if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 &&
-                    p != null) {                 // size 0 or 1
-                    VarHandle.fullFence();
-                    p.signalWork();
+                if (d == m)
+                    growArray(false);
+                else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) {
+                    VarHandle.fullFence();  // was empty
+                    p.signalWork(null);
                 }
-                else if (d == m)
-                    growArray(false);
             }
         }
 
@@ -863,16 +859,16 @@
         final boolean lockedPush(ForkJoinTask<?> task) {
             ForkJoinTask<?>[] a;
             boolean signal = false;
-            int s = top, b = base, cap, d;
+            int s = top, d = s - base, cap, m;
             if ((a = array) != null && (cap = a.length) > 0) {
-                a[(cap - 1) & s] = task;
+                a[(m = (cap - 1)) & s] = task;
                 top = s + 1;
-                if (b - s + cap - 1 == 0)
+                if (d == m)
                     growArray(true);
                 else {
                     phase = 0; // full volatile unlock
-                    if (((s - base) & ~1) == 0) // size 0 or 1
-                        signal = true;
+                    if (a[m & (s - 1)] == null)
+                        signal = true;   // was empty
                 }
             }
             return signal;
@@ -1014,25 +1010,30 @@
          * queue, up to bound n (to avoid infinite unfairness).
          */
         final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) {
-            if (t != null && q != null) { // hoist checks
-                int nstolen = 1;
-                for (;;) {
+            int nstolen = 1;
+            for (int j = 0;;) {
+                if (t != null)
                     t.doExec();
-                    if (n-- < 0)
+                if (j++ <= n)
+                    t = nextLocalTask();
+                else {
+                    j = 0;
+                    t = null;
+                }
+                if (t == null) {
+                    if (q != null && (t = q.poll()) != null) {
+                        ++nstolen;
+                        j = 0;
+                    }
+                    else if (j != 0)
                         break;
-                    else if ((t = nextLocalTask()) == null) {
-                        if ((t = q.poll()) == null)
-                            break;
-                        else
-                            ++nstolen;
-                    }
                 }
-                ForkJoinWorkerThread thread = owner;
-                nsteals += nstolen;
-                source = 0;
-                if (thread != null)
-                    thread.afterTopLevelExec();
             }
+            ForkJoinWorkerThread thread = owner;
+            nsteals += nstolen;
+            source = 0;
+            if (thread != null)
+                thread.afterTopLevelExec();
         }
 
         /**
@@ -1455,7 +1456,7 @@
 
         if (!tryTerminate(false, false) &&            // possibly replace worker
             w != null && w.array != null)             // avoid repeated failures
-            signalWork();
+            signalWork(null);
 
         if (ex == null)                               // help clean on way out
             ForkJoinTask.helpExpungeStaleExceptions();
@@ -1465,8 +1466,9 @@
 
     /**
      * Tries to create or release a worker if too few are running.
+     * @param q if non-null recheck if empty on CAS failure
      */
-    final void signalWork() {
+    final void signalWork(WorkQueue q) {
         for (;;) {
             long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
             if ((c = ctl) >= 0L)                      // enough workers
@@ -1493,6 +1495,8 @@
                         LockSupport.unpark(vt);
                     break;
                 }
+                else if (q != null && q.isEmpty())     // no need to retry
+                    break;
             }
         }
     }
@@ -1613,19 +1617,24 @@
                 else if (rc <= 0 && (md & SHUTDOWN) != 0 &&
                          tryTerminate(false, false))
                     break;                        // quiescent shutdown
-                else if (rc <= 0 && pred != 0 && phase == (int)c) {
-                    long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
-                    long d = keepAlive + System.currentTimeMillis();
-                    LockSupport.parkUntil(this, d);
-                    if (ctl == c &&               // drop on timeout if all idle
-                        d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
-                        CTL.compareAndSet(this, c, nc)) {
-                        w.phase = QUIET;
-                        break;
+                else if (w.phase < 0) {
+                    if (rc <= 0 && pred != 0 && phase == (int)c) {
+                        long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
+                        long d = keepAlive + System.currentTimeMillis();
+                        LockSupport.parkUntil(this, d);
+                        if (ctl == c &&           // drop on timeout if all idle
+                            d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
+                            CTL.compareAndSet(this, c, nc)) {
+                            w.phase = QUIET;
+                            break;
+                        }
+                    }
+                    else {
+                        LockSupport.park(this);
+                        if (w.phase < 0)          // one spurious wakeup check
+                            LockSupport.park(this);
                     }
                 }
-                else if (w.phase < 0)
-                    LockSupport.park(this);       // OK if spuriously woken
                 w.source = 0;                     // disable signal
             }
         }
@@ -1641,8 +1650,8 @@
         WorkQueue[] ws; int n;
         if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
             for (int m = n - 1, j = r & m;;) {
-                WorkQueue q; int b;
-                if ((q = ws[j]) != null && q.top != (b = q.base)) {
+                WorkQueue q; int b, s;
+                if ((q = ws[j]) != null && (s = q.top) != (b = q.base)) {
                     int qid = q.id;
                     ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t;
                     if ((a = q.array) != null && (cap = a.length) > 0) {
@@ -1651,10 +1660,10 @@
                             QA.compareAndSet(a, k, t, null)) {
                             q.base = b;
                             w.source = qid;
-                            if (q.top - b > 0)
-                                signalWork();
+                            if (s != b && a[(cap - 1) & b] != null)
+                                signalWork(q);    // help signal if more tasks
                             w.topLevelExec(t, q,  // random fairness bound
-                                           r & ((n << TOP_BOUND_SHIFT) - 1));
+                                           (r | (1 << TOP_BOUND_SHIFT)) & SMASK);
                         }
                     }
                     return true;
@@ -1900,7 +1909,7 @@
                 r = ThreadLocalRandom.advanceProbe(r);
             else {
                 if (q.lockedPush(task))
-                    signalWork();
+                    signalWork(null);
                 return;
             }
         }
--- a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Wed Dec 12 08:38:45 2018 -0500
@@ -122,7 +122,7 @@
  * <p>All {@code Lock} implementations <em>must</em> enforce the same
  * memory synchronization semantics as provided by the built-in monitor
  * lock, as described in
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4">
  * Chapter 17 of
  * <cite>The Java&trade; Language Specification</cite></a>:
  * <ul>
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Dec 12 08:38:45 2018 -0500
@@ -133,7 +133,7 @@
  * <p><b>Memory Synchronization.</b> Methods with the effect of
  * successfully locking in any mode have the same memory
  * synchronization effects as a <em>Lock</em> action described in
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4">
  * Chapter 17 of <cite>The Java&trade; Language Specification</cite></a>.
  * Methods successfully unlocking in write mode have the same memory
  * synchronization effects as an <em>Unlock</em> action.  In optimistic
--- a/src/java.base/share/classes/java/util/concurrent/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/java/util/concurrent/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -226,7 +226,7 @@
  *
  * <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
  *
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5">
+ * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5">
  * Chapter 17 of
  * <cite>The Java&trade; Language Specification</cite></a> defines the
  * <i>happens-before</i> relation on memory operations such as reads and
--- a/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,6 +26,8 @@
 package jdk.internal.misc;
 
 import static java.lang.Thread.State.*;
+
+import java.util.Collections;
 import java.util.Map;
 import java.util.Properties;
 
@@ -175,7 +177,7 @@
         if (savedProps == null)
             throw new IllegalStateException("Not yet initialized");
 
-        return savedProps;
+        return Collections.unmodifiableMap(savedProps);
     }
 
     private static Map<String, String> savedProps;
@@ -184,16 +186,15 @@
     // the system properties that are not intended for public access.
     //
     // This method can only be invoked during system initialization.
-    public static void saveAndRemoveProperties(Properties props) {
+    public static void saveProperties(Map<String, String> props) {
         if (initLevel() != 0)
             throw new IllegalStateException("Wrong init level");
 
-        @SuppressWarnings({"rawtypes", "unchecked"})
-        Map<String, String> sp =
-            Map.ofEntries(props.entrySet().toArray(new Map.Entry[0]));
         // only main thread is running at this time, so savedProps and
         // its content will be correctly published to threads started later
-        savedProps = sp;
+        if (savedProps == null) {
+            savedProps = props;
+        }
 
         // Set the maximum amount of direct memory.  This value is controlled
         // by the vm option -XX:MaxDirectMemorySize=<size>.
@@ -201,7 +202,7 @@
         // from the system property sun.nio.MaxDirectMemorySize set by the VM.
         // If not set or set to -1, the max memory will be used
         // The system property will be removed.
-        String s = (String)props.remove("sun.nio.MaxDirectMemorySize");
+        String s = props.get("sun.nio.MaxDirectMemorySize");
         if (s == null || s.isEmpty() || s.equals("-1")) {
             // -XX:MaxDirectMemorySize not given, take default
             directMemory = Runtime.getRuntime().maxMemory();
@@ -212,19 +213,9 @@
         }
 
         // Check if direct buffers should be page aligned
-        s = (String)props.remove("sun.nio.PageAlignDirectMemory");
+        s = props.get("sun.nio.PageAlignDirectMemory");
         if ("true".equals(s))
             pageAlignDirectMemory = true;
-
-        // Remove other private system properties
-        // used by java.lang.Integer.IntegerCache
-        props.remove("java.lang.Integer.IntegerCache.high");
-
-        // used by sun.launcher.LauncherHelper
-        props.remove("sun.java.launcher.diag");
-
-        // used by jdk.internal.loader.ClassLoaders
-        props.remove("jdk.boot.class.path.append");
     }
 
     // Initialize any miscellaneous operating system settings that need to be
--- a/src/java.base/share/classes/jdk/internal/util/SystemProps.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/jdk/internal/util/SystemProps.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,7 +26,8 @@
 
 
 import java.lang.annotation.Native;
-import java.util.Properties;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * System Property initialization for internal use only
@@ -47,12 +48,13 @@
      *
      * @return a Properties instance initialized with all of the properties
      */
-    public static Properties initProperties() {
+    public static Map<String, String> initProperties() {
+
         // Initially, cmdProperties only includes -D and props from the VM
         Raw raw = new Raw();
-        Properties props = raw.cmdProperties();
+        HashMap<String, String> props = raw.cmdProperties();
 
-        String javaHome = props.getProperty("java.home");
+        String javaHome = props.get("java.home");
         assert javaHome != null : "java.home not set";
 
         putIfAbsent(props, "user.home", raw.propDefault(Raw._user_home_NDX));
@@ -92,7 +94,6 @@
         putIfAbsent(props, "java.awt.headless", raw.propDefault(Raw._java_awt_headless_NDX));
         putIfAbsent(props, "java.awt.graphicsenv", raw.propDefault(Raw._java_awt_graphicsenv_NDX));
         putIfAbsent(props, "sun.desktop", raw.propDefault(Raw._sun_desktop_NDX));
-        putIfAbsent(props, "sun.java2d.fontpath", raw.propDefault(Raw._sun_java2d_fontpath_NDX));
         putIfAbsent(props, "sun.arch.abi", raw.propDefault(Raw._sun_arch_abi_NDX));
         putIfAbsent(props, "sun.arch.data.model", raw.propDefault(Raw._sun_arch_data_model_NDX));
         putIfAbsent(props, "sun.os.patch.level", raw.propDefault(Raw._sun_os_patch_level_NDX));
@@ -121,7 +122,7 @@
      * @param key the key
      * @param value the value
      */
-    private static void put(Properties props, String key, String value) {
+    private static void put(HashMap<String, String> props, String key, String value) {
         if (value != null) {
             props.put(key, value);
         }
@@ -133,7 +134,7 @@
      * @param key the key
      * @param value the value
      */
-    private static void putIfAbsent(Properties props, String key, String value) {
+    private static void putIfAbsent(HashMap<String, String> props, String key, String value) {
         if (value != null) {
             props.putIfAbsent(key, value);
         }
@@ -148,10 +149,12 @@
      * @param display the display value for the base
      * @param format the format value for the base
      */
-    private static void fillI18nProps(Properties cmdProps, String base, String display,
+    private static void fillI18nProps(HashMap<String, String> cmdProps,
+                                      String base,
+                                      String display,
                                       String format) {
         // Do not override command line setting
-        String baseValue = cmdProps.getProperty(base);
+        String baseValue = cmdProps.get(base);
         if (baseValue != null) {
             return;     // Do not override value from the command line
         }
@@ -164,7 +167,7 @@
 
         /* user.xxx.display property */
         String disp = base.concat(".display");
-        String dispValue = cmdProps.getProperty(disp);
+        String dispValue = cmdProps.get(disp);
         if (dispValue == null && display != null && !display.equals(baseValue)) {
             // Create the property only if different from the base property
             cmdProps.put(disp, display);
@@ -172,7 +175,7 @@
 
         /* user.xxx.format property */
         String fmt = base.concat(".format");
-        String fmtValue = cmdProps.getProperty(fmt);
+        String fmtValue = cmdProps.get(fmt);
         if (fmtValue == null && format != null && !format.equals(baseValue)) {
             // Create the property only if different than the base property
             cmdProps.put(fmt, format);
@@ -221,8 +224,7 @@
         @Native private static final int _sun_cpu_isalist_NDX = 1 + _sun_cpu_endian_NDX;
         @Native private static final int _sun_desktop_NDX = 1 + _sun_cpu_isalist_NDX;
         @Native private static final int _sun_io_unicode_encoding_NDX = 1 + _sun_desktop_NDX;
-        @Native private static final int _sun_java2d_fontpath_NDX = 1 + _sun_io_unicode_encoding_NDX;
-        @Native private static final int _sun_jnu_encoding_NDX = 1 + _sun_java2d_fontpath_NDX;
+        @Native private static final int _sun_jnu_encoding_NDX = 1 + _sun_io_unicode_encoding_NDX;
         @Native private static final int _sun_os_patch_level_NDX = 1 + _sun_jnu_encoding_NDX;
         @Native private static final int _sun_stderr_encoding_NDX = 1 + _sun_os_patch_level_NDX;
         @Native private static final int _sun_stdout_encoding_NDX = 1 + _sun_stderr_encoding_NDX;
@@ -255,15 +257,17 @@
          *
          * @return return a Properties instance of the command line and VM options
          */
-        private Properties cmdProperties() {
+        private HashMap<String, String> cmdProperties() {
             String[] vmProps = vmProperties();
-            int nProps = vmProps.length / 2;
-            var cmdProps = new Properties(nProps + Raw.FIXED_LENGTH);
-            for (int i = 0; i < nProps; i++) {
-                String k = vmProps[i * 2];
+            // While optimal initialCapacity here would be the exact number of properties
+            // divided by LOAD_FACTOR, a large portion of the properties in Raw are
+            // usually not set, so for typical cases the chosen capacity avoids resizing
+            var cmdProps = new HashMap<String, String>((vmProps.length / 2) + Raw.FIXED_LENGTH);
+            for (int i = 0; i < vmProps.length;) {
+                String k = vmProps[i++];
                 if (k != null) {
-                    String v = vmProps[i * 2 + 1];
-                    cmdProps.setProperty(k, v != null ? v : "");
+                    String v = vmProps[i++];
+                    cmdProps.put(k, v != null ? v : "");
                 } else {
                     // no more key/value pairs
                     break;
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java	Wed Dec 12 08:38:45 2018 -0500
@@ -90,6 +90,9 @@
 
     ClientHelloMessage initialClientHelloMsg = null;
 
+    // PSK identity is selected in first Hello and used again after HRR
+    byte[] pskIdentity;
+
     ClientHandshakeContext(SSLContextImpl sslContext,
             TransportContext conContext) throws IOException {
         super(sslContext, conContext);
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java	Wed Dec 12 08:38:45 2018 -0500
@@ -656,7 +656,11 @@
                 return null;
             }
             SecretKey psk = pskOpt.get();
-            Optional<byte[]> pskIdOpt = chc.resumingSession.consumePskIdentity();
+            // The PSK ID can only be used in one connections, but this method
+            // may be called twice in a connection if the server sends HRR.
+            // ID is saved in the context so it can be used in the second call.
+            Optional<byte[]> pskIdOpt = Optional.ofNullable(chc.pskIdentity)
+                .or(chc.resumingSession::consumePskIdentity);
             if (!pskIdOpt.isPresent()) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
@@ -664,7 +668,7 @@
                 }
                 return null;
             }
-            byte[] pskId = pskIdOpt.get();
+            chc.pskIdentity = pskIdOpt.get();
 
             //The session cannot be used again. Remove it from the cache.
             SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
@@ -681,7 +685,7 @@
                     chc.resumingSession.getTicketCreationTime());
             int obfuscatedAge =
                     ageMillis + chc.resumingSession.getTicketAgeAdd();
-            identities.add(new PskIdentity(pskId, obfuscatedAge));
+            identities.add(new PskIdentity(chc.pskIdentity, obfuscatedAge));
 
             SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession);
             ClientHelloMessage clientHello = (ClientHelloMessage)message;
--- a/src/java.base/share/classes/sun/security/util/ArrayUtil.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/ArrayUtil.java	Wed Dec 12 08:38:45 2018 -0500
@@ -52,4 +52,21 @@
         // NPE is thrown when array is null
         Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER);
     }
+
+    private static void swap(byte[] arr, int i, int j) {
+        byte tmp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = tmp;
+    }
+
+    public static void reverse(byte [] arr) {
+        int i = 0;
+        int j = arr.length - 1;
+
+        while (i < j) {
+            swap(arr, i, j);
+            i++;
+            j--;
+        }
+    }
 }
--- a/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java	Wed Dec 12 08:38:45 2018 -0500
@@ -41,6 +41,18 @@
 public interface MutableIntegerModuloP extends IntegerModuloP {
 
     /**
+     * Set this value to the value of b when set has the value 1.
+     * No change is made to this element when set has the value 0. The
+     * result is undefined when set has a value other than 0 or 1. The set
+     * parameter is an int (rather than boolean) to allow the implementation
+     * to perform the assignment using branch-free integer arithmetic.
+     *
+     * @param b the element to conditionally swap with
+     * @param set an int that determines whether to set
+     */
+    void conditionalSet(IntegerModuloP b, int set);
+
+    /**
      * Swap the value of this with the value of b when swap has the value 1.
      * No change is made to either element when swap has the value 0. The
      * result is undefined when swap has a value other than 0 or 1. The swap
@@ -131,5 +143,20 @@
      * @return this
      */
     MutableIntegerModuloP setProduct(SmallValue v);
+
+    /**
+     * Set the value of this element equal to 0 - this.
+     *
+     * @return this
+     */
+    MutableIntegerModuloP setAdditiveInverse();
+
+    /**
+     * Some implementations required reduction operations to be requested
+     * by the client at certain times. This method reduces the representation.
+     *
+     * @return this
+     */
+    MutableIntegerModuloP setReduced();
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/FieldGen.jsh	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,851 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * This file is used to generated optimized finite field implementations.
+ * Required settings are included in the file. To generate, use jshell:
+ * jshell < FieldGen.jsh
+ */
+
+import java.io.*;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class FieldGen {
+
+    static FieldParams Curve25519 = new FieldParams("IntegerPolynomial25519", 26, 10, 1, 255,
+    Arrays.asList(
+    new Term(0, -19)
+    ),
+    Curve25519CrSequence(), simpleSmallCrSequence(10)
+    );
+
+    private static List<CarryReduce> Curve25519CrSequence() {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+
+        // reduce(7,2)
+        result.add(new Reduce(17));
+        result.add(new Reduce(18));
+
+        // carry(8,2)
+        result.add(new Carry(8));
+        result.add(new Carry(9));
+
+        // reduce(0,7)
+        for (int i = 10; i < 17; i++) {
+            result.add(new Reduce(i));
+        }
+
+        // carry(0,9)
+        result.addAll(fullCarry(10));
+
+        return result;
+    }
+
+    static FieldParams Curve448 = new FieldParams("IntegerPolynomial448", 28, 16, 1, 448,
+    Arrays.asList(
+    new Term(224, -1),
+    new Term(0, -1)
+    ),
+    Curve448CrSequence(), simpleSmallCrSequence(16)
+    );
+
+    private static List<CarryReduce> Curve448CrSequence() {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+
+        // reduce(8, 7)
+        for (int i = 24; i < 31; i++) {
+            result.add(new Reduce(i));
+        }
+        // reduce(4, 4)
+        for (int i = 20; i < 24; i++) {
+            result.add(new Reduce(i));
+        }
+
+        //carry(14, 2)
+        result.add(new Carry(14));
+        result.add(new Carry(15));
+
+        // reduce(0, 4)
+        for (int i = 16; i < 20; i++) {
+            result.add(new Reduce(i));
+        }
+
+        // carry(0, 15)
+        result.addAll(fullCarry(16));
+
+        return result;
+    }
+
+    static FieldParams P256 = new FieldParams("IntegerPolynomialP256", 26, 10, 2, 256,
+    Arrays.asList(
+    new Term(224, -1),
+    new Term(192, 1),
+    new Term(96, 1),
+    new Term(0, -1)
+    ),
+    P256CrSequence(), simpleSmallCrSequence(10)
+    );
+
+    private static List<CarryReduce> P256CrSequence() {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullReduce(10));
+        result.addAll(simpleSmallCrSequence(10));
+        return result;
+    }
+
+    static FieldParams P384 = new FieldParams("IntegerPolynomialP384", 28, 14, 2, 384,
+    Arrays.asList(
+    new Term(128, -1),
+    new Term(96, -1),
+    new Term(32, 1),
+    new Term(0, -1)
+    ),
+    P384CrSequence(), simpleSmallCrSequence(14)
+    );
+
+    private static List<CarryReduce> P384CrSequence() {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullReduce(14));
+        result.addAll(simpleSmallCrSequence(14));
+        return result;
+    }
+
+    static FieldParams P521 = new FieldParams("IntegerPolynomialP521", 28, 19, 2, 521,
+    Arrays.asList(new Term(0, -1)), P521CrSequence(), simpleSmallCrSequence(19)
+    );
+
+    private static List<CarryReduce> P521CrSequence() {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullReduce(19));
+        result.addAll(simpleSmallCrSequence(19));
+        return result;
+    }
+
+    static FieldParams O256 = new FieldParams("P256OrderField", 26, 10, 1, 256,
+    new BigInteger("26959946660873538059280334323273029441504803697035324946844617595567"),
+    orderFieldCrSequence(10), orderFieldSmallCrSequence(10)
+    );
+
+    static FieldParams O384 = new FieldParams("P384OrderField", 28, 14, 1, 384,
+    new BigInteger("1388124618062372383947042015309946732620727252194336364173"),
+    orderFieldCrSequence(14), orderFieldSmallCrSequence(14)
+    );
+
+    static FieldParams O521 = new FieldParams("P521OrderField", 28, 19, 1, 521,
+    new BigInteger("657877501894328237357444332315020117536923257219387276263472201219398408051703"),
+    o521crSequence(19), orderFieldSmallCrSequence(19)
+    );
+
+    private static List<CarryReduce> o521crSequence(int numLimbs) {
+
+        // split the full reduce in half, with a carry in between
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullCarry(2 * numLimbs));
+        for (int i = 2 * numLimbs - 1; i >= numLimbs + numLimbs/2; i--) {
+            result.add(new Reduce(i));
+        }
+        // carry
+        for (int i = numLimbs; i < numLimbs + numLimbs / 2 - 1; i++) {
+            result.add(new Carry(i));
+        }
+        // rest of reduce
+        for (int i = numLimbs + numLimbs/2 - 1; i >= numLimbs; i--) {
+            result.add(new Reduce(i));
+        }
+        result.addAll(orderFieldSmallCrSequence(numLimbs));
+
+        return result;
+    }
+
+    private static List<CarryReduce> orderFieldCrSequence(int numLimbs) {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullCarry(2 * numLimbs));
+        result.add(new Reduce(2 * numLimbs - 1));
+        result.addAll(fullReduce(numLimbs));
+        result.addAll(fullCarry(numLimbs + 1));
+        result.add(new Reduce(numLimbs));
+        result.addAll(fullCarry(numLimbs));
+
+        return result;
+    }
+   private static List<CarryReduce> orderFieldSmallCrSequence(int numLimbs) {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        result.addAll(fullCarry(numLimbs + 1));
+        result.add(new Reduce(numLimbs));
+        result.addAll(fullCarry(numLimbs));
+        return result;
+    }
+
+    static final FieldParams[] ALL_FIELDS = {P256, P384, P521, O256, O384, O521};
+
+    public static class Term {
+        private final int power;
+        private final int coefficient;
+
+        public Term(int power, int coefficient) {
+            this.power = power;
+            this.coefficient = coefficient;
+        }
+
+        public int getPower() {
+            return power;
+        }
+
+        public int getCoefficient() {
+            return coefficient;
+        }
+
+        public BigInteger getValue() {
+            return BigInteger.valueOf(2).pow(power).multiply(BigInteger.valueOf(coefficient));
+        }
+
+    }
+
+    static abstract class CarryReduce {
+        private final int index;
+
+        protected CarryReduce(int index) {
+            this.index = index;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public abstract void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining);
+    }
+
+    static class Carry extends CarryReduce {
+        public Carry(int index) {
+            super(index);
+        }
+
+        public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) {
+            carry(out, params, prefix, getIndex());
+        }
+    }
+
+    static class Reduce extends CarryReduce {
+        public Reduce(int index) {
+            super(index);
+        }
+
+        public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) {
+            reduce(out, params, prefix, getIndex(), remaining);
+        }
+    }
+
+    static class FieldParams {
+        private final String className;
+        private final int bitsPerLimb;
+        private final int numLimbs;
+        private final int maxAdds;
+        private final int power;
+        private final Iterable<Term> terms;
+        private final List<CarryReduce> crSequence;
+        private final List<CarryReduce> smallCrSequence;
+
+        public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+                           Iterable<Term> terms, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) {
+            this.className = className;
+            this.bitsPerLimb = bitsPerLimb;
+            this.numLimbs = numLimbs;
+            this.maxAdds = maxAdds;
+            this.power = power;
+            this.terms = terms;
+            this.crSequence = crSequence;
+            this.smallCrSequence = smallCrSequence;
+        }
+
+        public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+                           BigInteger term, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) {
+            this.className = className;
+            this.bitsPerLimb = bitsPerLimb;
+            this.numLimbs = numLimbs;
+            this.maxAdds = maxAdds;
+            this.power = power;
+            this.crSequence = crSequence;
+            this.smallCrSequence = smallCrSequence;
+
+            terms = buildTerms(term);
+        }
+
+        private Iterable<Term> buildTerms(BigInteger sub) {
+            // split a large subtrahend into smaller terms that are aligned with limbs
+            List<Term> result = new ArrayList<Term>();
+            BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb);
+            int termIndex = 0;
+            while (!sub.equals(BigInteger.ZERO)) {
+                int coef = sub.mod(mod).intValue();
+                boolean plusOne = false;
+                if (coef > (1 << (bitsPerLimb - 1))) {
+                    coef = coef - (1 << bitsPerLimb);
+                    plusOne = true;
+                }
+                if (coef != 0) {
+                    int pow = termIndex * bitsPerLimb;
+                    result.add(new Term(pow, -coef));
+                }
+                sub = sub.shiftRight(bitsPerLimb);
+                if (plusOne) {
+                   sub = sub.add(BigInteger.ONE);
+                }
+                ++termIndex;
+            }
+            return result;
+        }
+
+        public String getClassName() {
+            return className;
+        }
+
+        public int getBitsPerLimb() {
+            return bitsPerLimb;
+        }
+
+        public int getNumLimbs() {
+            return numLimbs;
+        }
+
+        public int getMaxAdds() {
+            return maxAdds;
+        }
+
+        public int getPower() {
+            return power;
+        }
+
+        public Iterable<Term> getTerms() {
+            return terms;
+        }
+
+        public List<CarryReduce> getCrSequence() {
+            return crSequence;
+        }
+
+        public List<CarryReduce> getSmallCrSequence() {
+            return smallCrSequence;
+        }
+    }
+
+    static Collection<Carry> fullCarry(int numLimbs) {
+        List<Carry> result = new ArrayList<Carry>();
+        for (int i = 0; i < numLimbs - 1; i++) {
+            result.add(new Carry(i));
+        }
+        return result;
+    }
+
+    static Collection<Reduce> fullReduce(int numLimbs) {
+        List<Reduce> result = new ArrayList<Reduce>();
+        for (int i = numLimbs - 2; i >= 0; i--) {
+            result.add(new Reduce(i + numLimbs));
+        }
+        return result;
+    }
+
+    static List<CarryReduce> simpleCrSequence(int numLimbs) {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        for(int i = 0; i < 4; i++) {
+            result.addAll(fullCarry(2 * numLimbs - 1));
+            result.addAll(fullReduce(numLimbs));
+        }
+
+        return result;
+    }
+
+    static List<CarryReduce> simpleSmallCrSequence(int numLimbs) {
+        List<CarryReduce> result = new ArrayList<CarryReduce>();
+        // carry a few positions at the end
+        for (int i = numLimbs - 2; i < numLimbs; i++) {
+            result.add(new Carry(i));
+        }
+        // this carries out a single value that must be reduced back in
+        result.add(new Reduce(numLimbs));
+        // finish with a full carry
+        result.addAll(fullCarry(numLimbs));
+        return result;
+    }
+
+    private final String packageName;
+    private final String parentName;
+
+    public FieldGen(String packageName, String parentName) {
+        this.packageName = packageName;
+        this.parentName = parentName;
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        FieldGen gen = new FieldGen("sun.security.util.math.intpoly", "IntegerPolynomial");
+        for(FieldParams p : ALL_FIELDS) {
+            gen.generateFile(p);
+        }
+    }
+
+    private void generateFile(FieldParams params) throws IOException {
+        String text = generate(params);
+        String fileName = params.getClassName() + ".java";
+        PrintWriter out = new PrintWriter(new FileWriter(fileName));
+        out.println(text);
+        out.close();
+    }
+
+    static class CodeBuffer {
+
+        private int nextTemporary = 0;
+        private Set<String> temporaries = new HashSet<String>();
+        private StringBuffer buffer = new StringBuffer();
+        private int indent = 0;
+        private Class lastCR;
+        private int lastCrCount = 0;
+        private int crMethodBreakCount = 0;
+        private int crNumLimbs = 0;
+
+        public void incrIndent() {
+            indent++;
+        }
+
+        public void decrIndent() {
+            indent--;
+        }
+
+        public void newTempScope() {
+            nextTemporary = 0;
+            temporaries.clear();
+        }
+
+        public void appendLine(String s) {
+            appendIndent();
+            buffer.append(s + "\n");
+        }
+
+        public void appendLine() {
+            buffer.append("\n");
+        }
+
+        public String toString() {
+            return buffer.toString();
+        }
+
+        public void startCrSequence(int numLimbs) {
+            this.crNumLimbs = numLimbs;
+            lastCrCount = 0;
+            crMethodBreakCount = 0;
+            lastCR = null;
+        }
+        /*
+         * Record a carry/reduce of the specified type. This method is used to
+         * break up large carry/reduce sequences into multiple methods to make
+         * JIT/optimization easier
+         */
+        public void record(Class type) {
+            if (type == lastCR) {
+                lastCrCount++;
+            } else {
+
+                if (lastCrCount >= 8) {
+                    insertCrMethodBreak();
+                }
+
+                lastCR = type;
+                lastCrCount = 0;
+            }
+        }
+
+        private void insertCrMethodBreak() {
+
+            appendLine();
+
+            // call the new method
+            appendIndent();
+            append("carryReduce" + crMethodBreakCount + "(r");
+            for(int i = 0; i < crNumLimbs; i++) {
+                append(", c" + i);
+            }
+            // temporaries are not live between operations, no need to send
+            append(");\n");
+
+            decrIndent();
+            appendLine("}");
+
+            // make the method
+            appendIndent();
+            append("void carryReduce" + crMethodBreakCount + "(long[] r");
+            for(int i = 0; i < crNumLimbs; i++) {
+                append (", long c" + i);
+            }
+            append(") {\n");
+            incrIndent();
+            // declare temporaries
+            for(String temp : temporaries) {
+                appendLine("long " + temp + ";");
+            }
+            append("\n");
+
+            crMethodBreakCount++;
+        }
+
+        public String getTemporary(String type, String value) {
+            Iterator<String> iter = temporaries.iterator();
+            if(iter.hasNext()) {
+                String result = iter.next();
+                iter.remove();
+                appendLine(result + " = " + value + ";");
+                return result;
+            } else {
+                String result = "t" + (nextTemporary++);
+                appendLine(type + " " + result + " = " + value + ";");
+                return result;
+            }
+        }
+
+        public void freeTemporary(String temp) {
+            temporaries.add(temp);
+        }
+
+        public void appendIndent() {
+            for(int i = 0; i < indent; i++) {
+                buffer.append("    ");
+            }
+        }
+
+        public void append(String s) {
+            buffer.append(s);
+        }
+    }
+
+    private String generate(FieldParams params) throws IOException {
+        CodeBuffer result = new CodeBuffer();
+        String header = readHeader();
+        result.appendLine(header);
+
+        if (packageName != null) {
+            result.appendLine("package " + packageName + ";");
+            result.appendLine();
+        }
+        result.appendLine("import java.math.BigInteger;");
+
+        result.appendLine("public class " + params.getClassName() + " extends " + this.parentName + " {");
+        result.incrIndent();
+
+        result.appendLine("private static final int BITS_PER_LIMB = " + params.getBitsPerLimb() + ";");
+        result.appendLine("private static final int NUM_LIMBS = " + params.getNumLimbs() + ";");
+        result.appendLine("private static final int MAX_ADDS = " + params.getMaxAdds() + ";");
+        result.appendLine("public static final BigInteger MODULUS = evaluateModulus();");
+        result.appendLine("private static final long CARRY_ADD = 1 << " + (params.getBitsPerLimb() - 1) + ";");
+        if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) {
+            result.appendLine("private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);");
+        }
+        int termIndex = 0;
+
+        result.appendLine("public " + params.getClassName() + "() {");
+        result.appendLine();
+        result.appendLine("    super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);");
+        result.appendLine();
+        result.appendLine("}");
+
+        result.appendLine("private static BigInteger evaluateModulus() {");
+        result.incrIndent();
+        result.appendLine("BigInteger result = BigInteger.valueOf(2).pow(" + params.getPower() + ");");
+        for(Term t : params.getTerms()) {
+            boolean subtract = false;
+            int coefValue = t.getCoefficient();
+            if (coefValue < 0) {
+                coefValue = 0 - coefValue;
+                subtract = true;
+            }
+            String coefExpr = "BigInteger.valueOf(" + coefValue + ")";
+            String powExpr = "BigInteger.valueOf(2).pow(" + t.getPower() + ")";
+            String termExpr = "ERROR";
+            if (t.getPower() == 0) {
+                termExpr = coefExpr;
+            } else if (coefValue == 1) {
+                termExpr = powExpr;
+            } else {
+                termExpr = powExpr + ".multiply(" + coefExpr + ")";
+            }
+            if (subtract) {
+                result.appendLine("result = result.subtract(" + termExpr + ");");
+            } else {
+                result.appendLine("result = result.add(" + termExpr + ");");
+            }
+        }
+        result.appendLine("return result;");
+        result.decrIndent();
+        result.appendLine("}");
+
+        result.appendLine("@Override");
+        result.appendLine("protected void finalCarryReduceLast(long[] limbs) {");
+        result.incrIndent();
+        int extraBits = params.getBitsPerLimb() * params.getNumLimbs() - params.getPower();
+        int highBits = params.getBitsPerLimb() - extraBits;
+        result.appendLine("long c = limbs[" + (params.getNumLimbs() - 1) + "] >> " + highBits + ";");
+        result.appendLine("limbs[" + (params.getNumLimbs() - 1) + "] -= c << " + highBits + ";");
+        for (Term t : params.getTerms()) {
+            int reduceBits = params.getPower() + extraBits - t.getPower();
+            int negatedCoefficient = -1 * t.getCoefficient();
+            modReduceInBits(result, params, true, "limbs", params.getNumLimbs(), reduceBits, negatedCoefficient, "c");
+        }
+        result.decrIndent();
+        result.appendLine("}");
+
+        // full carry/reduce sequence
+        result.appendIndent();
+        result.append("private void carryReduce(long[] r, ");
+        for(int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+            result.append ("long c" + i);
+            if (i < 2 * params.getNumLimbs() - 2) {
+                result.append(", ");
+            }
+        }
+        result.append(") {\n");
+        result.newTempScope();
+        result.incrIndent();
+        result.appendLine("long c" + (2 * params.getNumLimbs() - 1) + " = 0;");
+        write(result, params.getCrSequence(), params, "c", 2 * params.getNumLimbs());
+        result.appendLine();
+        for (int i = 0; i < params.getNumLimbs(); i++) {
+            result.appendLine("r[" + i + "] = c" + i + ";");
+        }
+        result.decrIndent();
+        result.appendLine("}");
+
+        // small carry/reduce sequence
+        result.appendIndent();
+        result.append("private void carryReduce(long[] r, ");
+        for(int i = 0; i < params.getNumLimbs(); i++) {
+            result.append ("long c" + i);
+            if (i < params.getNumLimbs() - 1) {
+                result.append(", ");
+            }
+        }
+        result.append(") {\n");
+        result.newTempScope();
+        result.incrIndent();
+        result.appendLine("long c" + params.getNumLimbs() + " = 0;");
+        write(result, params.getSmallCrSequence(), params, "c", params.getNumLimbs() + 1);
+        result.appendLine();
+        for (int i = 0; i < params.getNumLimbs(); i++) {
+            result.appendLine("r[" + i + "] = c" + i + ";");
+        }
+        result.decrIndent();
+        result.appendLine("}");
+
+        result.appendLine("@Override");
+        result.appendLine("protected void mult(long[] a, long[] b, long[] r) {");
+        result.incrIndent();
+        for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+            result.appendIndent();
+            result.append("long c" + i + " = ");
+            int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+            int endJ = Math.min(params.getNumLimbs(), i + 1);
+            for (int j = startJ; j < endJ; j++) {
+                int bIndex = i - j;
+                result.append("(a[" + j + "] * b[" + bIndex + "])");
+                if (j < endJ - 1) {
+                    result.append(" + ");
+                }
+            }
+            result.append(";\n");
+        }
+        result.appendLine();
+        result.appendIndent();
+        result.append("carryReduce(r, ");
+        for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+            result.append("c" + i);
+            if (i < 2 * params.getNumLimbs() - 2) {
+                result.append(", ");
+            }
+        }
+        result.append(");\n");
+        result.decrIndent();
+        result.appendLine("}");
+
+        result.appendLine("@Override");
+        result.appendLine("protected void reduce(long[] a) {");
+        result.incrIndent();
+        result.appendIndent();
+        result.append("carryReduce(a, ");
+        for (int i = 0; i < params.getNumLimbs(); i++) {
+            result.append("a[" + i + "]");
+            if (i < params.getNumLimbs() - 1) {
+                result.append(", ");
+            }
+        }
+        result.append(");\n");
+        result.decrIndent();
+        result.appendLine("}");
+
+        result.appendLine("@Override");
+        result.appendLine("protected void square(long[] a, long[] r) {");
+        result.incrIndent();
+        for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+            result.appendIndent();
+            result.append("long c" + i + " = ");
+            int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+            int endJ = Math.min(params.getNumLimbs(), i + 1);
+            int jDiff = endJ - startJ;
+            if (jDiff > 1) {
+                result.append("2 * (");
+            }
+            for (int j = 0; j < jDiff / 2; j++) {
+                int aIndex = j + startJ;
+                int bIndex = i - aIndex;
+                result.append("(a[" + aIndex + "] * a[" + bIndex + "])");
+                if (j < (jDiff / 2) - 1) {
+                    result.append(" + ");
+                }
+            }
+            if (jDiff > 1) {
+                result.append(")");
+            }
+            if (jDiff % 2 == 1) {
+                int aIndex = i / 2;
+                if (jDiff > 1) {
+                    result.append (" + ");
+                }
+                result.append("(a[" + aIndex + "] * a[" + aIndex + "])");
+            }
+            result.append(";\n");
+        }
+        result.appendLine();
+        result.appendIndent();
+        result.append("carryReduce(r, ");
+        for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+            result.append("c" + i);
+            if (i < 2 * params.getNumLimbs() - 2) {
+                result.append(", ");
+            }
+        }
+        result.append(");\n");
+        result.decrIndent();
+        result.appendLine("}");
+
+        result.decrIndent();
+        result.appendLine("}"); // end class
+
+        return result.toString();
+    }
+
+    private static void write(CodeBuffer out, List<CarryReduce> sequence, FieldParams params, String prefix, int numLimbs) {
+
+        out.startCrSequence(numLimbs);
+        for (int i = 0; i < sequence.size(); i++) {
+            CarryReduce cr = sequence.get(i);
+            Iterator<CarryReduce> remainingIter = sequence.listIterator(i + 1);
+            List<CarryReduce> remaining = new ArrayList<CarryReduce>();
+            remainingIter.forEachRemaining(remaining::add);
+            cr.write(out, params, prefix, remaining);
+        }
+    }
+
+    private static void reduce(CodeBuffer out, FieldParams params, String prefix, int index, Iterable<CarryReduce> remaining) {
+
+        out.record(Reduce.class);
+
+        out.appendLine("//reduce from position " + index);
+        String reduceFrom = indexedExpr(false, prefix, index);
+        boolean referenced = false;
+        for (CarryReduce cr : remaining) {
+            if(cr.index == index) {
+                referenced = true;
+            }
+        }
+        for (Term t : params.getTerms()) {
+            int reduceBits = params.getPower() - t.getPower();
+            int negatedCoefficient = -1 * t.getCoefficient();
+            modReduceInBits(out, params, false, prefix, index, reduceBits, negatedCoefficient, reduceFrom);
+        }
+        if (referenced) {
+            out.appendLine(reduceFrom + " = 0;");
+        }
+    }
+
+    private static void carry(CodeBuffer out, FieldParams params, String prefix, int index) {
+
+        out.record(Carry.class);
+
+        out.appendLine("//carry from position " + index);
+        String carryFrom = prefix + index;
+        String carryTo = prefix + (index + 1);
+        String carry = "(" + carryFrom + " + CARRY_ADD) >> " + params.getBitsPerLimb();
+        String temp = out.getTemporary("long", carry);
+        out.appendLine(carryFrom + " -= (" + temp + " << " + params.getBitsPerLimb() + ");");
+        out.appendLine(carryTo + " += " + temp + ";");
+        out.freeTemporary(temp);
+    }
+
+    private static String indexedExpr(boolean isArray, String prefix, int index) {
+        String result = prefix + index;
+        if (isArray) {
+            result = prefix + "[" + index + "]";
+        }
+        return result;
+    }
+
+    private static void modReduceInBits(CodeBuffer result, FieldParams params, boolean isArray, String prefix, int index, int reduceBits, int coefficient, String c) {
+
+        String x = coefficient + " * " + c;
+        String accOp = "+=";
+        String temp = null;
+        if (coefficient == 1) {
+            x = c;
+        } else if (coefficient == -1) {
+            x = c;
+            accOp = "-=";
+        } else {
+            temp = result.getTemporary("long", x);
+            x = temp;
+        }
+
+        if (reduceBits % params.getBitsPerLimb() == 0) {
+            int pos = reduceBits / params.getBitsPerLimb();
+            result.appendLine(indexedExpr(isArray, prefix, (index - pos)) + " " + accOp + " " + x + ";");
+        } else {
+            int secondPos = reduceBits / params.getBitsPerLimb();
+            int bitOffset = (secondPos + 1) * params.getBitsPerLimb() - reduceBits;
+            int rightBitOffset = params.getBitsPerLimb() - bitOffset;
+            result.appendLine(indexedExpr(isArray, prefix, (index - (secondPos + 1))) + " " + accOp + " (" + x + " << " + bitOffset + ") & LIMB_MASK;");
+            result.appendLine(indexedExpr(isArray, prefix, (index - secondPos)) + " " + accOp + " " + x + " >> " + rightBitOffset + ";");
+        }
+
+        if (temp != null) {
+            result.freeTemporary(temp);
+        }
+    }
+
+    private String readHeader() throws IOException {
+        BufferedReader reader = Files.newBufferedReader(Paths.get("header.txt"));
+        StringBuffer result = new StringBuffer();
+        reader.lines().forEach(s -> result.append(s + "\n"));
+        return result.toString();
+    }
+}
+
+FieldGen.main(null);
+
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java	Wed Dec 12 08:38:45 2018 -0500
@@ -69,14 +69,25 @@
     private final BigInteger modulus;
     protected final int bitsPerLimb;
     private final long[] posModLimbs;
+    private final int maxAdds;
+
+    /**
+     * Reduce an IntegerPolynomial representation (a) and store the result
+     * in a. Requires that a.length == numLimbs.
+     */
+    protected abstract void reduce(long[] a);
 
     /**
      * Multiply an IntegerPolynomial representation (a) with a long (b) and
-     * store the result in an IntegerPolynomial representation (r). Requires
-     * that a.length == r.length == numLimbs. It is allowed for a and r to be
-     * the same array.
+     * store the result in an IntegerPolynomial representation in a. Requires
+     * that a.length == numLimbs.
      */
-    protected abstract void multByInt(long[] a, long b, long[] r);
+    protected void multByInt(long[] a, long b) {
+        for (int i = 0; i < a.length; i++) {
+            a[i] *= b;
+        }
+        reduce(a);
+    }
 
     /**
      * Multiply two IntegerPolynomial representations (a and b) and store the
@@ -96,12 +107,14 @@
 
     IntegerPolynomial(int bitsPerLimb,
                       int numLimbs,
+                      int maxAdds,
                       BigInteger modulus) {
 
 
         this.numLimbs = numLimbs;
         this.modulus = modulus;
         this.bitsPerLimb = bitsPerLimb;
+        this.maxAdds = maxAdds;
 
         posModLimbs = setPosModLimbs();
     }
@@ -116,6 +129,10 @@
         return numLimbs;
     }
 
+    public int getMaxAdds() {
+        return maxAdds;
+    }
+
     @Override
     public BigInteger getSize() {
         return modulus;
@@ -155,12 +172,22 @@
      */
     protected void encode(ByteBuffer buf, int length, byte highByte,
                           long[] result) {
+
         int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte);
         int numBits = 8 * length + numHighBits;
-        int maxBits = bitsPerLimb * result.length;
-        if (numBits > maxBits) {
-            throw new ArithmeticException("Value is too large.");
+        int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb;
+        if (requiredLimbs > numLimbs) {
+            long[] temp = new long[requiredLimbs];
+            encodeSmall(buf, length, highByte, temp);
+            // encode does a full carry/reduce
+            System.arraycopy(temp, 0, result, 0, result.length);
+        } else {
+            encodeSmall(buf, length, highByte, result);
         }
+    }
+
+    protected void encodeSmall(ByteBuffer buf, int length, byte highByte,
+                               long[] result) {
 
         int limbIndex = 0;
         long curLimbValue = 0;
@@ -195,10 +222,10 @@
             }
         }
 
-        if (limbIndex < numLimbs) {
+        if (limbIndex < result.length) {
             result[limbIndex++] = curLimbValue;
         }
-        Arrays.fill(result, limbIndex, numLimbs, 0);
+        Arrays.fill(result, limbIndex, result.length, 0);
 
         postEncodeCarry(result);
     }
@@ -211,8 +238,10 @@
         encode(buf, length, highByte, result);
     }
 
+    // Encode does not produce compressed limbs. A simplified carry/reduce
+    // operation can be used to compress the limbs.
     protected void postEncodeCarry(long[] v) {
-        carry(v);
+        reduce(v);
     }
 
     public ImmutableElement getElement(byte[] v, int offset, int length,
@@ -222,7 +251,7 @@
 
         encode(v, offset, length, highByte, result);
 
-        return new ImmutableElement(result, true);
+        return new ImmutableElement(result, 0);
     }
 
     protected BigInteger evaluate(long[] limbs) {
@@ -387,6 +416,20 @@
     }
 
     /**
+     * Branch-free conditional assignment of b to a. Requires that set is 0 or
+     * 1, and that a.length == b.length. If set==0, then the values of a and b
+     * will be unchanged. If set==1, then the values of b will be assigned to a.
+     * The behavior is undefined if swap has any value other than 0 or 1.
+     */
+    protected static void conditionalAssign(int set, long[] a, long[] b) {
+        int maskValue = 0 - set;
+        for (int i = 0; i < a.length; i++) {
+            long dummyLimbs = maskValue & (a[i] ^ b[i]);
+            a[i] = dummyLimbs ^ a[i];
+        }
+    }
+
+    /**
      * Branch-free conditional swap of a and b. Requires that swap is 0 or 1,
      * and that a.length == b.length. If swap==0, then the values of a and b
      * will be unchanged. If swap==1, then the values of a and b will be
@@ -442,7 +485,7 @@
     private abstract class Element implements IntegerModuloP {
 
         protected long[] limbs;
-        protected boolean summand = false;
+        protected int numAdds;
 
         public Element(BigInteger v) {
             limbs = new long[numLimbs];
@@ -450,19 +493,19 @@
         }
 
         public Element(boolean v) {
-            limbs = new long[numLimbs];
-            limbs[0] = v ? 1l : 0l;
-            summand = true;
+            this.limbs = new long[numLimbs];
+            this.limbs[0] = v ? 1l : 0l;
+            this.numAdds = 0;
         }
 
-        private Element(long[] limbs, boolean summand) {
+        private Element(long[] limbs, int numAdds) {
             this.limbs = limbs;
-            this.summand = summand;
+            this.numAdds = numAdds;
         }
 
         private void setValue(BigInteger v) {
             setLimbsValue(v, limbs);
-            summand = true;
+            this.numAdds = 0;
         }
 
         @Override
@@ -477,14 +520,18 @@
 
         @Override
         public MutableElement mutable() {
-            return new MutableElement(limbs.clone(), summand);
+            return new MutableElement(limbs.clone(), numAdds);
+        }
+
+        protected boolean isSummand() {
+            return numAdds < maxAdds;
         }
 
         @Override
         public ImmutableElement add(IntegerModuloP genB) {
 
             Element b = (Element) genB;
-            if (!(summand && b.summand)) {
+            if (!(isSummand() && b.isSummand())) {
                 throw new ArithmeticException("Not a valid summand");
             }
 
@@ -493,7 +540,8 @@
                 newLimbs[i] = limbs[i] + b.limbs[i];
             }
 
-            return new ImmutableElement(newLimbs, false);
+            int newNumAdds = Math.max(numAdds, b.numAdds) + 1;
+            return new ImmutableElement(newLimbs, newNumAdds);
         }
 
         @Override
@@ -504,7 +552,7 @@
                 newLimbs[i] = -limbs[i];
             }
 
-            ImmutableElement result = new ImmutableElement(newLimbs, summand);
+            ImmutableElement result = new ImmutableElement(newLimbs, numAdds);
             return result;
         }
 
@@ -524,43 +572,52 @@
 
             long[] newLimbs = new long[limbs.length];
             mult(limbs, b.limbs, newLimbs);
-            return new ImmutableElement(newLimbs, true);
+            return new ImmutableElement(newLimbs, 0);
         }
 
         @Override
         public ImmutableElement square() {
             long[] newLimbs = new long[limbs.length];
             IntegerPolynomial.this.square(limbs, newLimbs);
-            return new ImmutableElement(newLimbs, true);
+            return new ImmutableElement(newLimbs, 0);
         }
 
         public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
 
             Element other = (Element) arg;
-            if (!(summand && other.summand)) {
+            if (!(isSummand() && other.isSummand())) {
                 throw new ArithmeticException("Not a valid summand");
             }
             addLimbsModPowerTwo(limbs, other.limbs, result);
         }
 
         public void asByteArray(byte[] result) {
-            if (!summand) {
+            if (!isSummand()) {
                 throw new ArithmeticException("Not a valid summand");
             }
             limbsToByteArray(limbs, result);
         }
     }
 
-    private class MutableElement extends Element
+    protected class MutableElement extends Element
         implements MutableIntegerModuloP {
 
-        protected MutableElement(long[] limbs, boolean summand) {
-            super(limbs, summand);
+        protected MutableElement(long[] limbs, int numAdds) {
+            super(limbs, numAdds);
         }
 
         @Override
         public ImmutableElement fixed() {
-            return new ImmutableElement(limbs.clone(), summand);
+            return new ImmutableElement(limbs.clone(), numAdds);
+        }
+
+        @Override
+        public void conditionalSet(IntegerModuloP b, int set) {
+
+            Element other = (Element) b;
+
+            conditionalAssign(set, limbs, other.limbs);
+            numAdds = other.numAdds;
         }
 
         @Override
@@ -569,9 +626,9 @@
             MutableElement other = (MutableElement) b;
 
             conditionalSwap(swap, limbs, other.limbs);
-            boolean summandTemp = summand;
-            summand = other.summand;
-            other.summand = summandTemp;
+            int numAddsTemp = numAdds;
+            numAdds = other.numAdds;
+            other.numAdds = numAddsTemp;
         }
 
 
@@ -580,7 +637,7 @@
             Element other = (Element) v;
 
             System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length);
-            summand = other.summand;
+            numAdds = other.numAdds;
             return this;
         }
 
@@ -589,7 +646,7 @@
                                        int length, byte highByte) {
 
             encode(arr, offset, length, highByte, limbs);
-            summand = true;
+            this.numAdds = 0;
 
             return this;
         }
@@ -599,7 +656,7 @@
                                        byte highByte) {
 
             encode(buf, length, highByte, limbs);
-            summand = true;
+            numAdds = 0;
 
             return this;
         }
@@ -608,15 +665,15 @@
         public MutableElement setProduct(IntegerModuloP genB) {
             Element b = (Element) genB;
             mult(limbs, b.limbs, limbs);
-            summand = true;
+            numAdds = 0;
             return this;
         }
 
         @Override
         public MutableElement setProduct(SmallValue v) {
             int value = ((Limb) v).value;
-            multByInt(limbs, value, limbs);
-            summand = true;
+            multByInt(limbs, value);
+            numAdds = 0;
             return this;
         }
 
@@ -624,7 +681,7 @@
         public MutableElement setSum(IntegerModuloP genB) {
 
             Element b = (Element) genB;
-            if (!(summand && b.summand)) {
+            if (!(isSummand() && b.isSummand())) {
                 throw new ArithmeticException("Not a valid summand");
             }
 
@@ -632,7 +689,7 @@
                 limbs[i] = limbs[i] + b.limbs[i];
             }
 
-            summand = false;
+            numAdds = Math.max(numAdds, b.numAdds) + 1;
             return this;
         }
 
@@ -640,7 +697,7 @@
         public MutableElement setDifference(IntegerModuloP genB) {
 
             Element b = (Element) genB;
-            if (!(summand && b.summand)) {
+            if (!(isSummand() && b.isSummand())) {
                 throw new ArithmeticException("Not a valid summand");
             }
 
@@ -648,16 +705,33 @@
                 limbs[i] = limbs[i] - b.limbs[i];
             }
 
+            numAdds = Math.max(numAdds, b.numAdds) + 1;
             return this;
         }
 
         @Override
         public MutableElement setSquare() {
             IntegerPolynomial.this.square(limbs, limbs);
-            summand = true;
+            numAdds = 0;
             return this;
         }
 
+        @Override
+        public MutableElement setAdditiveInverse() {
+
+            for (int i = 0; i < limbs.length; i++) {
+                limbs[i] = -limbs[i];
+            }
+            return this;
+        }
+
+        @Override
+        public MutableElement setReduced() {
+
+            reduce(limbs);
+            numAdds = 0;
+            return this;
+        }
     }
 
     class ImmutableElement extends Element implements ImmutableIntegerModuloP {
@@ -670,8 +744,8 @@
             super(v);
         }
 
-        protected ImmutableElement(long[] limbs, boolean summand) {
-            super(limbs, summand);
+        protected ImmutableElement(long[] limbs, int numAdds) {
+            super(limbs, numAdds);
         }
 
         @Override
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java	Wed Dec 12 08:38:45 2018 -0500
@@ -45,7 +45,7 @@
         = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
 
     public IntegerPolynomial1305() {
-        super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+        super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
     }
 
     protected void mult(long[] a, long[] b, long[] r) {
@@ -96,15 +96,6 @@
         carry(r);
     }
 
-    protected void multByInt(long[] a, long b, long[] r) {
-
-        for (int i = 0; i < a.length; i++) {
-            r[i] = a[i] * b;
-        }
-
-        reduce(r);
-    }
-
     @Override
     protected void square(long[] a, long[] r) {
         // Use grade-school multiplication with a simple squaring optimization.
@@ -199,7 +190,12 @@
         return x >> BITS_PER_LIMB;
     }
 
+    @Override
+    protected void postEncodeCarry(long[] v) {
+        // not needed because carry is unsigned
+    }
 
+    @Override
     protected void reduce(long[] limbs) {
         long carry3 = carryOut(limbs, 3);
         long new4 = carry3 + limbs[4];
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java	Wed Dec 12 08:38:45 2018 -0500
@@ -48,7 +48,7 @@
     private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET;
 
     public IntegerPolynomial25519() {
-        super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+        super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
     }
 
     @Override
@@ -60,6 +60,26 @@
     }
 
     @Override
+    protected void reduce(long[] a) {
+
+        // carry(8, 2)
+        long carry8 = carryValue(a[8]);
+        a[8] -= (carry8 << BITS_PER_LIMB);
+        a[9] += carry8;
+
+        long carry9 = carryValue(a[9]);
+        a[9] -= (carry9 << BITS_PER_LIMB);
+
+        // reduce(0, 1)
+        long reducedValue10 = (carry9 * SUBTRAHEND);
+        a[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
+        a[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
+
+        // carry(0, 9)
+        carry(a, 0, 9);
+    }
+
+    @Override
     protected void mult(long[] a, long[] b, long[] r) {
 
         // Use grade-school multiplication into primitives to avoid the
@@ -153,28 +173,6 @@
         carry(r, 0, 9);
     }
 
-    protected void multByInt(long[] a, long b, long[] r) {
-        for (int i = 0; i < a.length; i++) {
-            r[i] = a[i] * b;
-        }
-
-        // carry(8, 2)
-        long carry8 = carryValue(r[8]);
-        r[8] -= (carry8 << BITS_PER_LIMB);
-        r[9] += carry8;
-
-        long carry9 = carryValue(r[9]);
-        r[9] -= (carry9 << BITS_PER_LIMB);
-
-        // reduce(0, 1)
-        long reducedValue10 = (carry9 * SUBTRAHEND);
-        r[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
-        r[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
-
-        // carry(0, 9)
-        carry(r, 0, 9);
-    }
-
     @Override
     protected void square(long[] a, long[] r) {
 
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java	Wed Dec 12 08:38:45 2018 -0500
@@ -42,7 +42,7 @@
             .subtract(BigInteger.valueOf(1));
 
     public IntegerPolynomial448() {
-        super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
+        super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
     }
 
     private void modReduceIn(long[] limbs, int index, long x) {
@@ -58,6 +58,25 @@
     }
 
     @Override
+    protected void reduce(long[] a) {
+
+        // carry(14, 2)
+        long carry14 = carryValue(a[14]);
+        a[14] -= (carry14 << BITS_PER_LIMB);
+        a[15] += carry14;
+
+        long carry15 = carryValue(a[15]);
+        a[15] -= (carry15 << BITS_PER_LIMB);
+
+        // reduce(0, 1)
+        a[0] += carry15;
+        a[8] += carry15;
+
+        // carry(0, 15)
+        carry(a, 0, 15);
+    }
+
+    @Override
     protected void mult(long[] a, long[] b, long[] r) {
 
         // Use grade-school multiplication into primitives to avoid the
@@ -176,27 +195,6 @@
         carry(r, 0, 15);
     }
 
-    protected void multByInt(long[] a, long b, long[] r) {
-        for (int i = 0; i < a.length; i++) {
-            r[i] = a[i] * b;
-        }
-
-        // carry(14, 2)
-        long carry14 = carryValue(r[14]);
-        r[14] -= (carry14 << BITS_PER_LIMB);
-        r[15] += carry14;
-
-        long carry15 = carryValue(r[15]);
-        r[15] -= (carry15 << BITS_PER_LIMB);
-
-        // reduce(0, 1)
-        r[0] += carry15;
-        r[8] += carry15;
-
-        // carry(0, 15)
-        carry(r, 0, 15);
-    }
-
     @Override
     protected void square(long[] a, long[] r) {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP256 extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 26;
+    private static final int NUM_LIMBS = 10;
+    private static final int MAX_ADDS = 2;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 25;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public IntegerPolynomialP256() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(256);
+        result = result.subtract(BigInteger.valueOf(2).pow(224));
+        result = result.add(BigInteger.valueOf(2).pow(192));
+        result = result.add(BigInteger.valueOf(2).pow(96));
+        result = result.subtract(BigInteger.valueOf(1));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[9] >> 22;
+        limbs[9] -= c << 22;
+        limbs[8] += (c << 16) & LIMB_MASK;
+        limbs[9] += c >> 10;
+        limbs[7] -= (c << 10) & LIMB_MASK;
+        limbs[8] -= c >> 16;
+        limbs[3] -= (c << 18) & LIMB_MASK;
+        limbs[4] -= c >> 8;
+        limbs[0] += c;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+        long c19 = 0;
+        //reduce from position 18
+        c16 += (c18 << 20) & LIMB_MASK;
+        c17 += c18 >> 6;
+        c15 -= (c18 << 14) & LIMB_MASK;
+        c16 -= c18 >> 12;
+        c11 -= (c18 << 22) & LIMB_MASK;
+        c12 -= c18 >> 4;
+        c8 += (c18 << 4) & LIMB_MASK;
+        c9 += c18 >> 22;
+        //reduce from position 17
+        c15 += (c17 << 20) & LIMB_MASK;
+        c16 += c17 >> 6;
+        c14 -= (c17 << 14) & LIMB_MASK;
+        c15 -= c17 >> 12;
+        c10 -= (c17 << 22) & LIMB_MASK;
+        c11 -= c17 >> 4;
+        c7 += (c17 << 4) & LIMB_MASK;
+        c8 += c17 >> 22;
+        //reduce from position 16
+        c14 += (c16 << 20) & LIMB_MASK;
+        c15 += c16 >> 6;
+        c13 -= (c16 << 14) & LIMB_MASK;
+        c14 -= c16 >> 12;
+        c9 -= (c16 << 22) & LIMB_MASK;
+        c10 -= c16 >> 4;
+        c6 += (c16 << 4) & LIMB_MASK;
+        c7 += c16 >> 22;
+        //reduce from position 15
+        c13 += (c15 << 20) & LIMB_MASK;
+        c14 += c15 >> 6;
+        c12 -= (c15 << 14) & LIMB_MASK;
+        c13 -= c15 >> 12;
+        c8 -= (c15 << 22) & LIMB_MASK;
+        c9 -= c15 >> 4;
+        c5 += (c15 << 4) & LIMB_MASK;
+        c6 += c15 >> 22;
+        //reduce from position 14
+        c12 += (c14 << 20) & LIMB_MASK;
+        c13 += c14 >> 6;
+        c11 -= (c14 << 14) & LIMB_MASK;
+        c12 -= c14 >> 12;
+        c7 -= (c14 << 22) & LIMB_MASK;
+        c8 -= c14 >> 4;
+        c4 += (c14 << 4) & LIMB_MASK;
+        c5 += c14 >> 22;
+        //reduce from position 13
+        c11 += (c13 << 20) & LIMB_MASK;
+        c12 += c13 >> 6;
+        c10 -= (c13 << 14) & LIMB_MASK;
+        c11 -= c13 >> 12;
+        c6 -= (c13 << 22) & LIMB_MASK;
+        c7 -= c13 >> 4;
+        c3 += (c13 << 4) & LIMB_MASK;
+        c4 += c13 >> 22;
+        //reduce from position 12
+        c10 += (c12 << 20) & LIMB_MASK;
+        c11 += c12 >> 6;
+        c9 -= (c12 << 14) & LIMB_MASK;
+        c10 -= c12 >> 12;
+        c5 -= (c12 << 22) & LIMB_MASK;
+        c6 -= c12 >> 4;
+        c2 += (c12 << 4) & LIMB_MASK;
+        c3 += c12 >> 22;
+        //reduce from position 11
+        c9 += (c11 << 20) & LIMB_MASK;
+        c10 += c11 >> 6;
+        c8 -= (c11 << 14) & LIMB_MASK;
+        c9 -= c11 >> 12;
+        c4 -= (c11 << 22) & LIMB_MASK;
+        c5 -= c11 >> 4;
+        c1 += (c11 << 4) & LIMB_MASK;
+        c2 += c11 >> 22;
+        //reduce from position 10
+        c8 += (c10 << 20) & LIMB_MASK;
+        c9 += c10 >> 6;
+        c7 -= (c10 << 14) & LIMB_MASK;
+        c8 -= c10 >> 12;
+        c3 -= (c10 << 22) & LIMB_MASK;
+        c4 -= c10 >> 4;
+        c0 += (c10 << 4) & LIMB_MASK;
+        c1 += c10 >> 22;
+        c10 = 0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+
+        //carry from position 8
+        long t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 26;
+        c9 -= (t0 << 26);
+        c10 += t0;
+        //reduce from position 10
+        c8 += (c10 << 20) & LIMB_MASK;
+        c9 += c10 >> 6;
+        c7 -= (c10 << 14) & LIMB_MASK;
+        c8 -= c10 >> 12;
+        c3 -= (c10 << 22) & LIMB_MASK;
+        c4 -= c10 >> 4;
+        c0 += (c10 << 4) & LIMB_MASK;
+        c1 += c10 >> 22;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+        long c10 = 0;
+        //carry from position 8
+        long t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 26;
+        c9 -= (t0 << 26);
+        c10 += t0;
+        //reduce from position 10
+        c8 += (c10 << 20) & LIMB_MASK;
+        c9 += c10 >> 6;
+        c7 -= (c10 << 14) & LIMB_MASK;
+        c8 -= c10 >> 12;
+        c3 -= (c10 << 22) & LIMB_MASK;
+        c4 -= c10 >> 4;
+        c0 += (c10 << 4) & LIMB_MASK;
+        c1 += c10 >> 22;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+        long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+        long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+        long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+        long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+        long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+        long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+        long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+        long c18 = (a[9] * b[9]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[8] * a[9]));
+        long c18 = (a[9] * a[9]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,431 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP384 extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 28;
+    private static final int NUM_LIMBS = 14;
+    private static final int MAX_ADDS = 2;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 27;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public IntegerPolynomialP384() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(384);
+        result = result.subtract(BigInteger.valueOf(2).pow(128));
+        result = result.subtract(BigInteger.valueOf(2).pow(96));
+        result = result.add(BigInteger.valueOf(2).pow(32));
+        result = result.subtract(BigInteger.valueOf(1));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[13] >> 20;
+        limbs[13] -= c << 20;
+        limbs[4] += (c << 16) & LIMB_MASK;
+        limbs[5] += c >> 12;
+        limbs[3] += (c << 12) & LIMB_MASK;
+        limbs[4] += c >> 16;
+        limbs[1] -= (c << 4) & LIMB_MASK;
+        limbs[2] -= c >> 24;
+        limbs[0] += c;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+        long c27 = 0;
+        //reduce from position 26
+        c16 += (c26 << 24) & LIMB_MASK;
+        c17 += c26 >> 4;
+        c15 += (c26 << 20) & LIMB_MASK;
+        c16 += c26 >> 8;
+        c13 -= (c26 << 12) & LIMB_MASK;
+        c14 -= c26 >> 16;
+        c12 += (c26 << 8) & LIMB_MASK;
+        c13 += c26 >> 20;
+        //reduce from position 25
+        c15 += (c25 << 24) & LIMB_MASK;
+        c16 += c25 >> 4;
+        c14 += (c25 << 20) & LIMB_MASK;
+        c15 += c25 >> 8;
+        c12 -= (c25 << 12) & LIMB_MASK;
+        c13 -= c25 >> 16;
+        c11 += (c25 << 8) & LIMB_MASK;
+        c12 += c25 >> 20;
+        //reduce from position 24
+        c14 += (c24 << 24) & LIMB_MASK;
+        c15 += c24 >> 4;
+        c13 += (c24 << 20) & LIMB_MASK;
+        c14 += c24 >> 8;
+        c11 -= (c24 << 12) & LIMB_MASK;
+        c12 -= c24 >> 16;
+        c10 += (c24 << 8) & LIMB_MASK;
+        c11 += c24 >> 20;
+        //reduce from position 23
+        c13 += (c23 << 24) & LIMB_MASK;
+        c14 += c23 >> 4;
+        c12 += (c23 << 20) & LIMB_MASK;
+        c13 += c23 >> 8;
+        c10 -= (c23 << 12) & LIMB_MASK;
+        c11 -= c23 >> 16;
+        c9 += (c23 << 8) & LIMB_MASK;
+        c10 += c23 >> 20;
+        //reduce from position 22
+        c12 += (c22 << 24) & LIMB_MASK;
+        c13 += c22 >> 4;
+        c11 += (c22 << 20) & LIMB_MASK;
+        c12 += c22 >> 8;
+        c9 -= (c22 << 12) & LIMB_MASK;
+        c10 -= c22 >> 16;
+        c8 += (c22 << 8) & LIMB_MASK;
+        c9 += c22 >> 20;
+        //reduce from position 21
+        c11 += (c21 << 24) & LIMB_MASK;
+        c12 += c21 >> 4;
+        c10 += (c21 << 20) & LIMB_MASK;
+        c11 += c21 >> 8;
+        c8 -= (c21 << 12) & LIMB_MASK;
+        c9 -= c21 >> 16;
+        c7 += (c21 << 8) & LIMB_MASK;
+        c8 += c21 >> 20;
+        //reduce from position 20
+        c10 += (c20 << 24) & LIMB_MASK;
+        c11 += c20 >> 4;
+        c9 += (c20 << 20) & LIMB_MASK;
+        c10 += c20 >> 8;
+        c7 -= (c20 << 12) & LIMB_MASK;
+        c8 -= c20 >> 16;
+        c6 += (c20 << 8) & LIMB_MASK;
+        c7 += c20 >> 20;
+        //reduce from position 19
+        c9 += (c19 << 24) & LIMB_MASK;
+        c10 += c19 >> 4;
+        c8 += (c19 << 20) & LIMB_MASK;
+        c9 += c19 >> 8;
+        c6 -= (c19 << 12) & LIMB_MASK;
+        c7 -= c19 >> 16;
+        c5 += (c19 << 8) & LIMB_MASK;
+        c6 += c19 >> 20;
+        //reduce from position 18
+        c8 += (c18 << 24) & LIMB_MASK;
+        c9 += c18 >> 4;
+        c7 += (c18 << 20) & LIMB_MASK;
+        c8 += c18 >> 8;
+        c5 -= (c18 << 12) & LIMB_MASK;
+        c6 -= c18 >> 16;
+        c4 += (c18 << 8) & LIMB_MASK;
+        c5 += c18 >> 20;
+        //reduce from position 17
+        c7 += (c17 << 24) & LIMB_MASK;
+        c8 += c17 >> 4;
+        c6 += (c17 << 20) & LIMB_MASK;
+        c7 += c17 >> 8;
+        c4 -= (c17 << 12) & LIMB_MASK;
+        c5 -= c17 >> 16;
+        c3 += (c17 << 8) & LIMB_MASK;
+        c4 += c17 >> 20;
+        //reduce from position 16
+        c6 += (c16 << 24) & LIMB_MASK;
+        c7 += c16 >> 4;
+        c5 += (c16 << 20) & LIMB_MASK;
+        c6 += c16 >> 8;
+        c3 -= (c16 << 12) & LIMB_MASK;
+        c4 -= c16 >> 16;
+        c2 += (c16 << 8) & LIMB_MASK;
+        c3 += c16 >> 20;
+        //reduce from position 15
+        c5 += (c15 << 24) & LIMB_MASK;
+        c6 += c15 >> 4;
+        c4 += (c15 << 20) & LIMB_MASK;
+        c5 += c15 >> 8;
+        c2 -= (c15 << 12) & LIMB_MASK;
+        c3 -= c15 >> 16;
+        c1 += (c15 << 8) & LIMB_MASK;
+        c2 += c15 >> 20;
+        //reduce from position 14
+        c4 += (c14 << 24) & LIMB_MASK;
+        c5 += c14 >> 4;
+        c3 += (c14 << 20) & LIMB_MASK;
+        c4 += c14 >> 8;
+        c1 -= (c14 << 12) & LIMB_MASK;
+        c2 -= c14 >> 16;
+        c0 += (c14 << 8) & LIMB_MASK;
+        c1 += c14 >> 20;
+        c14 = 0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+
+        //carry from position 12
+        long t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //reduce from position 14
+        c4 += (c14 << 24) & LIMB_MASK;
+        c5 += c14 >> 4;
+        c3 += (c14 << 20) & LIMB_MASK;
+        c4 += c14 >> 8;
+        c1 -= (c14 << 12) & LIMB_MASK;
+        c2 -= c14 >> 16;
+        c0 += (c14 << 8) & LIMB_MASK;
+        c1 += c14 >> 20;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+        long c14 = 0;
+        //carry from position 12
+        long t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //reduce from position 14
+        c4 += (c14 << 24) & LIMB_MASK;
+        c5 += c14 >> 4;
+        c3 += (c14 << 20) & LIMB_MASK;
+        c4 += c14 >> 8;
+        c1 -= (c14 << 12) & LIMB_MASK;
+        c2 -= c14 >> 16;
+        c0 += (c14 << 8) & LIMB_MASK;
+        c1 += c14 >> 20;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+        long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+        long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+        long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+        long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+        long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+        long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+        long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+        long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+        long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+        long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+        long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+        long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+        long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+        long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+        long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+        long c26 = (a[13] * b[13]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+        long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+        long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+        long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+        long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+        long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+        long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+        long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+        long c25 = 2 * ((a[12] * a[13]));
+        long c26 = (a[13] * a[13]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP521 extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 28;
+    private static final int NUM_LIMBS = 19;
+    private static final int MAX_ADDS = 2;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 27;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public IntegerPolynomialP521() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(521);
+        result = result.subtract(BigInteger.valueOf(1));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[18] >> 17;
+        limbs[18] -= c << 17;
+        limbs[0] += c;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+        long c37 = 0;
+        //reduce from position 36
+        c17 += (c36 << 11) & LIMB_MASK;
+        c18 += c36 >> 17;
+        //reduce from position 35
+        c16 += (c35 << 11) & LIMB_MASK;
+        c17 += c35 >> 17;
+        //reduce from position 34
+        c15 += (c34 << 11) & LIMB_MASK;
+        c16 += c34 >> 17;
+        //reduce from position 33
+        c14 += (c33 << 11) & LIMB_MASK;
+        c15 += c33 >> 17;
+        //reduce from position 32
+        c13 += (c32 << 11) & LIMB_MASK;
+        c14 += c32 >> 17;
+        //reduce from position 31
+        c12 += (c31 << 11) & LIMB_MASK;
+        c13 += c31 >> 17;
+        //reduce from position 30
+        c11 += (c30 << 11) & LIMB_MASK;
+        c12 += c30 >> 17;
+        //reduce from position 29
+        c10 += (c29 << 11) & LIMB_MASK;
+        c11 += c29 >> 17;
+        //reduce from position 28
+        c9 += (c28 << 11) & LIMB_MASK;
+        c10 += c28 >> 17;
+        //reduce from position 27
+        c8 += (c27 << 11) & LIMB_MASK;
+        c9 += c27 >> 17;
+        //reduce from position 26
+        c7 += (c26 << 11) & LIMB_MASK;
+        c8 += c26 >> 17;
+        //reduce from position 25
+        c6 += (c25 << 11) & LIMB_MASK;
+        c7 += c25 >> 17;
+        //reduce from position 24
+        c5 += (c24 << 11) & LIMB_MASK;
+        c6 += c24 >> 17;
+        //reduce from position 23
+        c4 += (c23 << 11) & LIMB_MASK;
+        c5 += c23 >> 17;
+        //reduce from position 22
+        c3 += (c22 << 11) & LIMB_MASK;
+        c4 += c22 >> 17;
+        //reduce from position 21
+        c2 += (c21 << 11) & LIMB_MASK;
+        c3 += c21 >> 17;
+        //reduce from position 20
+        c1 += (c20 << 11) & LIMB_MASK;
+        c2 += c20 >> 17;
+        //reduce from position 19
+        c0 += (c19 << 11) & LIMB_MASK;
+        c1 += c19 >> 17;
+        c19 = 0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+
+        //carry from position 17
+        long t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+        //reduce from position 19
+        c0 += (c19 << 11) & LIMB_MASK;
+        c1 += c19 >> 17;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+        r[14] = c14;
+        r[15] = c15;
+        r[16] = c16;
+        r[17] = c17;
+        r[18] = c18;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+        long c19 = 0;
+        //carry from position 17
+        long t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+        //reduce from position 19
+        c0 += (c19 << 11) & LIMB_MASK;
+        c1 += c19 >> 17;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+        r[14] = c14;
+        r[15] = c15;
+        r[16] = c16;
+        r[17] = c17;
+        r[18] = c18;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+        long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+        long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+        long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+        long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+        long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+        long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+        long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+        long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+        long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+        long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+        long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+        long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+        long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+        long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+        long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+        long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+        long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+        long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+        long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+        long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+        long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+        long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+        long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+        long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+        long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+        long c36 = (a[18] * b[18]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+        long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+        long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+        long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+        long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+        long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+        long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+        long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+        long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+        long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+        long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+        long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+        long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+        long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+        long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+        long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+        long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+        long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+        long c35 = 2 * ((a[17] * a[18]));
+        long c36 = (a[18] * a[18]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P256OrderField.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,673 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P256OrderField extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 26;
+    private static final int NUM_LIMBS = 10;
+    private static final int MAX_ADDS = 1;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 25;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public P256OrderField() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(256);
+        result = result.add(BigInteger.valueOf(6497617));
+        result = result.subtract(BigInteger.valueOf(2).pow(26).multiply(BigInteger.valueOf(26038081)));
+        result = result.add(BigInteger.valueOf(2).pow(52).multiply(BigInteger.valueOf(32001852)));
+        result = result.subtract(BigInteger.valueOf(2).pow(78).multiply(BigInteger.valueOf(21586850)));
+        result = result.subtract(BigInteger.valueOf(2).pow(104).multiply(BigInteger.valueOf(4397317)));
+        result = result.add(BigInteger.valueOf(2).pow(182).multiply(BigInteger.valueOf(1024)));
+        result = result.subtract(BigInteger.valueOf(2).pow(208).multiply(BigInteger.valueOf(65536)));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[9] >> 22;
+        limbs[9] -= c << 22;
+        long t0 = -6497617 * c;
+        limbs[0] += t0;
+        t0 = 26038081 * c;
+        limbs[1] += t0;
+        t0 = -32001852 * c;
+        limbs[2] += t0;
+        t0 = 21586850 * c;
+        limbs[3] += t0;
+        t0 = 4397317 * c;
+        limbs[4] += t0;
+        t0 = -1024 * c;
+        limbs[7] += t0;
+        t0 = 65536 * c;
+        limbs[8] += t0;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+        long c19 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 26;
+        c9 -= (t0 << 26);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 26;
+        c10 -= (t0 << 26);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 26;
+        c11 -= (t0 << 26);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 26;
+        c12 -= (t0 << 26);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 26;
+        c13 -= (t0 << 26);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 26;
+        c14 -= (t0 << 26);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 26;
+        c15 -= (t0 << 26);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 26;
+        c16 -= (t0 << 26);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 26;
+        c17 -= (t0 << 26);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 26;
+        c18 -= (t0 << 26);
+        c19 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+        long t0;
+
+        //reduce from position 19
+        t0 = -6497617 * c19;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = 26038081 * c19;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        t0 = -32001852 * c19;
+        c11 += (t0 << 4) & LIMB_MASK;
+        c12 += t0 >> 22;
+        t0 = 21586850 * c19;
+        c12 += (t0 << 4) & LIMB_MASK;
+        c13 += t0 >> 22;
+        t0 = 4397317 * c19;
+        c13 += (t0 << 4) & LIMB_MASK;
+        c14 += t0 >> 22;
+        t0 = -1024 * c19;
+        c16 += (t0 << 4) & LIMB_MASK;
+        c17 += t0 >> 22;
+        t0 = 65536 * c19;
+        c17 += (t0 << 4) & LIMB_MASK;
+        c18 += t0 >> 22;
+        //reduce from position 18
+        t0 = -6497617 * c18;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = 26038081 * c18;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = -32001852 * c18;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        t0 = 21586850 * c18;
+        c11 += (t0 << 4) & LIMB_MASK;
+        c12 += t0 >> 22;
+        t0 = 4397317 * c18;
+        c12 += (t0 << 4) & LIMB_MASK;
+        c13 += t0 >> 22;
+        t0 = -1024 * c18;
+        c15 += (t0 << 4) & LIMB_MASK;
+        c16 += t0 >> 22;
+        t0 = 65536 * c18;
+        c16 += (t0 << 4) & LIMB_MASK;
+        c17 += t0 >> 22;
+        //reduce from position 17
+        t0 = -6497617 * c17;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 26038081 * c17;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = -32001852 * c17;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = 21586850 * c17;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        t0 = 4397317 * c17;
+        c11 += (t0 << 4) & LIMB_MASK;
+        c12 += t0 >> 22;
+        t0 = -1024 * c17;
+        c14 += (t0 << 4) & LIMB_MASK;
+        c15 += t0 >> 22;
+        t0 = 65536 * c17;
+        c15 += (t0 << 4) & LIMB_MASK;
+        c16 += t0 >> 22;
+        //reduce from position 16
+        t0 = -6497617 * c16;
+        c6 += (t0 << 4) & LIMB_MASK;
+        c7 += t0 >> 22;
+        t0 = 26038081 * c16;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = -32001852 * c16;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = 21586850 * c16;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = 4397317 * c16;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        t0 = -1024 * c16;
+        c13 += (t0 << 4) & LIMB_MASK;
+        c14 += t0 >> 22;
+        t0 = 65536 * c16;
+        c14 += (t0 << 4) & LIMB_MASK;
+        c15 += t0 >> 22;
+        //reduce from position 15
+        t0 = -6497617 * c15;
+        c5 += (t0 << 4) & LIMB_MASK;
+        c6 += t0 >> 22;
+        t0 = 26038081 * c15;
+        c6 += (t0 << 4) & LIMB_MASK;
+        c7 += t0 >> 22;
+        t0 = -32001852 * c15;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 21586850 * c15;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = 4397317 * c15;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = -1024 * c15;
+        c12 += (t0 << 4) & LIMB_MASK;
+        c13 += t0 >> 22;
+        t0 = 65536 * c15;
+        c13 += (t0 << 4) & LIMB_MASK;
+        c14 += t0 >> 22;
+        //reduce from position 14
+        t0 = -6497617 * c14;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = 26038081 * c14;
+        c5 += (t0 << 4) & LIMB_MASK;
+        c6 += t0 >> 22;
+        t0 = -32001852 * c14;
+        c6 += (t0 << 4) & LIMB_MASK;
+        c7 += t0 >> 22;
+        t0 = 21586850 * c14;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 4397317 * c14;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = -1024 * c14;
+        c11 += (t0 << 4) & LIMB_MASK;
+        c12 += t0 >> 22;
+        t0 = 65536 * c14;
+        c12 += (t0 << 4) & LIMB_MASK;
+        c13 += t0 >> 22;
+        //reduce from position 13
+        t0 = -6497617 * c13;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = 26038081 * c13;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = -32001852 * c13;
+        c5 += (t0 << 4) & LIMB_MASK;
+        c6 += t0 >> 22;
+        t0 = 21586850 * c13;
+        c6 += (t0 << 4) & LIMB_MASK;
+        c7 += t0 >> 22;
+        t0 = 4397317 * c13;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = -1024 * c13;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        t0 = 65536 * c13;
+        c11 += (t0 << 4) & LIMB_MASK;
+        c12 += t0 >> 22;
+        //reduce from position 12
+        t0 = -6497617 * c12;
+        c2 += (t0 << 4) & LIMB_MASK;
+        c3 += t0 >> 22;
+        t0 = 26038081 * c12;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = -32001852 * c12;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = 21586850 * c12;
+        c5 += (t0 << 4) & LIMB_MASK;
+        c6 += t0 >> 22;
+        t0 = 4397317 * c12;
+        c6 += (t0 << 4) & LIMB_MASK;
+        c7 += t0 >> 22;
+        t0 = -1024 * c12;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        t0 = 65536 * c12;
+        c10 += (t0 << 4) & LIMB_MASK;
+        c11 += t0 >> 22;
+        //reduce from position 11
+        t0 = -6497617 * c11;
+        c1 += (t0 << 4) & LIMB_MASK;
+        c2 += t0 >> 22;
+        t0 = 26038081 * c11;
+        c2 += (t0 << 4) & LIMB_MASK;
+        c3 += t0 >> 22;
+        t0 = -32001852 * c11;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = 21586850 * c11;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = 4397317 * c11;
+        c5 += (t0 << 4) & LIMB_MASK;
+        c6 += t0 >> 22;
+        t0 = -1024 * c11;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        t0 = 65536 * c11;
+        c9 += (t0 << 4) & LIMB_MASK;
+        c10 += t0 >> 22;
+        //reduce from position 10
+        t0 = -6497617 * c10;
+        c0 += (t0 << 4) & LIMB_MASK;
+        c1 += t0 >> 22;
+        t0 = 26038081 * c10;
+        c1 += (t0 << 4) & LIMB_MASK;
+        c2 += t0 >> 22;
+        t0 = -32001852 * c10;
+        c2 += (t0 << 4) & LIMB_MASK;
+        c3 += t0 >> 22;
+        t0 = 21586850 * c10;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = 4397317 * c10;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = -1024 * c10;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 65536 * c10;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        c10 = 0;
+
+        carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+    }
+    void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+        long t0;
+
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 26;
+        c9 -= (t0 << 26);
+        c10 += t0;
+
+        carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+    }
+    void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+        long t0;
+
+        //reduce from position 10
+        t0 = -6497617 * c10;
+        c0 += (t0 << 4) & LIMB_MASK;
+        c1 += t0 >> 22;
+        t0 = 26038081 * c10;
+        c1 += (t0 << 4) & LIMB_MASK;
+        c2 += t0 >> 22;
+        t0 = -32001852 * c10;
+        c2 += (t0 << 4) & LIMB_MASK;
+        c3 += t0 >> 22;
+        t0 = 21586850 * c10;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = 4397317 * c10;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = -1024 * c10;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 65536 * c10;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+        long c10 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 26;
+        c9 -= (t0 << 26);
+        c10 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10) {
+        long t0;
+
+        //reduce from position 10
+        t0 = -6497617 * c10;
+        c0 += (t0 << 4) & LIMB_MASK;
+        c1 += t0 >> 22;
+        t0 = 26038081 * c10;
+        c1 += (t0 << 4) & LIMB_MASK;
+        c2 += t0 >> 22;
+        t0 = -32001852 * c10;
+        c2 += (t0 << 4) & LIMB_MASK;
+        c3 += t0 >> 22;
+        t0 = 21586850 * c10;
+        c3 += (t0 << 4) & LIMB_MASK;
+        c4 += t0 >> 22;
+        t0 = 4397317 * c10;
+        c4 += (t0 << 4) & LIMB_MASK;
+        c5 += t0 >> 22;
+        t0 = -1024 * c10;
+        c7 += (t0 << 4) & LIMB_MASK;
+        c8 += t0 >> 22;
+        t0 = 65536 * c10;
+        c8 += (t0 << 4) & LIMB_MASK;
+        c9 += t0 >> 22;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 26;
+        c0 -= (t0 << 26);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 26;
+        c1 -= (t0 << 26);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 26;
+        c2 -= (t0 << 26);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 26;
+        c3 -= (t0 << 26);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 26;
+        c4 -= (t0 << 26);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 26;
+        c5 -= (t0 << 26);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 26;
+        c6 -= (t0 << 26);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 26;
+        c7 -= (t0 << 26);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 26;
+        c8 -= (t0 << 26);
+        c9 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+        long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+        long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+        long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+        long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+        long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+        long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+        long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+        long c18 = (a[9] * b[9]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[8] * a[9]));
+        long c18 = (a[9] * a[9]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P384OrderField.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,881 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P384OrderField extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 28;
+    private static final int NUM_LIMBS = 14;
+    private static final int MAX_ADDS = 1;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 27;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public P384OrderField() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(384);
+        result = result.subtract(BigInteger.valueOf(54187661));
+        result = result.subtract(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(20867411)));
+        result = result.add(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(10975981)));
+        result = result.add(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(14361739)));
+        result = result.subtract(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(35694566)));
+        result = result.subtract(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(132168845)));
+        result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(3710130)));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[13] >> 20;
+        limbs[13] -= c << 20;
+        long t0 = 54187661 * c;
+        limbs[0] += t0;
+        t0 = 20867411 * c;
+        limbs[1] += t0;
+        t0 = -10975981 * c;
+        limbs[2] += t0;
+        t0 = -14361739 * c;
+        limbs[3] += t0;
+        t0 = 35694566 * c;
+        limbs[4] += t0;
+        t0 = 132168845 * c;
+        limbs[5] += t0;
+        t0 = 3710130 * c;
+        limbs[6] += t0;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+        long c27 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+        //carry from position 19
+        t0 = (c19 + CARRY_ADD) >> 28;
+        c19 -= (t0 << 28);
+        c20 += t0;
+        //carry from position 20
+        t0 = (c20 + CARRY_ADD) >> 28;
+        c20 -= (t0 << 28);
+        c21 += t0;
+        //carry from position 21
+        t0 = (c21 + CARRY_ADD) >> 28;
+        c21 -= (t0 << 28);
+        c22 += t0;
+        //carry from position 22
+        t0 = (c22 + CARRY_ADD) >> 28;
+        c22 -= (t0 << 28);
+        c23 += t0;
+        //carry from position 23
+        t0 = (c23 + CARRY_ADD) >> 28;
+        c23 -= (t0 << 28);
+        c24 += t0;
+        //carry from position 24
+        t0 = (c24 + CARRY_ADD) >> 28;
+        c24 -= (t0 << 28);
+        c25 += t0;
+        //carry from position 25
+        t0 = (c25 + CARRY_ADD) >> 28;
+        c25 -= (t0 << 28);
+        c26 += t0;
+        //carry from position 26
+        t0 = (c26 + CARRY_ADD) >> 28;
+        c26 -= (t0 << 28);
+        c27 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+        long t0;
+
+        //reduce from position 27
+        t0 = 54187661 * c27;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = 20867411 * c27;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        t0 = -10975981 * c27;
+        c15 += (t0 << 8) & LIMB_MASK;
+        c16 += t0 >> 20;
+        t0 = -14361739 * c27;
+        c16 += (t0 << 8) & LIMB_MASK;
+        c17 += t0 >> 20;
+        t0 = 35694566 * c27;
+        c17 += (t0 << 8) & LIMB_MASK;
+        c18 += t0 >> 20;
+        t0 = 132168845 * c27;
+        c18 += (t0 << 8) & LIMB_MASK;
+        c19 += t0 >> 20;
+        t0 = 3710130 * c27;
+        c19 += (t0 << 8) & LIMB_MASK;
+        c20 += t0 >> 20;
+        //reduce from position 26
+        t0 = 54187661 * c26;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = 20867411 * c26;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = -10975981 * c26;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        t0 = -14361739 * c26;
+        c15 += (t0 << 8) & LIMB_MASK;
+        c16 += t0 >> 20;
+        t0 = 35694566 * c26;
+        c16 += (t0 << 8) & LIMB_MASK;
+        c17 += t0 >> 20;
+        t0 = 132168845 * c26;
+        c17 += (t0 << 8) & LIMB_MASK;
+        c18 += t0 >> 20;
+        t0 = 3710130 * c26;
+        c18 += (t0 << 8) & LIMB_MASK;
+        c19 += t0 >> 20;
+        //reduce from position 25
+        t0 = 54187661 * c25;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = 20867411 * c25;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = -10975981 * c25;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = -14361739 * c25;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        t0 = 35694566 * c25;
+        c15 += (t0 << 8) & LIMB_MASK;
+        c16 += t0 >> 20;
+        t0 = 132168845 * c25;
+        c16 += (t0 << 8) & LIMB_MASK;
+        c17 += t0 >> 20;
+        t0 = 3710130 * c25;
+        c17 += (t0 << 8) & LIMB_MASK;
+        c18 += t0 >> 20;
+        //reduce from position 24
+        t0 = 54187661 * c24;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = 20867411 * c24;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = -10975981 * c24;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = -14361739 * c24;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = 35694566 * c24;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        t0 = 132168845 * c24;
+        c15 += (t0 << 8) & LIMB_MASK;
+        c16 += t0 >> 20;
+        t0 = 3710130 * c24;
+        c16 += (t0 << 8) & LIMB_MASK;
+        c17 += t0 >> 20;
+        //reduce from position 23
+        t0 = 54187661 * c23;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = 20867411 * c23;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = -10975981 * c23;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = -14361739 * c23;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = 35694566 * c23;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = 132168845 * c23;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        t0 = 3710130 * c23;
+        c15 += (t0 << 8) & LIMB_MASK;
+        c16 += t0 >> 20;
+        //reduce from position 22
+        t0 = 54187661 * c22;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = 20867411 * c22;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = -10975981 * c22;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = -14361739 * c22;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = 35694566 * c22;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = 132168845 * c22;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        t0 = 3710130 * c22;
+        c14 += (t0 << 8) & LIMB_MASK;
+        c15 += t0 >> 20;
+        //reduce from position 21
+        t0 = 54187661 * c21;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = 20867411 * c21;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = -10975981 * c21;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = -14361739 * c21;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = 35694566 * c21;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = 132168845 * c21;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        t0 = 3710130 * c21;
+        c13 += (t0 << 8) & LIMB_MASK;
+        c14 += t0 >> 20;
+        //reduce from position 20
+        t0 = 54187661 * c20;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = 20867411 * c20;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = -10975981 * c20;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = -14361739 * c20;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = 35694566 * c20;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = 132168845 * c20;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        t0 = 3710130 * c20;
+        c12 += (t0 << 8) & LIMB_MASK;
+        c13 += t0 >> 20;
+        //reduce from position 19
+        t0 = 54187661 * c19;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 20867411 * c19;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = -10975981 * c19;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = -14361739 * c19;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = 35694566 * c19;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = 132168845 * c19;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        t0 = 3710130 * c19;
+        c11 += (t0 << 8) & LIMB_MASK;
+        c12 += t0 >> 20;
+        //reduce from position 18
+        t0 = 54187661 * c18;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = 20867411 * c18;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = -10975981 * c18;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = -14361739 * c18;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = 35694566 * c18;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = 132168845 * c18;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        t0 = 3710130 * c18;
+        c10 += (t0 << 8) & LIMB_MASK;
+        c11 += t0 >> 20;
+        //reduce from position 17
+        t0 = 54187661 * c17;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = 20867411 * c17;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = -10975981 * c17;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = -14361739 * c17;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = 35694566 * c17;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = 132168845 * c17;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        t0 = 3710130 * c17;
+        c9 += (t0 << 8) & LIMB_MASK;
+        c10 += t0 >> 20;
+        //reduce from position 16
+        t0 = 54187661 * c16;
+        c2 += (t0 << 8) & LIMB_MASK;
+        c3 += t0 >> 20;
+        t0 = 20867411 * c16;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = -10975981 * c16;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = -14361739 * c16;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 35694566 * c16;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = 132168845 * c16;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        t0 = 3710130 * c16;
+        c8 += (t0 << 8) & LIMB_MASK;
+        c9 += t0 >> 20;
+        //reduce from position 15
+        t0 = 54187661 * c15;
+        c1 += (t0 << 8) & LIMB_MASK;
+        c2 += t0 >> 20;
+        t0 = 20867411 * c15;
+        c2 += (t0 << 8) & LIMB_MASK;
+        c3 += t0 >> 20;
+        t0 = -10975981 * c15;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = -14361739 * c15;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = 35694566 * c15;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 132168845 * c15;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        t0 = 3710130 * c15;
+        c7 += (t0 << 8) & LIMB_MASK;
+        c8 += t0 >> 20;
+        //reduce from position 14
+        t0 = 54187661 * c14;
+        c0 += (t0 << 8) & LIMB_MASK;
+        c1 += t0 >> 20;
+        t0 = 20867411 * c14;
+        c1 += (t0 << 8) & LIMB_MASK;
+        c2 += t0 >> 20;
+        t0 = -10975981 * c14;
+        c2 += (t0 << 8) & LIMB_MASK;
+        c3 += t0 >> 20;
+        t0 = -14361739 * c14;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = 35694566 * c14;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = 132168845 * c14;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 3710130 * c14;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        c14 = 0;
+
+        carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+    }
+    void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+        long t0;
+
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+
+        carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+    }
+    void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+        long t0;
+
+        //reduce from position 14
+        t0 = 54187661 * c14;
+        c0 += (t0 << 8) & LIMB_MASK;
+        c1 += t0 >> 20;
+        t0 = 20867411 * c14;
+        c1 += (t0 << 8) & LIMB_MASK;
+        c2 += t0 >> 20;
+        t0 = -10975981 * c14;
+        c2 += (t0 << 8) & LIMB_MASK;
+        c3 += t0 >> 20;
+        t0 = -14361739 * c14;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = 35694566 * c14;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = 132168845 * c14;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 3710130 * c14;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+        long c14 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14) {
+        long t0;
+
+        //reduce from position 14
+        t0 = 54187661 * c14;
+        c0 += (t0 << 8) & LIMB_MASK;
+        c1 += t0 >> 20;
+        t0 = 20867411 * c14;
+        c1 += (t0 << 8) & LIMB_MASK;
+        c2 += t0 >> 20;
+        t0 = -10975981 * c14;
+        c2 += (t0 << 8) & LIMB_MASK;
+        c3 += t0 >> 20;
+        t0 = -14361739 * c14;
+        c3 += (t0 << 8) & LIMB_MASK;
+        c4 += t0 >> 20;
+        t0 = 35694566 * c14;
+        c4 += (t0 << 8) & LIMB_MASK;
+        c5 += t0 >> 20;
+        t0 = 132168845 * c14;
+        c5 += (t0 << 8) & LIMB_MASK;
+        c6 += t0 >> 20;
+        t0 = 3710130 * c14;
+        c6 += (t0 << 8) & LIMB_MASK;
+        c7 += t0 >> 20;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+        long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+        long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+        long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+        long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+        long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+        long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+        long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+        long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+        long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+        long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+        long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+        long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+        long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+        long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+        long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+        long c26 = (a[13] * b[13]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+        long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+        long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+        long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+        long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+        long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+        long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+        long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+        long c25 = 2 * ((a[12] * a[13]));
+        long c26 = (a[13] * a[13]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P521OrderField.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,1377 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P521OrderField extends IntegerPolynomial {
+    private static final int BITS_PER_LIMB = 28;
+    private static final int NUM_LIMBS = 19;
+    private static final int MAX_ADDS = 1;
+    public static final BigInteger MODULUS = evaluateModulus();
+    private static final long CARRY_ADD = 1 << 27;
+    private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+    public P521OrderField() {
+
+        super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+    }
+    private static BigInteger evaluateModulus() {
+        BigInteger result = BigInteger.valueOf(2).pow(521);
+        result = result.add(BigInteger.valueOf(20472841));
+        result = result.add(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(117141993)));
+        result = result.subtract(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(62411077)));
+        result = result.subtract(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(56915814)));
+        result = result.add(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(97532854)));
+        result = result.add(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(76509338)));
+        result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(75510783)));
+        result = result.subtract(BigInteger.valueOf(2).pow(196).multiply(BigInteger.valueOf(67962521)));
+        result = result.add(BigInteger.valueOf(2).pow(224).multiply(BigInteger.valueOf(25593732)));
+        result = result.subtract(BigInteger.valueOf(2).pow(252).multiply(BigInteger.valueOf(91)));
+        return result;
+    }
+    @Override
+    protected void finalCarryReduceLast(long[] limbs) {
+        long c = limbs[18] >> 17;
+        limbs[18] -= c << 17;
+        long t0 = -20472841 * c;
+        limbs[0] += t0;
+        t0 = -117141993 * c;
+        limbs[1] += t0;
+        t0 = 62411077 * c;
+        limbs[2] += t0;
+        t0 = 56915814 * c;
+        limbs[3] += t0;
+        t0 = -97532854 * c;
+        limbs[4] += t0;
+        t0 = -76509338 * c;
+        limbs[5] += t0;
+        t0 = 75510783 * c;
+        limbs[6] += t0;
+        t0 = 67962521 * c;
+        limbs[7] += t0;
+        t0 = -25593732 * c;
+        limbs[8] += t0;
+        t0 = 91 * c;
+        limbs[9] += t0;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+        long c37 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+        //carry from position 19
+        t0 = (c19 + CARRY_ADD) >> 28;
+        c19 -= (t0 << 28);
+        c20 += t0;
+        //carry from position 20
+        t0 = (c20 + CARRY_ADD) >> 28;
+        c20 -= (t0 << 28);
+        c21 += t0;
+        //carry from position 21
+        t0 = (c21 + CARRY_ADD) >> 28;
+        c21 -= (t0 << 28);
+        c22 += t0;
+        //carry from position 22
+        t0 = (c22 + CARRY_ADD) >> 28;
+        c22 -= (t0 << 28);
+        c23 += t0;
+        //carry from position 23
+        t0 = (c23 + CARRY_ADD) >> 28;
+        c23 -= (t0 << 28);
+        c24 += t0;
+        //carry from position 24
+        t0 = (c24 + CARRY_ADD) >> 28;
+        c24 -= (t0 << 28);
+        c25 += t0;
+        //carry from position 25
+        t0 = (c25 + CARRY_ADD) >> 28;
+        c25 -= (t0 << 28);
+        c26 += t0;
+        //carry from position 26
+        t0 = (c26 + CARRY_ADD) >> 28;
+        c26 -= (t0 << 28);
+        c27 += t0;
+        //carry from position 27
+        t0 = (c27 + CARRY_ADD) >> 28;
+        c27 -= (t0 << 28);
+        c28 += t0;
+        //carry from position 28
+        t0 = (c28 + CARRY_ADD) >> 28;
+        c28 -= (t0 << 28);
+        c29 += t0;
+        //carry from position 29
+        t0 = (c29 + CARRY_ADD) >> 28;
+        c29 -= (t0 << 28);
+        c30 += t0;
+        //carry from position 30
+        t0 = (c30 + CARRY_ADD) >> 28;
+        c30 -= (t0 << 28);
+        c31 += t0;
+        //carry from position 31
+        t0 = (c31 + CARRY_ADD) >> 28;
+        c31 -= (t0 << 28);
+        c32 += t0;
+        //carry from position 32
+        t0 = (c32 + CARRY_ADD) >> 28;
+        c32 -= (t0 << 28);
+        c33 += t0;
+        //carry from position 33
+        t0 = (c33 + CARRY_ADD) >> 28;
+        c33 -= (t0 << 28);
+        c34 += t0;
+        //carry from position 34
+        t0 = (c34 + CARRY_ADD) >> 28;
+        c34 -= (t0 << 28);
+        c35 += t0;
+        //carry from position 35
+        t0 = (c35 + CARRY_ADD) >> 28;
+        c35 -= (t0 << 28);
+        c36 += t0;
+        //carry from position 36
+        t0 = (c36 + CARRY_ADD) >> 28;
+        c36 -= (t0 << 28);
+        c37 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+        long t0;
+
+        //reduce from position 37
+        t0 = -20472841 * c37;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = -117141993 * c37;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = 62411077 * c37;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = 56915814 * c37;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = -97532854 * c37;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        t0 = -76509338 * c37;
+        c23 += (t0 << 11) & LIMB_MASK;
+        c24 += t0 >> 17;
+        t0 = 75510783 * c37;
+        c24 += (t0 << 11) & LIMB_MASK;
+        c25 += t0 >> 17;
+        t0 = 67962521 * c37;
+        c25 += (t0 << 11) & LIMB_MASK;
+        c26 += t0 >> 17;
+        t0 = -25593732 * c37;
+        c26 += (t0 << 11) & LIMB_MASK;
+        c27 += t0 >> 17;
+        t0 = 91 * c37;
+        c27 += (t0 << 11) & LIMB_MASK;
+        c28 += t0 >> 17;
+        //reduce from position 36
+        t0 = -20472841 * c36;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = -117141993 * c36;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = 62411077 * c36;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = 56915814 * c36;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = -97532854 * c36;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = -76509338 * c36;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        t0 = 75510783 * c36;
+        c23 += (t0 << 11) & LIMB_MASK;
+        c24 += t0 >> 17;
+        t0 = 67962521 * c36;
+        c24 += (t0 << 11) & LIMB_MASK;
+        c25 += t0 >> 17;
+        t0 = -25593732 * c36;
+        c25 += (t0 << 11) & LIMB_MASK;
+        c26 += t0 >> 17;
+        t0 = 91 * c36;
+        c26 += (t0 << 11) & LIMB_MASK;
+        c27 += t0 >> 17;
+        //reduce from position 35
+        t0 = -20472841 * c35;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = -117141993 * c35;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = 62411077 * c35;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = 56915814 * c35;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = -97532854 * c35;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = -76509338 * c35;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = 75510783 * c35;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        t0 = 67962521 * c35;
+        c23 += (t0 << 11) & LIMB_MASK;
+        c24 += t0 >> 17;
+        t0 = -25593732 * c35;
+        c24 += (t0 << 11) & LIMB_MASK;
+        c25 += t0 >> 17;
+        t0 = 91 * c35;
+        c25 += (t0 << 11) & LIMB_MASK;
+        c26 += t0 >> 17;
+        //reduce from position 34
+        t0 = -20472841 * c34;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = -117141993 * c34;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = 62411077 * c34;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = 56915814 * c34;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = -97532854 * c34;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = -76509338 * c34;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = 75510783 * c34;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = 67962521 * c34;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        t0 = -25593732 * c34;
+        c23 += (t0 << 11) & LIMB_MASK;
+        c24 += t0 >> 17;
+        t0 = 91 * c34;
+        c24 += (t0 << 11) & LIMB_MASK;
+        c25 += t0 >> 17;
+        //reduce from position 33
+        t0 = -20472841 * c33;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = -117141993 * c33;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = 62411077 * c33;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = 56915814 * c33;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = -97532854 * c33;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = -76509338 * c33;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = 75510783 * c33;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = 67962521 * c33;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = -25593732 * c33;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        t0 = 91 * c33;
+        c23 += (t0 << 11) & LIMB_MASK;
+        c24 += t0 >> 17;
+        //reduce from position 32
+        t0 = -20472841 * c32;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = -117141993 * c32;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = 62411077 * c32;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = 56915814 * c32;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = -97532854 * c32;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = -76509338 * c32;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = 75510783 * c32;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = 67962521 * c32;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = -25593732 * c32;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        t0 = 91 * c32;
+        c22 += (t0 << 11) & LIMB_MASK;
+        c23 += t0 >> 17;
+        //reduce from position 31
+        t0 = -20472841 * c31;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = -117141993 * c31;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = 62411077 * c31;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = 56915814 * c31;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = -97532854 * c31;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = -76509338 * c31;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = 75510783 * c31;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = 67962521 * c31;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = -25593732 * c31;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        t0 = 91 * c31;
+        c21 += (t0 << 11) & LIMB_MASK;
+        c22 += t0 >> 17;
+        //reduce from position 30
+        t0 = -20472841 * c30;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = -117141993 * c30;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = 62411077 * c30;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = 56915814 * c30;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = -97532854 * c30;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = -76509338 * c30;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = 75510783 * c30;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = 67962521 * c30;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = -25593732 * c30;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        t0 = 91 * c30;
+        c20 += (t0 << 11) & LIMB_MASK;
+        c21 += t0 >> 17;
+        //reduce from position 29
+        t0 = -20472841 * c29;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = -117141993 * c29;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = 62411077 * c29;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = 56915814 * c29;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = -97532854 * c29;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = -76509338 * c29;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = 75510783 * c29;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = 67962521 * c29;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = -25593732 * c29;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+        t0 = 91 * c29;
+        c19 += (t0 << 11) & LIMB_MASK;
+        c20 += t0 >> 17;
+        //reduce from position 28
+        t0 = -20472841 * c28;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = -117141993 * c28;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = 62411077 * c28;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = 56915814 * c28;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = -97532854 * c28;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = -76509338 * c28;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = 75510783 * c28;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = 67962521 * c28;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = -25593732 * c28;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        t0 = 91 * c28;
+        c18 += (t0 << 11) & LIMB_MASK;
+        c19 += t0 >> 17;
+
+        carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+    }
+    void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+        long t0;
+
+        //carry from position 19
+        t0 = (c19 + CARRY_ADD) >> 28;
+        c19 -= (t0 << 28);
+        c20 += t0;
+        //carry from position 20
+        t0 = (c20 + CARRY_ADD) >> 28;
+        c20 -= (t0 << 28);
+        c21 += t0;
+        //carry from position 21
+        t0 = (c21 + CARRY_ADD) >> 28;
+        c21 -= (t0 << 28);
+        c22 += t0;
+        //carry from position 22
+        t0 = (c22 + CARRY_ADD) >> 28;
+        c22 -= (t0 << 28);
+        c23 += t0;
+        //carry from position 23
+        t0 = (c23 + CARRY_ADD) >> 28;
+        c23 -= (t0 << 28);
+        c24 += t0;
+        //carry from position 24
+        t0 = (c24 + CARRY_ADD) >> 28;
+        c24 -= (t0 << 28);
+        c25 += t0;
+        //carry from position 25
+        t0 = (c25 + CARRY_ADD) >> 28;
+        c25 -= (t0 << 28);
+        c26 += t0;
+        //carry from position 26
+        t0 = (c26 + CARRY_ADD) >> 28;
+        c26 -= (t0 << 28);
+        c27 += t0;
+        //reduce from position 27
+        t0 = -20472841 * c27;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = -117141993 * c27;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = 62411077 * c27;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = 56915814 * c27;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = -97532854 * c27;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = -76509338 * c27;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = 75510783 * c27;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = 67962521 * c27;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = -25593732 * c27;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        t0 = 91 * c27;
+        c17 += (t0 << 11) & LIMB_MASK;
+        c18 += t0 >> 17;
+        //reduce from position 26
+        t0 = -20472841 * c26;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -117141993 * c26;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 62411077 * c26;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = 56915814 * c26;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = -97532854 * c26;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = -76509338 * c26;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = 75510783 * c26;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = 67962521 * c26;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = -25593732 * c26;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        t0 = 91 * c26;
+        c16 += (t0 << 11) & LIMB_MASK;
+        c17 += t0 >> 17;
+        //reduce from position 25
+        t0 = -20472841 * c25;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = -117141993 * c25;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = 62411077 * c25;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 56915814 * c25;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = -97532854 * c25;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = -76509338 * c25;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = 75510783 * c25;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = 67962521 * c25;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = -25593732 * c25;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        t0 = 91 * c25;
+        c15 += (t0 << 11) & LIMB_MASK;
+        c16 += t0 >> 17;
+        //reduce from position 24
+        t0 = -20472841 * c24;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = -117141993 * c24;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 62411077 * c24;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = 56915814 * c24;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = -97532854 * c24;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = -76509338 * c24;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = 75510783 * c24;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = 67962521 * c24;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = -25593732 * c24;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        t0 = 91 * c24;
+        c14 += (t0 << 11) & LIMB_MASK;
+        c15 += t0 >> 17;
+        //reduce from position 23
+        t0 = -20472841 * c23;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = -117141993 * c23;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = 62411077 * c23;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 56915814 * c23;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -97532854 * c23;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = -76509338 * c23;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = 75510783 * c23;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = 67962521 * c23;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = -25593732 * c23;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        t0 = 91 * c23;
+        c13 += (t0 << 11) & LIMB_MASK;
+        c14 += t0 >> 17;
+        //reduce from position 22
+        t0 = -20472841 * c22;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = -117141993 * c22;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = 62411077 * c22;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = 56915814 * c22;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = -97532854 * c22;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -76509338 * c22;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 75510783 * c22;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = 67962521 * c22;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = -25593732 * c22;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        t0 = 91 * c22;
+        c12 += (t0 << 11) & LIMB_MASK;
+        c13 += t0 >> 17;
+        //reduce from position 21
+        t0 = -20472841 * c21;
+        c2 += (t0 << 11) & LIMB_MASK;
+        c3 += t0 >> 17;
+        t0 = -117141993 * c21;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = 62411077 * c21;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = 56915814 * c21;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = -97532854 * c21;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = -76509338 * c21;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = 75510783 * c21;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 67962521 * c21;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = -25593732 * c21;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        t0 = 91 * c21;
+        c11 += (t0 << 11) & LIMB_MASK;
+        c12 += t0 >> 17;
+        //reduce from position 20
+        t0 = -20472841 * c20;
+        c1 += (t0 << 11) & LIMB_MASK;
+        c2 += t0 >> 17;
+        t0 = -117141993 * c20;
+        c2 += (t0 << 11) & LIMB_MASK;
+        c3 += t0 >> 17;
+        t0 = 62411077 * c20;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = 56915814 * c20;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = -97532854 * c20;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = -76509338 * c20;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 75510783 * c20;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = 67962521 * c20;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = -25593732 * c20;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        t0 = 91 * c20;
+        c10 += (t0 << 11) & LIMB_MASK;
+        c11 += t0 >> 17;
+        //reduce from position 19
+        t0 = -20472841 * c19;
+        c0 += (t0 << 11) & LIMB_MASK;
+        c1 += t0 >> 17;
+        t0 = -117141993 * c19;
+        c1 += (t0 << 11) & LIMB_MASK;
+        c2 += t0 >> 17;
+        t0 = 62411077 * c19;
+        c2 += (t0 << 11) & LIMB_MASK;
+        c3 += t0 >> 17;
+        t0 = 56915814 * c19;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = -97532854 * c19;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = -76509338 * c19;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = 75510783 * c19;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 67962521 * c19;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -25593732 * c19;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 91 * c19;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        c19 = 0;
+
+        carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+    }
+    void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+        long t0;
+
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+
+        carryReduce3(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+    }
+    void carryReduce3(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+        long t0;
+
+        //reduce from position 19
+        t0 = -20472841 * c19;
+        c0 += (t0 << 11) & LIMB_MASK;
+        c1 += t0 >> 17;
+        t0 = -117141993 * c19;
+        c1 += (t0 << 11) & LIMB_MASK;
+        c2 += t0 >> 17;
+        t0 = 62411077 * c19;
+        c2 += (t0 << 11) & LIMB_MASK;
+        c3 += t0 >> 17;
+        t0 = 56915814 * c19;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = -97532854 * c19;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = -76509338 * c19;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = 75510783 * c19;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 67962521 * c19;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -25593732 * c19;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 91 * c19;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+        r[14] = c14;
+        r[15] = c15;
+        r[16] = c16;
+        r[17] = c17;
+        r[18] = c18;
+    }
+    private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+        long c19 = 0;
+        //carry from position 0
+        long t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+        //carry from position 18
+        t0 = (c18 + CARRY_ADD) >> 28;
+        c18 -= (t0 << 28);
+        c19 += t0;
+
+        carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+    }
+    void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+        long t0;
+
+        //reduce from position 19
+        t0 = -20472841 * c19;
+        c0 += (t0 << 11) & LIMB_MASK;
+        c1 += t0 >> 17;
+        t0 = -117141993 * c19;
+        c1 += (t0 << 11) & LIMB_MASK;
+        c2 += t0 >> 17;
+        t0 = 62411077 * c19;
+        c2 += (t0 << 11) & LIMB_MASK;
+        c3 += t0 >> 17;
+        t0 = 56915814 * c19;
+        c3 += (t0 << 11) & LIMB_MASK;
+        c4 += t0 >> 17;
+        t0 = -97532854 * c19;
+        c4 += (t0 << 11) & LIMB_MASK;
+        c5 += t0 >> 17;
+        t0 = -76509338 * c19;
+        c5 += (t0 << 11) & LIMB_MASK;
+        c6 += t0 >> 17;
+        t0 = 75510783 * c19;
+        c6 += (t0 << 11) & LIMB_MASK;
+        c7 += t0 >> 17;
+        t0 = 67962521 * c19;
+        c7 += (t0 << 11) & LIMB_MASK;
+        c8 += t0 >> 17;
+        t0 = -25593732 * c19;
+        c8 += (t0 << 11) & LIMB_MASK;
+        c9 += t0 >> 17;
+        t0 = 91 * c19;
+        c9 += (t0 << 11) & LIMB_MASK;
+        c10 += t0 >> 17;
+        //carry from position 0
+        t0 = (c0 + CARRY_ADD) >> 28;
+        c0 -= (t0 << 28);
+        c1 += t0;
+        //carry from position 1
+        t0 = (c1 + CARRY_ADD) >> 28;
+        c1 -= (t0 << 28);
+        c2 += t0;
+        //carry from position 2
+        t0 = (c2 + CARRY_ADD) >> 28;
+        c2 -= (t0 << 28);
+        c3 += t0;
+        //carry from position 3
+        t0 = (c3 + CARRY_ADD) >> 28;
+        c3 -= (t0 << 28);
+        c4 += t0;
+        //carry from position 4
+        t0 = (c4 + CARRY_ADD) >> 28;
+        c4 -= (t0 << 28);
+        c5 += t0;
+        //carry from position 5
+        t0 = (c5 + CARRY_ADD) >> 28;
+        c5 -= (t0 << 28);
+        c6 += t0;
+        //carry from position 6
+        t0 = (c6 + CARRY_ADD) >> 28;
+        c6 -= (t0 << 28);
+        c7 += t0;
+        //carry from position 7
+        t0 = (c7 + CARRY_ADD) >> 28;
+        c7 -= (t0 << 28);
+        c8 += t0;
+        //carry from position 8
+        t0 = (c8 + CARRY_ADD) >> 28;
+        c8 -= (t0 << 28);
+        c9 += t0;
+        //carry from position 9
+        t0 = (c9 + CARRY_ADD) >> 28;
+        c9 -= (t0 << 28);
+        c10 += t0;
+        //carry from position 10
+        t0 = (c10 + CARRY_ADD) >> 28;
+        c10 -= (t0 << 28);
+        c11 += t0;
+        //carry from position 11
+        t0 = (c11 + CARRY_ADD) >> 28;
+        c11 -= (t0 << 28);
+        c12 += t0;
+        //carry from position 12
+        t0 = (c12 + CARRY_ADD) >> 28;
+        c12 -= (t0 << 28);
+        c13 += t0;
+        //carry from position 13
+        t0 = (c13 + CARRY_ADD) >> 28;
+        c13 -= (t0 << 28);
+        c14 += t0;
+        //carry from position 14
+        t0 = (c14 + CARRY_ADD) >> 28;
+        c14 -= (t0 << 28);
+        c15 += t0;
+        //carry from position 15
+        t0 = (c15 + CARRY_ADD) >> 28;
+        c15 -= (t0 << 28);
+        c16 += t0;
+        //carry from position 16
+        t0 = (c16 + CARRY_ADD) >> 28;
+        c16 -= (t0 << 28);
+        c17 += t0;
+        //carry from position 17
+        t0 = (c17 + CARRY_ADD) >> 28;
+        c17 -= (t0 << 28);
+        c18 += t0;
+
+        r[0] = c0;
+        r[1] = c1;
+        r[2] = c2;
+        r[3] = c3;
+        r[4] = c4;
+        r[5] = c5;
+        r[6] = c6;
+        r[7] = c7;
+        r[8] = c8;
+        r[9] = c9;
+        r[10] = c10;
+        r[11] = c11;
+        r[12] = c12;
+        r[13] = c13;
+        r[14] = c14;
+        r[15] = c15;
+        r[16] = c16;
+        r[17] = c17;
+        r[18] = c18;
+    }
+    @Override
+    protected void mult(long[] a, long[] b, long[] r) {
+        long c0 = (a[0] * b[0]);
+        long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+        long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+        long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+        long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+        long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+        long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+        long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+        long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+        long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+        long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+        long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+        long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+        long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+        long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+        long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+        long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+        long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+        long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+        long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+        long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+        long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+        long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+        long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+        long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+        long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+        long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+        long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+        long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+        long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+        long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+        long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+        long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+        long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+        long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+        long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+        long c36 = (a[18] * b[18]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+    }
+    @Override
+    protected void reduce(long[] a) {
+        carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+    }
+    @Override
+    protected void square(long[] a, long[] r) {
+        long c0 = (a[0] * a[0]);
+        long c1 = 2 * ((a[0] * a[1]));
+        long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+        long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+        long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+        long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+        long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+        long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+        long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+        long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+        long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+        long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+        long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+        long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+        long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+        long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+        long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+        long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+        long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+        long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+        long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+        long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+        long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+        long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+        long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+        long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+        long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+        long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+        long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+        long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+        long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+        long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+        long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+        long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+        long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+        long c35 = 2 * ((a[17] * a[18]));
+        long c36 = (a[18] * a[18]);
+
+        carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/header.txt	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package sun.security.validator;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.EnumSet;
+
+import sun.security.util.Debug;
+
+/**
+ * Policies for distrusting a certificate authority (CA). See the
+ * jdk.security.caDistrustPolicies security property for more information.
+ */
+enum CADistrustPolicy {
+    /**
+     * Distrust TLS Server certificates anchored by a Symantec root CA and
+     * issued after April 16, 2019. If enabled, this policy is currently
+     * enforced by the PKIX and SunX509 TrustManager implementations of the
+     * SunJSSE provider implementation.
+     */
+    SYMANTEC_TLS {
+        void checkDistrust(String variant, X509Certificate anchor,
+                           X509Certificate ee) throws ValidatorException {
+            if (!variant.equals(Validator.VAR_TLS_SERVER)) {
+                return;
+            }
+            SymantecTLSPolicy.checkDistrust(anchor, ee);
+        }
+    };
+
+    /**
+     * Checks if the end-entity certificate is distrusted.
+     *
+     * @param variant the type of certificate being checked
+     * @param anchor the trust anchor certificate
+     * @param ee the end-entity certificate to check
+     * @throws ValidatorException if the end-entity certificate is distrusted
+     */
+    abstract void checkDistrust(String variant,
+                                X509Certificate anchor,
+                                X509Certificate ee) throws ValidatorException;
+
+    // The policies set in the jdk.security.caDistrustPolicies property.
+    static final EnumSet<CADistrustPolicy> POLICIES = parseProperty();
+    private static EnumSet<CADistrustPolicy> parseProperty() {
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<>() {
+                @Override
+                public String run() {
+                    return Security.getProperty(
+                        "jdk.security.caDistrustPolicies");
+                }
+            });
+        EnumSet<CADistrustPolicy> set = EnumSet.noneOf(CADistrustPolicy.class);
+        // if property is null or empty, the restrictions are not enforced
+        if (property == null || property.isEmpty()) {
+            return set;
+        }
+        String[] policies = property.split(",");
+        for (String policy : policies) {
+            policy = policy.trim();
+            try {
+                CADistrustPolicy caPolicy =
+                    Enum.valueOf(CADistrustPolicy.class, policy);
+                set.add(caPolicy);
+            } catch (IllegalArgumentException iae) {
+                // ignore unknown values but log it
+                Debug debug = Debug.getInstance("certpath");
+                if (debug != null) {
+                    debug.println("Unknown value for the " +
+                                  "jdk.security.caDistrustPolicies property: "
+                                  + policy);
+                }
+            }
+        }
+        return set;
+    }
+}
--- a/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -133,7 +133,9 @@
     }
 
     void check(X509Certificate cert, Object parameter,
-            boolean checkUnresolvedCritExts) throws CertificateException {
+            boolean checkUnresolvedCritExts, X509Certificate anchor)
+            throws CertificateException {
+
         if (variant.equals(Validator.VAR_GENERIC)) {
             return; // no checks
         }
@@ -159,6 +161,12 @@
         if (checkUnresolvedCritExts) {
             checkRemainingExtensions(exts);
         }
+
+        // check if certificate should be distrusted according to policies
+        // set in the jdk.security.caDistrustPolicies security property
+        for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {
+            policy.checkDistrust(variant, anchor, cert);
+        }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/validator/SymantecTLSPolicy.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+package sun.security.validator;
+
+import java.security.cert.X509Certificate;
+import java.time.LocalDate;
+import java.time.Month;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Set;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * This class checks if Symantec issued TLS Server certificates should be
+ * restricted.
+ */
+final class SymantecTLSPolicy {
+
+    // SHA-256 certificate fingerprints of distrusted roots
+    private static final Set<String> FINGERPRINTS = Set.of(
+        // cacerts alias: geotrustglobalca
+        // DN: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
+        "FF856A2D251DCD88D36656F450126798CFABAADE40799C722DE4D2B5DB36A73A",
+        // cacerts alias: geotrustprimaryca
+        // DN: CN=GeoTrust Primary Certification Authority,
+        //     O=GeoTrust Inc., C=US
+        "37D51006C512EAAB626421F1EC8C92013FC5F82AE98EE533EB4619B8DEB4D06C",
+        // cacerts alias: geotrustprimarycag2
+        // DN: CN=GeoTrust Primary Certification Authority - G2,
+        //     OU=(c) 2007 GeoTrust Inc. - For authorized use only,
+        //     O=GeoTrust Inc., C=US
+        "5EDB7AC43B82A06A8761E8D7BE4979EBF2611F7DD79BF91C1C6B566A219ED766",
+        // cacerts alias: geotrustprimarycag3
+        // DN: CN=GeoTrust Primary Certification Authority - G3,
+        //     OU=(c) 2008 GeoTrust Inc. - For authorized use only,
+        //     O=GeoTrust Inc., C=US
+        "B478B812250DF878635C2AA7EC7D155EAA625EE82916E2CD294361886CD1FBD4",
+        // cacerts alias: geotrustuniversalca
+        // DN: CN=GeoTrust Universal CA, O=GeoTrust Inc., C=US
+        "A0459B9F63B22559F5FA5D4C6DB3F9F72FF19342033578F073BF1D1B46CBB912",
+        // cacerts alias: thawteprimaryrootca
+        // DN: CN=thawte Primary Root CA,
+        //     OU="(c) 2006 thawte, Inc. - For authorized use only",
+        //     OU=Certification Services Division, O="thawte, Inc.", C=US
+        "8D722F81A9C113C0791DF136A2966DB26C950A971DB46B4199F4EA54B78BFB9F",
+        // cacerts alias: thawteprimaryrootcag2
+        // DN: CN=thawte Primary Root CA - G2,
+        //     OU="(c) 2007 thawte, Inc. - For authorized use only",
+        //     O="thawte, Inc.", C=US
+        "A4310D50AF18A6447190372A86AFAF8B951FFB431D837F1E5688B45971ED1557",
+        // cacerts alias: thawteprimaryrootcag3
+        // DN: CN=thawte Primary Root CA - G3,
+        //     OU="(c) 2008 thawte, Inc. - For authorized use only",
+        //     OU=Certification Services Division, O="thawte, Inc.", C=US
+        "4B03F45807AD70F21BFC2CAE71C9FDE4604C064CF5FFB686BAE5DBAAD7FDD34C",
+        // cacerts alias: thawtepremiumserverca
+        // DN: EMAILADDRESS=premium-server@thawte.com,
+        //     CN=Thawte Premium Server CA, OU=Certification Services Division,
+        //     O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
+        "3F9F27D583204B9E09C8A3D2066C4B57D3A2479C3693650880505698105DBCE9",
+        // cacerts alias: verisignclass2g2ca
+        // DN: OU=VeriSign Trust Network,
+        //     OU="(c) 1998 VeriSign, Inc. - For authorized use only",
+        //     OU=Class 2 Public Primary Certification Authority - G2,
+        //     O="VeriSign, Inc.", C=US
+        "3A43E220FE7F3EA9653D1E21742EAC2B75C20FD8980305BC502CAF8C2D9B41A1",
+        // cacerts alias: verisignclass3ca
+        // DN: OU=Class 3 Public Primary Certification Authority,
+        //     O="VeriSign, Inc.", C=US
+        "A4B6B3996FC2F306B3FD8681BD63413D8C5009CC4FA329C2CCF0E2FA1B140305",
+        // cacerts alias: verisignclass3g2ca
+        // DN: OU=VeriSign Trust Network,
+        //     OU="(c) 1998 VeriSign, Inc. - For authorized use only",
+        //     OU=Class 3 Public Primary Certification Authority - G2,
+        //     O="VeriSign, Inc.", C=US
+        "83CE3C1229688A593D485F81973C0F9195431EDA37CC5E36430E79C7A888638B",
+        // cacerts alias: verisignclass3g3ca
+        // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G3,
+        //     OU="(c) 1999 VeriSign, Inc. - For authorized use only",
+        //     OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+        "EB04CF5EB1F39AFA762F2BB120F296CBA520C1B97DB1589565B81CB9A17B7244",
+        // cacerts alias: verisignclass3g4ca
+        // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G4,
+        //     OU="(c) 2007 VeriSign, Inc. - For authorized use only",
+        //     OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+        "69DDD7EA90BB57C93E135DC85EA6FCD5480B603239BDC454FC758B2A26CF7F79",
+        // cacerts alias: verisignclass3g5ca
+        // DN: CN=VeriSign Class 3 Public Primary Certification Authority - G5,
+        //     OU="(c) 2006 VeriSign, Inc. - For authorized use only",
+        //     OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+        "9ACFAB7E43C8D880D06B262A94DEEEE4B4659989C3D0CAF19BAF6405E41AB7DF",
+        // cacerts alias: verisignuniversalrootca
+        // DN: CN=VeriSign Universal Root Certification Authority,
+        //     OU="(c) 2008 VeriSign, Inc. - For authorized use only",
+        //     OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+        "2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C"
+    );
+
+    // Any TLS Server certificate that is anchored by one of the Symantec
+    // roots above and is issued after this date will be distrusted.
+    private static final LocalDate APRIL_16_2019 =
+        LocalDate.of(2019, Month.APRIL, 16);
+
+    /**
+     * This method assumes the eeCert is a TLS Server Cert and chains back to
+     * the anchor.
+     *
+     * @param anchor the trust anchor certificate
+     * @param eeCert the certificate to check
+     * @throws ValidatorException if the certificate is distrusted
+     */
+    static void checkDistrust(X509Certificate anchor,
+                              X509Certificate eeCert)
+                              throws ValidatorException {
+        String fp = (anchor instanceof X509CertImpl)
+                    ? ((X509CertImpl)anchor).getFingerprint("SHA-256")
+                    : X509CertImpl.getFingerprint("SHA-256", anchor);
+        if (FINGERPRINTS.contains(fp)) {
+            // reject if certificate is issued after April 16, 2019
+            Date notBefore = eeCert.getNotBefore();
+            LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
+                                                        ZoneOffset.UTC);
+            if (ldNotBefore.isAfter(APRIL_16_2019)) {
+                throw new ValidatorException
+                    ("TLS Server certificate issued after " + APRIL_16_2019 +
+                     " and anchored by a distrusted legacy Symantec root CA: "
+                     + anchor.getSubjectX500Principal(),
+                     ValidatorException.T_UNTRUSTED_CERT, anchor);
+            }
+        }
+    }
+
+    private SymantecTLSPolicy() {}
+}
--- a/src/java.base/share/classes/sun/security/validator/Validator.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/classes/sun/security/validator/Validator.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -275,7 +275,8 @@
             boolean checkUnresolvedCritExts =
                     (type == TYPE_PKIX) ? false : true;
             endEntityChecker.check(chain[0], parameter,
-                                   checkUnresolvedCritExts);
+                                   checkUnresolvedCritExts,
+                                   chain[chain.length-1]);
         }
 
         return chain;
--- a/src/java.base/share/conf/security/java.security	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/conf/security/java.security	Wed Dec 12 08:38:45 2018 -0500
@@ -1088,3 +1088,26 @@
 # the same name, with the same syntax and possible values.
 #
 #jdk.includeInExceptions=hostInfo,jar
+
+#
+# Policies for distrusting Certificate Authorities (CAs).
+#
+# This is a comma separated value of one or more case-sensitive strings, each
+# of which represents a policy for determining if a CA should be distrusted.
+# The supported values are:
+#
+# SYMANTEC_TLS : Distrust TLS Server certificates anchored by
+#                a Symantec root CA and issued after April 16, 2019.
+#
+# Leading and trailing whitespace surrounding each value are ignored.
+# Unknown values are ignored. If the property is commented out or set to the
+# empty String, no policies are enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be supported by other SE implementations. Also, this
+# property does not override other security properties which can restrict
+# certificates such as jdk.tls.disabledAlgorithms or
+# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
+# if this property is not enabled.
+#
+jdk.security.caDistrustPolicies=SYMANTEC_TLS
--- a/src/java.base/share/native/libjava/System.c	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/native/libjava/System.c	Wed Dec 12 08:38:45 2018 -0500
@@ -220,7 +220,6 @@
      * This property may be removed if that mechanism is redesigned
      */
     PUTPROP(propArray, _java_awt_graphicsenv_NDX, sprops->graphics_env);
-    PUTPROP_PlatformString(propArray, _sun_java2d_fontpath_NDX, sprops->font_dir);
 
     /*
      * The sun.desktop property is currently only set for Gnome and Windows desktops.
--- a/src/java.base/share/native/libjava/java_props.h	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/share/native/libjava/java_props.h	Wed Dec 12 08:38:45 2018 -0500
@@ -46,7 +46,6 @@
 #endif
 
     nchar *tmp_dir;
-    nchar *font_dir;
     nchar *user_dir;
 
     char *file_separator;
--- a/src/java.base/unix/classes/java/lang/ProcessImpl.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -412,7 +412,7 @@
                         new BufferedOutputStream(
                             new FileOutputStream(newFileDescriptor(fds[0])));
 
-                stdout = (fds[1] == -1) ?
+                stdout = (fds[1] == -1 || forceNullOutputStream) ?
                          ProcessBuilder.NullInputStream.INSTANCE :
                          new BufferedInputStream(
                              stdout_inner_stream =
@@ -446,7 +446,7 @@
                         ProcessBuilder.NullOutputStream.INSTANCE :
                         new ProcessPipeOutputStream(fds[0]);
 
-                stdout = (fds[1] == -1) ?
+                stdout = (fds[1] == -1 || forceNullOutputStream) ?
                          ProcessBuilder.NullInputStream.INSTANCE :
                          new DeferredCloseProcessPipeInputStream(fds[1]);
 
--- a/src/java.base/unix/native/libjava/java_props_md.c	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/unix/native/libjava/java_props_md.c	Wed Dec 12 08:38:45 2018 -0500
@@ -407,10 +407,6 @@
     sprops.awt_toolkit = "sun.awt.X11.XToolkit";
 #endif
 
-    /* This is used only for debugging of font problems. */
-    v = getenv("JAVA2D_FONTPATH");
-    sprops.font_dir = v ? v : NULL;
-
 #ifdef SI_ISALIST
     /* supported instruction sets */
     {
--- a/src/java.base/windows/native/libjava/java_props_md.c	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.base/windows/native/libjava/java_props_md.c	Wed Dec 12 08:38:45 2018 -0500
@@ -379,11 +379,6 @@
     /* Java2D properties */
     sprops.graphics_env = "sun.awt.Win32GraphicsEnvironment";
 
-    {    /* This is used only for debugging of font problems. */
-        WCHAR *path = _wgetenv(L"JAVA2D_FONTPATH");
-        sprops.font_dir = (path != NULL) ? _wcsdup(path) : NULL;
-    }
-
     /* OS properties */
     {
         char buf[100];
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1264,27 +1264,18 @@
     }
 
     private void orderAboveSiblings() {
+        // Recursively pop up the windows from the very bottom, (i.e. root owner) so that
+        // the windows are ordered above their nearest owner; ancestors of the window,
+        // which is going to become 'main window', are placed above their siblings.
         CPlatformWindow rootOwner = getRootOwner();
+        if (rootOwner.isVisible() && !rootOwner.isIconified() && !rootOwner.isActive()) {
+            rootOwner.execute(CWrapper.NSWindow::orderFront);
+        }
 
         // Do not order child windows of iconified owner.
         if (!rootOwner.isIconified()) {
             final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
-            Window[] windows = windowAccessor.getOwnedWindows(rootOwner.target);
-
-            // No need to order windows if it doesn't own other windows and hence return
-            if (windows.length == 0) {
-                return;
-            }
-
-            // Recursively pop up the windows from the very bottom, (i.e. root owner) so that
-            // the windows are ordered above their nearest owner; ancestors of the window,
-            // which is going to become 'main window', are placed above their siblings.
-            if (rootOwner.isVisible()) {
-                rootOwner.execute(CWrapper.NSWindow::orderFront);
-            }
-
-            // Order child windows.
-            orderAboveSiblingsImpl(windows);
+            orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
         }
     }
 
--- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStream.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -414,8 +414,8 @@
 
     /**
      * Reads in a string that has been encoded using a
-     * <a href="../../../java/io/DataInput.html#modified-utf-8">modified
-     * UTF-8</a>
+     * <a href="../../../../java.base/java/io/DataInput.html#modified-utf-8">
+     * modified UTF-8</a>
      * format.  The general contract of {@code readUTF} is that
      * it reads a representation of a Unicode character string encoded
      * in modified UTF-8 format; this string of characters is
--- a/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageOutputStream.java	Wed Dec 12 08:38:45 2018 -0500
@@ -367,8 +367,8 @@
     /**
      * Writes two bytes of length information to the output stream in
      * network byte order, followed by the
-     * <a href="../../../java/io/DataInput.html#modified-utf-8">modified
-     * UTF-8</a>
+     * <a href="../../../../java.base/java/io/DataInput.html#modified-utf-8">
+     * modified UTF-8</a>
      * representation of every character in the string {@code s}.
      * If {@code s} is {@code null}, a
      * {@code NullPointerException} is thrown.  Each character in
--- a/src/java.desktop/share/classes/javax/swing/Action.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/swing/Action.java	Wed Dec 12 08:38:45 2018 -0500
@@ -370,7 +370,7 @@
      * Determines whether the action should be performed with the specified
      * sender object. The {@code sender} can be {@code null}.
      * The method must return false if the action is disabled.
-     * <p>
+     *
      * @param sender the object to check, can be null
      * @return {@code true} if the action should be performed with the sender
      *         object, must be false if the action is disabled.
--- a/src/java.desktop/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html	Wed Dec 12 08:38:45 2018 -0500
@@ -251,16 +251,14 @@
 the <code>javax.swing.plaf</code> package.
 </p>
 
-<a id="dosanddonts">
+<a id="dosanddonts"></a>
   <h3>Dos and Don'ts</h3>
-</a>
 
 <p>
 The following paragraphs provide some general recommendations for developing
 auxiliary look and feels.
 </p>
 
-<p>
 <h4>Use the <code>installUI</code> method
 to perform all initialization,
 and the <code>uninstallUI</code> method
--- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html	Wed Dec 12 08:38:45 2018 -0500
@@ -32,8 +32,12 @@
 <body>
 <main role="main">
 <h1 id="primaryColors">Primary Colors</h1>
-<table summary="Nimbus primary colors">
+<table>
+<caption>Primary colors used in Nimbus Look And Feel</caption>
+<thead>
 <tr><th>Key</th><th>Value</th><th>Preview</th></tr>
+</thead>
+<tbody>
 <tr>
 <td width="250"><code>control</code></td>
 <td><pre>#d6d9df (214,217,223)</pre></td>
@@ -110,11 +114,16 @@
 <td><pre>#000000 (0,0,0)</pre></td>
 <td width="100" bgcolor="#000000">&nbsp;</td>
 </tr>
+</tbody>
 </table>
 
 <h1 id="secondaryColors">Secondary Colors</h1>
-<table summary="Nimbus secondary colors">
+<table>
+<caption>Secondary colors used in Nimbus Look And Feel </caption>
+<thead>
 <tr><th>Key</th><th>Value</th><th>Preview</th></tr>
+</thead>
+<tbody>
 <tr>
 <td width="250"><code>activeCaption</code></td>
 
@@ -229,6 +238,7 @@
 <td><pre>#8e8f91 (142,143,145)</pre></td>
 <td width="100" bgcolor="#8e8f91">&nbsp;</td>
 </tr>
+</tbody>
 </table>
 </main>
 </body>
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/componentProperties.html	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/componentProperties.html	Wed Dec 12 08:38:45 2018 -0500
@@ -53,8 +53,8 @@
 In       addition to the <a
  href="#buttonProperties">Button 	properties</a>, ArrowButton supports
 the following properties: </p>
-<h3>ArrowButton Specific Properties</h3>
-<table border="1" summary="ArrowButton specific properties">
+<table border="1">
+<caption>ArrowButton Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -75,8 +75,8 @@
 <p> JButton paints text using the TEXT_FOREGROUND ColorType. In addition
 to the <a href="#buttonProperties">Button 	properties</a>, JButton
 supports the following property: </p>
-<h3>JButton Specific Properties</h3>
-<table border="1" summary="JButton specific properties">
+<table border="1">
+<caption>JButton Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -98,8 +98,8 @@
 <p> JCheckBox paints text using the TEXT_FOREGROUND ColorType. In
 addition to the <a href="#buttonProperties">Button 	properties</a>,
 JCheckBox supports the following property: </p>
-<h3>JCheckBox Specific Properties</h3>
-<table border="1" summary="JCheckBox specific properties">
+<table border="1">
+<caption>JCheckBox Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -119,7 +119,8 @@
 <h2><a id="JComboBox">JComboBox</a></h2>
 <p> JComboBox is a composite component that consists of the following
 child Components: </p>
-<table border="1" summary="JComboBox child components">
+<table border="1">
+<caption>JComboBox child components</caption>
   <thead><tr>
     <th>Name</th>
     <th>Type</th>
@@ -165,8 +166,9 @@
   </tbody>
 </table>
 
-<h3>JComboBox Specific Properties</h3>
-<table border="1" summary="JComboBox specific properties">
+<p>&nbsp;</p>
+<table border="1">
+<caption>JComboBox Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -185,9 +187,8 @@
 </table>
 <br>
 <h2>JFileChooser</h2>
-<h3>JFileChooser Specific Properties</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JFileChooser specific properties"
- style="width: 100%; text-align: left;">
+<table cellpadding="2" cellspacing="2" border="1" style="width: 100%; text-align: left;">
+<caption>JFileChooser Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property</th>
@@ -345,9 +346,8 @@
 </table>
 <br>
 <h2><a id="JInternalFrame"></a>JInternalFrame</h2>
-<h3>JInternalFrame Specific Properties</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JInternalFrame specific properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
+<caption>JInternalFrame Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property<br>
@@ -378,9 +378,8 @@
 <p>JInternalFrameTitlePane is the control bar located at the top of the
 internal frame similar to that found in a frame.<br>
 </p>
-<h3>JInternalFrameTitlePane Specific Properties</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JInternalFrameTitlePane specific properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
+<caption>JInternalFrameTitlePane Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property<br>
@@ -477,8 +476,8 @@
 <h2><a id="JList">JList</a></h2>
 <p> JList's sets the name of the renderer to List.renderer.       JList
 supports the following properties: </p>
-<h3>JList Specific Properties</h3>
-<table border="1" summary="JList specific properties">
+<table border="1">
+<caption>JList Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -521,7 +520,8 @@
 MENU_ITEM_ACCELERATOR is used for painting the accelerator. Both Regions
 paint text using the TEXT_FOREGROUND ColorType. The following set of
 properties are supported: </p>
-<table border="1" summary="Menu classes common properties">
+<table border="1">
+<caption>Menu classes common properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -575,7 +575,8 @@
 <p> <code>Prefix</code> is one of: CheckBoxMenuItem, Menu, MenuItem, or
 RadioButtonMenuItem. </p>
 <p> JMenu also supports the following properties: </p>
-<table border="1" summary="JMenu specific properties">
+<table border="1">
+<caption>JMenu specific properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -603,8 +604,8 @@
 components, they are: OptionPane.button, OptionPane.label,
 OptionPane.comboBox, OptionPane.scrollPane, OptionPane.list,
 OptionPane.textField, OptionPane.iconLabel. </p>
-<h3>JOptionPane Specific Properties</h3>
-<table border="1" summary="JOptionPane specific properties">
+<table border="1">
+<caption>JOptionPane Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -716,10 +717,8 @@
 <br>
 <h2><a id="JProgressBar"></a>JProgressBar<br>
 </h2>
-<h3>JProgressBar Specific Properties<br>
-</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JProgressBar specific properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
+<caption>JProgressBar Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property</th>
@@ -758,8 +757,8 @@
 <p> JRadioButton paints text using the TEXT_FOREGROUND ColorType. In
 addition to the <a href="#buttonProperties">Button 	properties</a>,
 JRadioButton supports the following property: </p>
-<h3>JRadioButton Specific Properties</h3>
-<table border="1" summary="JRadioButton specific properties">
+<table border="1">
+<caption>JRadioButton Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -779,7 +778,8 @@
 <h2><a id="JScrollBar">JScrollBar</a></h2>
 <p> JScrollBar is a composite component that consists of the following
 child Components: </p>
-<table border="1" summary="JScrollBar child components">
+<table border="1">
+<caption>JScrollBar child components</caption>
   <thead><tr>
     <th>Name</th>
     <th>Type</th>
@@ -794,8 +794,9 @@
   </tbody>
 </table>
 
-<h3>JScrollBar Specific Properties</h3>
-<table border="1" summary="JScrollBar specific properties">
+<p>&nbsp;</p>
+<table border="1">
+<caption>JScrollBar Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -849,7 +850,8 @@
 <h2><a id="Separator">Separators</a></h2>
 <p> All of the separator classes, JSeparator, JPopupMenu.Separator and
 JToolBar.Separator use the same property: </p>
-<table border="1" summary="Separator classes common properties">
+<table border="1">
+<caption>Separator classes common properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -868,7 +870,8 @@
   </tbody>
 </table>
 <p> JToolBar.Separator also supports the following property: </p>
-<table border="1" summary="JToolBar.Separator specific properties">
+<table border="1">
+<caption>JToolBar.Separator specific properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -901,8 +904,8 @@
       <code>paintViewportBorder</code> is called to paint the
       <code>Viewport</code>s border.
  </p>
-<h3>JScrollPane Specific Properties</h3>
-<table border="1" summary="JScrollPane specific properties">
+<table border="1">
+<caption>JScrollPane Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -925,8 +928,8 @@
 invoked. The two buttons will be named:
 SplitPaneDivider.leftOneTouchButton and
 SplitPaneDivider.rightOneTouchButton. </p>
-<h3>JSplitPane Specific Properties</h3>
-<table border="1" summary="JSplitPane specific properties">
+<table border="1">
+<caption>JSplitPane Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -969,9 +972,8 @@
 </table>
 <br>
 <h2><a id="JSlider"></a>JSlider</h2>
-<h3>JSlider Specific Properties</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JSlider specific properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
+<caption>JSlider Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property<br>
@@ -1029,9 +1031,8 @@
 </table>
 <br>
 <h2><a id="JTabbedPane"></a>JTabbedPane</h2>
-<h3>JTabbedPane Specific Properties</h3>
-<table cellpadding="2" cellspacing="2" border="1" summary="JTabbedPane specific properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
+<caption>JTabbedPane Specific Properties</caption>
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property</th>
@@ -1093,8 +1094,8 @@
 <h2><a id="JTable">JTable</a></h2>
 <p> JTable sets the name of the renderer to Table.cellRenderer.
 JTable supports the following properties: </p>
-<h3>JTable Specific Properties</h3>
-<table border="1" summary="JTable specific properties">
+<table border="1">
+<caption>JTable Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -1138,8 +1139,8 @@
 <h2><a id="JTree">JTree</a></h2>
 <p> JTree sets the name of the renderer to Tree.renderer, the name of
 the editor is Tree.cellEditor.</p>
-<h3>JTree Specific Properties</h3>
-<table border="1" summary="JTree specific properties">
+<table border="1">
+<caption>JTree Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -1222,8 +1223,8 @@
 <p> JToggleButton paints text using the TEXT_FOREGROUND ColorType. In
 addition to the <a href="#buttonProperties">Button 	properties</a>,
 JToggleButton supports the following property: </p>
-<h3>JToggleButton Specific Properties</h3>
-<table border="1" summary="JToggleButton specific properties">
+<table border="1">
+<caption>JToggleButton Specific Properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -1244,7 +1245,8 @@
 <p> Each of the Button classes (JButton, JCheckBox, JRadioButton,
 JToggleButton and SynthArrowButton) support a similar set of properties.
 These properties are: </p>
-<table border="1" summary="Button classes common properties">
+<table border="1">
+<caption>Button classes common properties</caption>
   <thead><tr>
     <th>Property</th>
     <th>Expected Type</th>
@@ -1295,8 +1297,7 @@
 </p>
 <h2><a id="textProperties"></a>Text Properties<br>
 </h2>
-<table cellpadding="2" cellspacing="2" border="1" summary="Text properties"
- style="text-align: left; width: 100%;">
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 100%;">
   <tbody>
     <tr>
       <th style="vertical-align: top; text-align: center;">Property</th>
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html	Wed Dec 12 08:38:45 2018 -0500
@@ -776,7 +776,8 @@
       The following outlines which painter will be used for what
       SynthPainter method:
     </p>
-    <table border=1 summary="Painters for SynthPainter methods">
+    <table border=1>
+     <caption> Painters for SynthPainter methods </caption>
       <tr><th>State<th>Method<th>Painter
 	<tr><td>SELECTED<td>paintButtonBackground<td>stateButtonBackgroundPainter
 	<tr><td>SELECTED<td>Anything but paintButtonBackground<td>stateFallbackPainter
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Wed Dec 12 08:38:45 2018 -0500
@@ -694,7 +694,7 @@
     int error, imageSize;
     UInt16 width, height;
     GlyphInfo *glyphInfo;
-    int renderFlags = FT_LOAD_RENDER, target;
+    int renderFlags = FT_LOAD_DEFAULT, target;
     FT_GlyphSlot ftglyph;
 
     FTScalerContext* context =
--- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -394,9 +394,12 @@
         return;
     }
 
-    jboolean isCopy;
-    jlong *lFormats = env->GetLongArrayElements(formats, &isCopy),
+    jlong *lFormats = env->GetLongArrayElements(formats, 0),
         *saveFormats = lFormats;
+    if (lFormats == NULL) {
+        m_ntypes = 0;
+        return;
+    }
 
     for (i = 0, m_ntypes = 0; i < items; i++, lFormats++) {
         // Warning C4244.
@@ -422,6 +425,7 @@
         m_types = (FORMATETC *)safe_Calloc(sizeof(FORMATETC), m_ntypes);
     } catch (std::bad_alloc&) {
         m_ntypes = 0;
+        env->ReleaseLongArrayElements(formats, saveFormats, 0);
         throw;
     }
 
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Wed Dec 12 08:38:45 2018 -0500
@@ -333,8 +333,7 @@
         AOTKlassData data = klassData.get(name);
         if (data != null) {
             HotSpotResolvedObjectType oldType = data.getType();
-            assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() +
-                            ", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
+            assert oldType.equals(type) : "duplicate classes for name " + type.getName();
         }
         return data;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1121,7 +1121,7 @@
 
     public void visitVarDef(JCVariableDecl tree) {
         // Local variables have not been entered yet, so we need to do it now:
-        if (env.info.scope.owner.kind == MTH) {
+        if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
             if (tree.sym != null) {
                 // parameters have already been entered
                 env.info.scope.enter(tree.sym);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1633,7 +1633,7 @@
         protected boolean trackable(VarSymbol sym) {
             return
                 sym.pos >= startPos &&
-                ((sym.owner.kind == MTH ||
+                ((sym.owner.kind == MTH || sym.owner.kind == VAR ||
                 isFinalUninitializedField(sym)));
         }
 
@@ -2009,7 +2009,7 @@
             lint = lint.augment(tree.sym);
             try{
                 boolean track = trackable(tree.sym);
-                if (track && tree.sym.owner.kind == MTH) {
+                if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
                     newVar(tree);
                 }
                 if (tree.init != null) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,8 +25,6 @@
 
 package com.sun.tools.javac.jvm;
 
-import java.util.function.BiConsumer;
-
 import com.sun.tools.javac.tree.TreeInfo.PosKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -166,6 +164,7 @@
     boolean inCondSwitchExpression;
     Chain switchExpressionTrueChain;
     Chain switchExpressionFalseChain;
+    List<LocalItem> stackBeforeSwitchExpression;
 
     /** Generate code to load an integer constant.
      *  @param n     The integer to be loaded.
@@ -1178,13 +1177,59 @@
     }
 
     private void doHandleSwitchExpression(JCSwitchExpression tree) {
-        int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+        List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression;
+        int limit = code.nextreg;
         try {
-            handleSwitch(tree, tree.selector, tree.cases);
+            stackBeforeSwitchExpression = List.nil();
+            if (hasTry(tree)) {
+                //if the switch expression contains try-catch, the catch handlers need to have
+                //an empty stack. So stash whole stack to local variables, and restore it before
+                //breaks:
+                while (code.state.stacksize > 0) {
+                    Type type = code.state.peek();
+                    Name varName = names.fromString(target.syntheticNameChar() +
+                                                    "stack" +
+                                                    target.syntheticNameChar() +
+                                                    tree.pos +
+                                                    target.syntheticNameChar() +
+                                                    code.state.stacksize);
+                    VarSymbol var = new VarSymbol(Flags.SYNTHETIC, varName, type,
+                                                  this.env.enclMethod.sym);
+                    LocalItem item = items.new LocalItem(type, code.newLocal(var));
+                    stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item);
+                    item.store();
+                }
+            }
+            int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+            try {
+                handleSwitch(tree, tree.selector, tree.cases);
+            } finally {
+                code.setLetExprStackPos(prevLetExprStart);
+            }
         } finally {
-            code.setLetExprStackPos(prevLetExprStart);
+            stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
+            code.endScopes(limit);
         }
     }
+    //where:
+        private boolean hasTry(JCSwitchExpression tree) {
+            boolean[] hasTry = new boolean[1];
+            new TreeScanner() {
+                @Override
+                public void visitTry(JCTry tree) {
+                    hasTry[0] = true;
+                }
+
+                @Override
+                public void visitClassDef(JCClassDecl tree) {
+                }
+
+                @Override
+                public void visitLambda(JCLambda tree) {
+                }
+            }.scan(tree);
+            return hasTry[0];
+        }
 
     private void handleSwitch(JCTree swtch, JCExpression selector, List<JCCase> cases) {
         int limit = code.nextreg;
@@ -1659,14 +1704,17 @@
     }
 
     public void visitBreak(JCBreak tree) {
-        int tmpPos = code.pendingStatPos;
         Assert.check(code.isStatementStart());
-        Env<GenContext> targetEnv = unwind(tree.target, env);
-        code.pendingStatPos = tmpPos;
+        final Env<GenContext> targetEnv;
         if (tree.isValueBreak()) {
+            //restore stack as it was before the switch expression:
+            for (LocalItem li : stackBeforeSwitchExpression) {
+                li.load();
+            }
             if (inCondSwitchExpression) {
                 CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
                 Chain falseJumps = value.jumpFalse();
+                targetEnv = unwindBreak(tree);
                 code.resolve(value.trueJumps);
                 Chain trueJumps = code.branch(goto_);
                 if (switchExpressionTrueChain == null) {
@@ -1684,13 +1732,22 @@
             } else {
                 genExpr(tree.value, pt).load();
                 code.state.forceStackTop(tree.target.type);
+                targetEnv = unwindBreak(tree);
                 targetEnv.info.addExit(code.branch(goto_));
             }
         } else {
+            targetEnv = unwindBreak(tree);
             targetEnv.info.addExit(code.branch(goto_));
         }
         endFinalizerGaps(env, targetEnv);
     }
+    //where:
+        private Env<GenContext> unwindBreak(JCBreak tree) {
+            int tmpPos = code.pendingStatPos;
+            Env<GenContext> targetEnv = unwind(tree.target, env);
+            code.pendingStatPos = tmpPos;
+            return targetEnv;
+        }
 
     public void visitContinue(JCContinue tree) {
         int tmpPos = code.pendingStatPos;
@@ -2138,7 +2195,7 @@
                 res = items.makeMemberItem(sym, true);
             }
             result = res;
-        } else if (sym.kind == VAR && sym.owner.kind == MTH) {
+        } else if (sym.kind == VAR && (sym.owner.kind == MTH || sym.owner.kind == VAR)) {
             result = items.makeLocalItem((VarSymbol)sym);
         } else if (isInvokeDynamic(sym)) {
             result = items.makeDynamicItem(sym);
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,14 +25,19 @@
 
 package sun.security.ec;
 
+import java.math.*;
 import java.security.*;
 import java.security.interfaces.*;
 import java.security.spec.*;
+import java.util.Optional;
 
 import javax.crypto.*;
 import javax.crypto.spec.*;
 
+import sun.security.util.ArrayUtil;
 import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
 
 /**
  * KeyAgreement implementation for ECDH.
@@ -44,8 +49,8 @@
     // private key, if initialized
     private ECPrivateKey privateKey;
 
-    // encoded public point, non-null between doPhase() & generateSecret() only
-    private byte[] publicValue;
+    // public key, non-null between doPhase() & generateSecret() only
+    private ECPublicKey publicKey;
 
     // length of the secret to be derived
     private int secretLen;
@@ -65,7 +70,7 @@
                         ("Key must be instance of PrivateKey");
         }
         privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
-        publicValue = null;
+        publicKey = null;
     }
 
     // see JCE spec
@@ -87,7 +92,7 @@
         if (privateKey == null) {
             throw new IllegalStateException("Not initialized");
         }
-        if (publicValue != null) {
+        if (publicKey != null) {
             throw new IllegalStateException("Phase already executed");
         }
         if (!lastPhase) {
@@ -99,42 +104,74 @@
                 ("Key must be a PublicKey with algorithm EC");
         }
 
-        ECPublicKey ecKey = (ECPublicKey)key;
-        ECParameterSpec params = ecKey.getParams();
+        this.publicKey = (ECPublicKey) key;
 
-        if (ecKey instanceof ECPublicKeyImpl) {
-            publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
-        } else { // instanceof ECPublicKey
-            publicValue =
-                ECUtil.encodePoint(ecKey.getW(), params.getCurve());
-        }
+        ECParameterSpec params = publicKey.getParams();
         int keyLenBits = params.getCurve().getField().getFieldSize();
         secretLen = (keyLenBits + 7) >> 3;
 
         return null;
     }
 
+    private static void validateCoordinate(BigInteger c, BigInteger mod) {
+        if (c.compareTo(BigInteger.ZERO) < 0) {
+            throw new ProviderException("invalid coordinate");
+        }
+
+        if (c.compareTo(mod) >= 0) {
+            throw new ProviderException("invalid coordinate");
+        }
+    }
+
+    /*
+     * Check whether a public key is valid. Throw ProviderException
+     * if it is not valid or could not be validated.
+     */
+    private static void validate(ECOperations ops, ECPublicKey key) {
+
+        // ensure that integers are in proper range
+        BigInteger x = key.getW().getAffineX();
+        BigInteger y = key.getW().getAffineY();
+
+        BigInteger p = ops.getField().getSize();
+        validateCoordinate(x, p);
+        validateCoordinate(y, p);
+
+        // ensure the point is on the curve
+        EllipticCurve curve = key.getParams().getCurve();
+        BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
+            .multiply(x)).add(curve.getB()).mod(p);
+        BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
+        if (!rhs.equals(lhs)) {
+            throw new ProviderException("point is not on curve");
+        }
+
+        // check the order of the point
+        ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
+        ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
+        AffinePoint affP = new AffinePoint(xElem, yElem);
+        byte[] order = key.getParams().getOrder().toByteArray();
+        ArrayUtil.reverse(order);
+        Point product = ops.multiply(affP, order);
+        if (!ops.isNeutral(product)) {
+            throw new ProviderException("point has incorrect order");
+        }
+
+    }
+
     // see JCE spec
     @Override
     protected byte[] engineGenerateSecret() throws IllegalStateException {
-        if ((privateKey == null) || (publicValue == null)) {
+        if ((privateKey == null) || (publicKey == null)) {
             throw new IllegalStateException("Not initialized correctly");
         }
 
-        byte[] s = privateKey.getS().toByteArray();
-        byte[] encodedParams =                   // DER OID
-            ECUtil.encodeECParameterSpec(null, privateKey.getParams());
-
-        try {
-
-            byte[] result = deriveKey(s, publicValue, encodedParams);
-            publicValue = null;
-            return result;
-
-        } catch (GeneralSecurityException e) {
-            throw new ProviderException("Could not derive key", e);
-        }
-
+        Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
+        byte[] result = resultOpt.orElseGet(
+            () -> deriveKeyNative(privateKey, publicKey)
+        );
+        publicKey = null;
+        return result;
     }
 
     // see JCE spec
@@ -143,7 +180,8 @@
             offset) throws IllegalStateException, ShortBufferException {
         if (offset + secretLen > sharedSecret.length) {
             throw new ShortBufferException("Need " + secretLen
-                + " bytes, only " + (sharedSecret.length - offset) + " available");
+                + " bytes, only " + (sharedSecret.length - offset)
+                + " available");
         }
         byte[] secret = engineGenerateSecret();
         System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
@@ -165,6 +203,78 @@
         return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
     }
 
+    private static
+    Optional<byte[]> deriveKeyImpl(ECPrivateKey priv, ECPublicKey pubKey) {
+
+        ECParameterSpec ecSpec = priv.getParams();
+        EllipticCurve curve = ecSpec.getCurve();
+        Optional<ECOperations> opsOpt = ECOperations.forParameters(ecSpec);
+        if (opsOpt.isEmpty()) {
+            return Optional.empty();
+        }
+        ECOperations ops = opsOpt.get();
+        if (! (priv instanceof ECPrivateKeyImpl)) {
+            return Optional.empty();
+        }
+        ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) priv;
+        byte[] sArr = privImpl.getArrayS();
+
+        // to match the native implementation, validate the public key here
+        // and throw ProviderException if it is invalid
+        validate(ops, pubKey);
+
+        IntegerFieldModuloP field = ops.getField();
+        // convert s array into field element and multiply by the cofactor
+        MutableIntegerModuloP scalar = field.getElement(sArr).mutable();
+        SmallValue cofactor =
+            field.getSmallValue(priv.getParams().getCofactor());
+        scalar.setProduct(cofactor);
+        int keySize = (curve.getField().getFieldSize() + 7) / 8;
+        byte[] privArr = scalar.asByteArray(keySize);
+
+        ImmutableIntegerModuloP x =
+            field.getElement(pubKey.getW().getAffineX());
+        ImmutableIntegerModuloP y =
+            field.getElement(pubKey.getW().getAffineY());
+        AffinePoint affPub = new AffinePoint(x, y);
+        Point product = ops.multiply(affPub, privArr);
+        if (ops.isNeutral(product)) {
+            throw new ProviderException("Product is zero");
+        }
+        AffinePoint affProduct = product.asAffine();
+
+        byte[] result = affProduct.getX().asByteArray(keySize);
+        ArrayUtil.reverse(result);
+
+        return Optional.of(result);
+    }
+
+    private static
+    byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
+
+        ECParameterSpec params = privateKey.getParams();
+        byte[] s = privateKey.getS().toByteArray();
+        byte[] encodedParams =                   // DER OID
+            ECUtil.encodeECParameterSpec(null, params);
+
+        byte[] publicValue;
+        if (publicKey instanceof ECPublicKeyImpl) {
+            ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
+            publicValue = ecPub.getEncodedPublicValue();
+        } else { // instanceof ECPublicKey
+            publicValue =
+                ECUtil.encodePoint(publicKey.getW(), params.getCurve());
+        }
+
+        try {
+            return deriveKey(s, publicValue, encodedParams);
+
+        } catch (GeneralSecurityException e) {
+            throw new ProviderException("Could not derive key", e);
+        }
+    }
+
+
     /**
      * Generates a secret key using the public and private keys.
      *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+package sun.security.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.ArrayUtil;
+import sun.security.util.math.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
+
+import java.security.ProviderException;
+import java.security.spec.*;
+import java.util.Optional;
+
+public class ECDSAOperations {
+
+    public static class Seed {
+        private final byte[] seedValue;
+
+        public Seed(byte[] seedValue) {
+            this.seedValue = seedValue;
+        }
+
+        public byte[] getSeedValue() {
+            return seedValue;
+        }
+    }
+
+    public static class Nonce {
+        private final byte[] nonceValue;
+
+        public Nonce(byte[] nonceValue) {
+            this.nonceValue = nonceValue;
+        }
+
+        public byte[] getNonceValue() {
+            return nonceValue;
+        }
+    }
+
+    private final ECOperations ecOps;
+    private final AffinePoint basePoint;
+
+    public ECDSAOperations(ECOperations ecOps, ECPoint basePoint) {
+        this.ecOps = ecOps;
+        this.basePoint = toAffinePoint(basePoint, ecOps.getField());
+    }
+
+    public ECOperations getEcOperations() {
+        return ecOps;
+    }
+
+    public AffinePoint basePointMultiply(byte[] scalar) {
+        return ecOps.multiply(basePoint, scalar).asAffine();
+    }
+
+    public static AffinePoint toAffinePoint(ECPoint point,
+        IntegerFieldModuloP field) {
+
+        ImmutableIntegerModuloP affineX = field.getElement(point.getAffineX());
+        ImmutableIntegerModuloP affineY = field.getElement(point.getAffineY());
+        return new AffinePoint(affineX, affineY);
+    }
+
+    public static
+    Optional<ECDSAOperations> forParameters(ECParameterSpec ecParams) {
+        Optional<ECOperations> curveOps =
+            ECOperations.forParameters(ecParams);
+        return curveOps.map(
+            ops -> new ECDSAOperations(ops, ecParams.getGenerator())
+        );
+    }
+
+    /**
+     *
+     * Sign a digest using the provided private key and seed.
+     * IMPORTANT: The private key is a scalar represented using a
+     * little-endian byte array. This is backwards from the conventional
+     * representation in ECDSA. The routines that produce and consume this
+     * value uses little-endian, so this deviation from convention removes
+     * the requirement to swap the byte order. The returned signature is in
+     * the conventional byte order.
+     *
+     * @param privateKey the private key scalar as a little-endian byte array
+     * @param digest the digest to be signed
+     * @param seed the seed that will be used to produce the nonce. This object
+     *             should contain an array that is at least 64 bits longer than
+     *             the number of bits required to represent the group order.
+     * @return the ECDSA signature value
+     * @throws IntermediateValueException if the signature cannot be produced
+     *      due to an unacceptable intermediate or final value. If this
+     *      exception is thrown, then the caller should discard the nonnce and
+     *      try again with an entirely new nonce value.
+     */
+    public byte[] signDigest(byte[] privateKey, byte[] digest, Seed seed)
+        throws IntermediateValueException {
+
+        byte[] nonceArr = ecOps.seedToScalar(seed.getSeedValue());
+
+        Nonce nonce = new Nonce(nonceArr);
+        return signDigest(privateKey, digest, nonce);
+    }
+
+    /**
+     *
+     * Sign a digest using the provided private key and nonce.
+     * IMPORTANT: The private key and nonce are scalars represented by a
+     * little-endian byte array. This is backwards from the conventional
+     * representation in ECDSA. The routines that produce and consume these
+     * values use little-endian, so this deviation from convention removes
+     * the requirement to swap the byte order. The returned signature is in
+     * the conventional byte order.
+     *
+     * @param privateKey the private key scalar as a little-endian byte array
+     * @param digest the digest to be signed
+     * @param nonce the nonce object containing a little-endian scalar value.
+     * @return the ECDSA signature value
+     * @throws IntermediateValueException if the signature cannot be produced
+     *      due to an unacceptable intermediate or final value. If this
+     *      exception is thrown, then the caller should discard the nonnce and
+     *      try again with an entirely new nonce value.
+     */
+    public byte[] signDigest(byte[] privateKey, byte[] digest, Nonce nonce)
+        throws IntermediateValueException {
+
+        IntegerFieldModuloP orderField = ecOps.getOrderField();
+        int orderBits = orderField.getSize().bitLength();
+        if (orderBits % 8 != 0 && orderBits < digest.length * 8) {
+            // This implementation does not support truncating digests to
+            // a length that is not a multiple of 8.
+            throw new ProviderException("Invalid digest length");
+        }
+
+        byte[] k = nonce.getNonceValue();
+        // check nonce length
+        int length = (orderField.getSize().bitLength() + 7) / 8;
+        if (k.length != length) {
+            throw new ProviderException("Incorrect nonce length");
+        }
+
+        MutablePoint R = ecOps.multiply(basePoint, k);
+        IntegerModuloP r = R.asAffine().getX();
+        // put r into the correct field by fully reducing to an array
+        byte[] temp = new byte[length];
+        r.asByteArray(temp);
+        r = orderField.getElement(temp);
+        // store r in result
+        r.asByteArray(temp);
+        byte[] result = new byte[2 * length];
+        ArrayUtil.reverse(temp);
+        System.arraycopy(temp, 0, result, 0, length);
+        // compare r to 0
+        if (ECOperations.allZero(temp)) {
+            throw new IntermediateValueException();
+        }
+
+        IntegerModuloP dU = orderField.getElement(privateKey);
+        int lengthE = Math.min(length, digest.length);
+        byte[] E = new byte[lengthE];
+        System.arraycopy(digest, 0, E, 0, lengthE);
+        ArrayUtil.reverse(E);
+        IntegerModuloP e = orderField.getElement(E);
+        IntegerModuloP kElem = orderField.getElement(k);
+        IntegerModuloP kInv = kElem.multiplicativeInverse();
+        MutableIntegerModuloP s = r.mutable();
+        s.setProduct(dU).setSum(e).setProduct(kInv);
+        // store s in result
+        s.asByteArray(temp);
+        ArrayUtil.reverse(temp);
+        System.arraycopy(temp, 0, result, length, length);
+        // compare s to 0
+        if (ECOperations.allZero(temp)) {
+            throw new IntermediateValueException();
+        }
+
+        return result;
+
+    }
+
+}
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Wed Dec 12 08:38:45 2018 -0500
@@ -32,9 +32,11 @@
 import java.security.*;
 import java.security.interfaces.*;
 import java.security.spec.*;
+import java.util.Optional;
 
 import sun.security.jca.JCAUtil;
 import sun.security.util.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
 
 /**
  * ECDSA signature implementation. This class currently supports the
@@ -147,7 +149,7 @@
         // Stores the precomputed message digest value.
         @Override
         protected void engineUpdate(byte[] b, int off, int len)
-                throws SignatureException {
+        throws SignatureException {
             if (offset >= precomputedDigest.length) {
                 offset = RAW_ECDSA_MAX + 1;
                 return;
@@ -172,7 +174,7 @@
         }
 
         @Override
-        protected void resetDigest(){
+        protected void resetDigest() {
             offset = 0;
         }
 
@@ -222,14 +224,14 @@
     // Nested class for SHA224withECDSA signatures
     public static final class SHA224 extends ECDSASignature {
         public SHA224() {
-           super("SHA-224");
+            super("SHA-224");
         }
     }
 
     // Nested class for SHA224withECDSAinP1363Format signatures
     public static final class SHA224inP1363Format extends ECDSASignature {
         public SHA224inP1363Format() {
-           super("SHA-224", true);
+            super("SHA-224", true);
         }
     }
 
@@ -278,7 +280,7 @@
     // initialize for verification. See JCA doc
     @Override
     protected void engineInitVerify(PublicKey publicKey)
-            throws InvalidKeyException {
+    throws InvalidKeyException {
         this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
 
         // Should check that the supplied key is appropriate for signature
@@ -290,14 +292,14 @@
     // initialize for signing. See JCA doc
     @Override
     protected void engineInitSign(PrivateKey privateKey)
-            throws InvalidKeyException {
+    throws InvalidKeyException {
         engineInitSign(privateKey, null);
     }
 
     // initialize for signing. See JCA doc
     @Override
     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
-            throws InvalidKeyException {
+    throws InvalidKeyException {
         this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
 
         // Should check that the supplied key is appropriate for signature
@@ -337,7 +339,7 @@
     // update the signature with the plaintext data. See JCA doc
     @Override
     protected void engineUpdate(byte[] b, int off, int len)
-            throws SignatureException {
+    throws SignatureException {
         messageDigest.update(b, off, len);
         needsReset = true;
     }
@@ -354,20 +356,67 @@
         needsReset = true;
     }
 
-    // sign the data and return the signature. See JCA doc
-    @Override
-    protected byte[] engineSign() throws SignatureException {
+    private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
+        byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
+        throws SignatureException {
+
+        byte[] seedBytes = new byte[(seedBits + 7) / 8];
+        byte[] s = privImpl.getArrayS();
+
+        // Attempt to create the signature in a loop that uses new random input
+        // each time. The chance of failure is very small assuming the
+        // implementation derives the nonce using extra bits
+        int numAttempts = 128;
+        for (int i = 0; i < numAttempts; i++) {
+            random.nextBytes(seedBytes);
+            ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes);
+            try {
+                return ops.signDigest(s, digest, seed);
+            } catch (IntermediateValueException ex) {
+                // try again in the next iteration
+            }
+        }
+
+        throw new SignatureException("Unable to produce signature after "
+            + numAttempts + " attempts");
+    }
+
+
+    private Optional<byte[]> signDigestImpl(ECPrivateKey privateKey,
+        byte[] digest, SecureRandom random) throws SignatureException {
+
+        if (! (privateKey instanceof ECPrivateKeyImpl)) {
+            return Optional.empty();
+        }
+        ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey;
+        ECParameterSpec params = privateKey.getParams();
+
+        // seed is the key size + 64 bits
+        int seedBits = params.getOrder().bitLength() + 64;
+        Optional<ECDSAOperations> opsOpt =
+            ECDSAOperations.forParameters(params);
+        if (opsOpt.isEmpty()) {
+            return Optional.empty();
+        } else {
+            byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
+                privImpl, random);
+            return Optional.of(sig);
+        }
+    }
+
+    private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
+        SecureRandom random) throws SignatureException {
+
         byte[] s = privateKey.getS().toByteArray();
         ECParameterSpec params = privateKey.getParams();
+
         // DER OID
         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
         int keySize = params.getCurve().getField().getFieldSize();
 
         // seed is twice the key size (in bytes) plus 1
         byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
-        if (random == null) {
-            random = JCAUtil.getSecureRandom();
-        }
+
         random.nextBytes(seed);
 
         // random bits needed for timing countermeasures
@@ -375,14 +424,32 @@
         // values must be non-zero to enable countermeasures
         timingArgument |= 1;
 
-        byte[] sig;
         try {
-            sig = signDigest(getDigestValue(), s, encodedParams, seed,
+            return signDigest(digest, s, encodedParams, seed,
                 timingArgument);
         } catch (GeneralSecurityException e) {
             throw new SignatureException("Could not sign data", e);
         }
 
+    }
+
+    // sign the data and return the signature. See JCA doc
+    @Override
+    protected byte[] engineSign() throws SignatureException {
+
+        if (random == null) {
+            random = JCAUtil.getSecureRandom();
+        }
+
+        byte[] digest = getDigestValue();
+        Optional<byte[]> sigOpt = signDigestImpl(privateKey, digest, random);
+        byte[] sig;
+        if (sigOpt.isPresent()) {
+            sig = sigOpt.get();
+        } else {
+            sig = signDigestNative(privateKey, digest, random);
+        }
+
         if (p1363Format) {
             return sig;
         } else {
@@ -400,7 +467,7 @@
         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
 
         if (publicKey instanceof ECPublicKeyImpl) {
-            w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
+            w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
         } else { // instanceof ECPublicKey
             w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
         }
@@ -423,13 +490,13 @@
     @Override
     @Deprecated
     protected void engineSetParameter(String param, Object value)
-            throws InvalidParameterException {
+    throws InvalidParameterException {
         throw new UnsupportedOperationException("setParameter() not supported");
     }
 
     @Override
     protected void engineSetParameter(AlgorithmParameterSpec params)
-            throws InvalidAlgorithmParameterException {
+    throws InvalidAlgorithmParameterException {
         if (params != null) {
             throw new InvalidAlgorithmParameterException("No parameter accepted");
         }
@@ -439,7 +506,7 @@
     @Override
     @Deprecated
     protected Object engineGetParameter(String param)
-            throws InvalidParameterException {
+    throws InvalidParameterException {
         throw new UnsupportedOperationException("getParameter() not supported");
     }
 
@@ -464,7 +531,7 @@
             out.putInteger(r);
             out.putInteger(s);
             DerValue result =
-                new DerValue(DerValue.tag_Sequence, out.toByteArray());
+            new DerValue(DerValue.tag_Sequence, out.toByteArray());
 
             return result.toByteArray();
 
@@ -497,9 +564,9 @@
             // r and s each occupy half the array
             byte[] result = new byte[k << 1];
             System.arraycopy(rBytes, 0, result, k - rBytes.length,
-                rBytes.length);
+            rBytes.length);
             System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
-                sBytes.length);
+            sBytes.length);
             return result;
 
         } catch (Exception e) {
@@ -539,13 +606,13 @@
      * @return byte[] the signature.
      */
     private static native byte[] signDigest(byte[] digest, byte[] s,
-        byte[] encodedParams, byte[] seed, int timing)
-            throws GeneralSecurityException;
+                                            byte[] encodedParams, byte[] seed, int timing)
+        throws GeneralSecurityException;
 
     /**
      * Verifies the signed digest using the public key.
      *
-     * @param signedDigest the signature to be verified. It is encoded
+     * @param signature the signature to be verified. It is encoded
      *        as a concatenation of the key's R and S values.
      * @param digest the digest to be used.
      * @param w the public key's W point (in uncompressed form).
@@ -554,6 +621,6 @@
      * @return boolean true if the signature is successfully verified.
      */
     private static native boolean verifySignedDigest(byte[] signature,
-        byte[] digest, byte[] w, byte[] encodedParams)
-            throws GeneralSecurityException;
+                                                     byte[] digest, byte[] w, byte[] encodedParams)
+        throws GeneralSecurityException;
 }
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECKeyPairGenerator.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -33,13 +33,15 @@
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
 import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.*;
+import java.util.Optional;
 
-import sun.security.ec.ECPrivateKeyImpl;
-import sun.security.ec.ECPublicKeyImpl;
 import sun.security.jca.JCAUtil;
-import sun.security.util.ECParameters;
 import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
 import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE;
+import static sun.security.ec.ECOperations.IntermediateValueException;
 
 /**
  * EC keypair generator.
@@ -90,14 +92,14 @@
         ECParameterSpec ecSpec = null;
 
         if (params instanceof ECParameterSpec) {
-            ecSpec = ECUtil.getECParameterSpec(null,
-                                                    (ECParameterSpec)params);
+            ECParameterSpec ecParams = (ECParameterSpec) params;
+            ecSpec = ECUtil.getECParameterSpec(null, ecParams);
             if (ecSpec == null) {
                 throw new InvalidAlgorithmParameterException(
                     "Unsupported curve: " + params);
             }
         } else if (params instanceof ECGenParameterSpec) {
-            String name = ((ECGenParameterSpec)params).getName();
+            String name = ((ECGenParameterSpec) params).getName();
             ecSpec = ECUtil.getECParameterSpec(null, name);
             if (ecSpec == null) {
                 throw new InvalidAlgorithmParameterException(
@@ -112,8 +114,7 @@
         ensureCurveIsSupported(ecSpec);
         this.params = ecSpec;
 
-        this.keySize =
-            ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
+        this.keySize = ecSpec.getCurve().getField().getFieldSize();
         this.random = random;
     }
 
@@ -141,39 +142,97 @@
     @Override
     public KeyPair generateKeyPair() {
 
-        byte[] encodedParams =
-            ECUtil.encodeECParameterSpec(null, (ECParameterSpec)params);
-
-        // seed is twice the key size (in bytes) plus 1
-        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
-        random.nextBytes(seed);
 
         try {
-
-            Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
+            Optional<KeyPair> kp = generateKeyPairImpl(random);
+            if (kp.isPresent()) {
+                return kp.get();
+            }
+            return generateKeyPairNative(random);
+        } catch (Exception ex) {
+            throw new ProviderException(ex);
+        }
+    }
 
-            // The 'params' object supplied above is equivalent to the native
-            // one so there is no need to fetch it.
-            // keyBytes[0] is the encoding of the native private key
-            BigInteger s = new BigInteger(1, (byte[])keyBytes[0]);
+    private byte[] generatePrivateScalar(SecureRandom random,
+        ECOperations ecOps, int seedSize) {
+        // Attempt to create the private scalar in a loop that uses new random
+        // input each time. The chance of failure is very small assuming the
+        // implementation derives the nonce using extra bits
+        int numAttempts = 128;
+        byte[] seedArr = new byte[seedSize];
+        for (int i = 0; i < numAttempts; i++) {
+            random.nextBytes(seedArr);
+            try {
+                return ecOps.seedToScalar(seedArr);
+            } catch (IntermediateValueException ex) {
+                // try again in the next iteration
+            }
+        }
 
-            PrivateKey privateKey =
-                new ECPrivateKeyImpl(s, (ECParameterSpec)params);
+        throw new ProviderException("Unable to produce private key after "
+                                         + numAttempts + " attempts");
+    }
+
+    private Optional<KeyPair> generateKeyPairImpl(SecureRandom random)
+        throws InvalidKeyException {
+
+        ECParameterSpec ecParams = (ECParameterSpec) params;
 
-            // keyBytes[1] is the encoding of the native public key
-            ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
-                ((ECParameterSpec)params).getCurve());
-            PublicKey publicKey =
-                new ECPublicKeyImpl(w, (ECParameterSpec)params);
+        Optional<ECOperations> opsOpt = ECOperations.forParameters(ecParams);
+        if (opsOpt.isEmpty()) {
+            return Optional.empty();
+        }
+        ECOperations ops = opsOpt.get();
+        IntegerFieldModuloP field = ops.getField();
+        int numBits = ecParams.getOrder().bitLength();
+        int seedBits = numBits + 64;
+        int seedSize = (seedBits + 7) / 8;
+        byte[] privArr = generatePrivateScalar(random, ops, seedSize);
+
+        ECPoint genPoint = ecParams.getGenerator();
+        ImmutableIntegerModuloP x = field.getElement(genPoint.getAffineX());
+        ImmutableIntegerModuloP y = field.getElement(genPoint.getAffineY());
+        AffinePoint affGen = new AffinePoint(x, y);
+        Point pub = ops.multiply(affGen, privArr);
+        AffinePoint affPub = pub.asAffine();
+
+        PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
+
+        ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
+            affPub.getY().asBigInteger());
+        PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
 
-            return new KeyPair(publicKey, privateKey);
+        return Optional.of(new KeyPair(publicKey, privateKey));
+    }
+
+    private KeyPair generateKeyPairNative(SecureRandom random)
+        throws Exception {
+
+        ECParameterSpec ecParams = (ECParameterSpec) params;
+        byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
+
+        // seed is twice the key size (in bytes) plus 1
+        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+        random.nextBytes(seed);
+        Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
 
-        } catch (Exception e) {
-            throw new ProviderException(e);
-        }
+        // The 'params' object supplied above is equivalent to the native
+        // one so there is no need to fetch it.
+        // keyBytes[0] is the encoding of the native private key
+        BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
+
+        PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
+
+        // keyBytes[1] is the encoding of the native public key
+        byte[] pubKey = (byte[]) keyBytes[1];
+        ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
+        PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+        return new KeyPair(publicKey, privateKey);
     }
 
     private void checkKeySize(int keySize) throws InvalidParameterException {
@@ -190,7 +249,9 @@
 
     /**
      * Checks whether the curve in the encoded parameters is supported by the
-     * native implementation.
+     * native implementation. Some curve operations will be performed by the
+     * Java implementation, but not all of them. So native support is still
+     * required for all curves.
      *
      * @param encodedParams encoded parameters in the same form accepted
      *    by generateECKeyPair
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECOperations.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,493 @@
+/*
+ * 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.
+ */
+
+package sun.security.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.math.*;
+import sun.security.util.math.intpoly.*;
+
+import java.math.BigInteger;
+import java.security.ProviderException;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.EllipticCurve;
+import java.util.Map;
+import java.util.Optional;
+
+/*
+ * Elliptic curve point arithmetic for prime-order curves where a=-3.
+ * Formulas are derived from "Complete addition formulas for prime order
+ * elliptic curves" by Renes, Costello, and Batina.
+ */
+
+public class ECOperations {
+
+    /*
+     * An exception indicating a problem with an intermediate value produced
+     * by some part of the computation. For example, the signing operation
+     * will throw this exception to indicate that the r or s value is 0, and
+     * that the signing operation should be tried again with a different nonce.
+     */
+    static class IntermediateValueException extends Exception {
+        private static final long serialVersionUID = 1;
+    }
+
+    static final Map<BigInteger, IntegerFieldModuloP> fields = Map.of(
+        IntegerPolynomialP256.MODULUS, new IntegerPolynomialP256(),
+        IntegerPolynomialP384.MODULUS, new IntegerPolynomialP384(),
+        IntegerPolynomialP521.MODULUS, new IntegerPolynomialP521()
+    );
+
+    static final Map<BigInteger, IntegerFieldModuloP> orderFields = Map.of(
+        P256OrderField.MODULUS, new P256OrderField(),
+        P384OrderField.MODULUS, new P384OrderField(),
+        P521OrderField.MODULUS, new P521OrderField()
+    );
+
+    public static Optional<ECOperations> forParameters(ECParameterSpec params) {
+
+        EllipticCurve curve = params.getCurve();
+        if (!(curve.getField() instanceof ECFieldFp)) {
+            return Optional.empty();
+        }
+        ECFieldFp primeField = (ECFieldFp) curve.getField();
+
+        BigInteger three = BigInteger.valueOf(3);
+        if (!primeField.getP().subtract(curve.getA()).equals(three)) {
+            return Optional.empty();
+        }
+        IntegerFieldModuloP field = fields.get(primeField.getP());
+        if (field == null) {
+            return Optional.empty();
+        }
+
+        IntegerFieldModuloP orderField = orderFields.get(params.getOrder());
+        if (orderField == null) {
+            return Optional.empty();
+        }
+
+        ImmutableIntegerModuloP b = field.getElement(curve.getB());
+        ECOperations ecOps = new ECOperations(b, orderField);
+        return Optional.of(ecOps);
+    }
+
+    final ImmutableIntegerModuloP b;
+    final SmallValue one;
+    final SmallValue two;
+    final SmallValue three;
+    final SmallValue four;
+    final ProjectivePoint.Immutable neutral;
+    private final IntegerFieldModuloP orderField;
+
+    public ECOperations(IntegerModuloP b, IntegerFieldModuloP orderField) {
+        this.b = b.fixed();
+        this.orderField = orderField;
+
+        this.one = b.getField().getSmallValue(1);
+        this.two = b.getField().getSmallValue(2);
+        this.three = b.getField().getSmallValue(3);
+        this.four = b.getField().getSmallValue(4);
+
+        IntegerFieldModuloP field = b.getField();
+        this.neutral = new ProjectivePoint.Immutable(field.get0(),
+            field.get1(), field.get0());
+    }
+
+    public IntegerFieldModuloP getField() {
+        return b.getField();
+    }
+    public IntegerFieldModuloP getOrderField() {
+        return orderField;
+    }
+
+    protected ProjectivePoint.Immutable getNeutral() {
+        return neutral;
+    }
+
+    public boolean isNeutral(Point p) {
+        ProjectivePoint<?> pp = (ProjectivePoint<?>) p;
+
+        IntegerModuloP z = pp.getZ();
+
+        IntegerFieldModuloP field = z.getField();
+        int byteLength = (field.getSize().bitLength() + 7) / 8;
+        byte[] zBytes = z.asByteArray(byteLength);
+        return allZero(zBytes);
+    }
+
+    byte[] seedToScalar(byte[] seedBytes)
+        throws IntermediateValueException {
+
+        // Produce a nonce from the seed using FIPS 186-4,section B.5.1:
+        // Per-Message Secret Number Generation Using Extra Random Bits
+        // or
+        // Produce a scalar from the seed using FIPS 186-4, section B.4.1:
+        // Key Pair Generation Using Extra Random Bits
+
+        // To keep the implementation simple, sample in the range [0,n)
+        // and throw IntermediateValueException in the (unlikely) event
+        // that the result is 0.
+
+        // Get 64 extra bits and reduce in to the nonce
+        int seedBits = orderField.getSize().bitLength() + 64;
+        if (seedBytes.length * 8 < seedBits) {
+            throw new ProviderException("Incorrect seed length: " +
+            seedBytes.length * 8 + " < " + seedBits);
+        }
+
+        // input conversion only works on byte boundaries
+        // clear high-order bits of last byte so they don't influence nonce
+        int lastByteBits = seedBits % 8;
+        if (lastByteBits != 0) {
+            int lastByteIndex = seedBits / 8;
+            byte mask = (byte) (0xFF >>> (8 - lastByteBits));
+            seedBytes[lastByteIndex] &= mask;
+        }
+
+        int seedLength = (seedBits + 7) / 8;
+        IntegerModuloP scalarElem =
+            orderField.getElement(seedBytes, 0, seedLength, (byte) 0);
+        int scalarLength = (orderField.getSize().bitLength() + 7) / 8;
+        byte[] scalarArr = new byte[scalarLength];
+        scalarElem.asByteArray(scalarArr);
+        if (ECOperations.allZero(scalarArr)) {
+            throw new IntermediateValueException();
+        }
+        return scalarArr;
+    }
+
+    /*
+     * Compare all values in the array to 0 without branching on any value
+     *
+     */
+    public static boolean allZero(byte[] arr) {
+        byte acc = 0;
+        for (int i = 0; i < arr.length; i++) {
+            acc |= arr[i];
+        }
+        return acc == 0;
+    }
+
+    /*
+     * 4-bit branchless array lookup for projective points.
+     */
+    private void lookup4(ProjectivePoint.Immutable[] arr, int index,
+        ProjectivePoint.Mutable result, IntegerModuloP zero) {
+
+        for (int i = 0; i < 16; i++) {
+            int xor = index ^ i;
+            int bit3 = (xor & 0x8) >>> 3;
+            int bit2 = (xor & 0x4) >>> 2;
+            int bit1 = (xor & 0x2) >>> 1;
+            int bit0 = (xor & 0x1);
+            int inverse = bit0 | bit1 | bit2 | bit3;
+            int set = 1 - inverse;
+
+            ProjectivePoint.Immutable pi = arr[i];
+            result.conditionalSet(pi, set);
+        }
+    }
+
+    private void double4(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+        MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+        MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+        for (int i = 0; i < 4; i++) {
+            setDouble(p, t0, t1, t2, t3, t4);
+        }
+    }
+
+    /**
+     * Multiply an affine point by a scalar and return the result as a mutable
+     * point.
+     *
+     * @param affineP the point
+     * @param s the scalar as a little-endian array
+     * @return the product
+     */
+    public MutablePoint multiply(AffinePoint affineP, byte[] s) {
+
+        // 4-bit windowed multiply with branchless lookup.
+        // The mixed addition is faster, so it is used to construct the array
+        // at the beginning of the operation.
+
+        IntegerFieldModuloP field = affineP.getX().getField();
+        ImmutableIntegerModuloP zero = field.get0();
+        // temporaries
+        MutableIntegerModuloP t0 = zero.mutable();
+        MutableIntegerModuloP t1 = zero.mutable();
+        MutableIntegerModuloP t2 = zero.mutable();
+        MutableIntegerModuloP t3 = zero.mutable();
+        MutableIntegerModuloP t4 = zero.mutable();
+
+        ProjectivePoint.Mutable result = new ProjectivePoint.Mutable(field);
+        result.getY().setValue(field.get1().mutable());
+
+        ProjectivePoint.Immutable[] pointMultiples =
+            new ProjectivePoint.Immutable[16];
+        // 0P is neutral---same as initial result value
+        pointMultiples[0] = result.fixed();
+
+        ProjectivePoint.Mutable ps = new ProjectivePoint.Mutable(field);
+        ps.setValue(affineP);
+        // 1P = P
+        pointMultiples[1] = ps.fixed();
+
+        // the rest are calculated using mixed point addition
+        for (int i = 2; i < 16; i++) {
+            setSum(ps, affineP, t0, t1, t2, t3, t4);
+            pointMultiples[i] = ps.fixed();
+        }
+
+        ProjectivePoint.Mutable lookupResult = ps.mutable();
+
+        for (int i = s.length - 1; i >= 0; i--) {
+
+            double4(result, t0, t1, t2, t3, t4);
+
+            int high = (0xFF & s[i]) >>> 4;
+            lookup4(pointMultiples, high, lookupResult, zero);
+            setSum(result, lookupResult, t0, t1, t2, t3, t4);
+
+            double4(result, t0, t1, t2, t3, t4);
+
+            int low = 0xF & s[i];
+            lookup4(pointMultiples, low, lookupResult, zero);
+            setSum(result, lookupResult, t0, t1, t2, t3, t4);
+        }
+
+        return result;
+
+    }
+
+    /*
+     * Point double
+     */
+    private void setDouble(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+        MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+        MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+        t0.setValue(p.getX()).setSquare();
+        t1.setValue(p.getY()).setSquare();
+        t2.setValue(p.getZ()).setSquare();
+        t3.setValue(p.getX()).setProduct(p.getY());
+        t4.setValue(p.getY()).setProduct(p.getZ());
+
+        t3.setSum(t3);
+        p.getZ().setProduct(p.getX());
+
+        p.getZ().setProduct(two);
+
+        p.getY().setValue(t2).setProduct(b);
+        p.getY().setDifference(p.getZ());
+
+        p.getX().setValue(p.getY()).setProduct(two);
+        p.getY().setSum(p.getX());
+        p.getY().setReduced();
+        p.getX().setValue(t1).setDifference(p.getY());
+
+        p.getY().setSum(t1);
+        p.getY().setProduct(p.getX());
+        p.getX().setProduct(t3);
+
+        t3.setValue(t2).setProduct(two);
+        t2.setSum(t3);
+        p.getZ().setProduct(b);
+
+        t2.setReduced();
+        p.getZ().setDifference(t2);
+        p.getZ().setDifference(t0);
+        t3.setValue(p.getZ()).setProduct(two);
+        p.getZ().setReduced();
+        p.getZ().setSum(t3);
+        t0.setProduct(three);
+
+        t0.setDifference(t2);
+        t0.setProduct(p.getZ());
+        p.getY().setSum(t0);
+
+        t4.setSum(t4);
+        p.getZ().setProduct(t4);
+
+        p.getX().setDifference(p.getZ());
+        p.getZ().setValue(t4).setProduct(t1);
+
+        p.getZ().setProduct(four);
+
+    }
+
+    /*
+     * Mixed point addition. This method constructs new temporaries each time
+     * it is called. For better efficiency, the method that reuses temporaries
+     * should be used if more than one sum will be computed.
+     */
+    public void setSum(MutablePoint p, AffinePoint p2) {
+
+        IntegerModuloP zero = p.getField().get0();
+        MutableIntegerModuloP t0 = zero.mutable();
+        MutableIntegerModuloP t1 = zero.mutable();
+        MutableIntegerModuloP t2 = zero.mutable();
+        MutableIntegerModuloP t3 = zero.mutable();
+        MutableIntegerModuloP t4 = zero.mutable();
+        setSum((ProjectivePoint.Mutable) p, p2, t0, t1, t2, t3, t4);
+
+    }
+
+    /*
+     * Mixed point addition
+     */
+    private void setSum(ProjectivePoint.Mutable p, AffinePoint p2,
+        MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+        MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+        MutableIntegerModuloP t4) {
+
+        t0.setValue(p.getX()).setProduct(p2.getX());
+        t1.setValue(p.getY()).setProduct(p2.getY());
+        t3.setValue(p2.getX()).setSum(p2.getY());
+        t4.setValue(p.getX()).setSum(p.getY());
+        p.getX().setReduced();
+        t3.setProduct(t4);
+        t4.setValue(t0).setSum(t1);
+
+        t3.setDifference(t4);
+        t4.setValue(p2.getY()).setProduct(p.getZ());
+        t4.setSum(p.getY());
+
+        p.getY().setValue(p2.getX()).setProduct(p.getZ());
+        p.getY().setSum(p.getX());
+        t2.setValue(p.getZ());
+        p.getZ().setProduct(b);
+
+        p.getX().setValue(p.getY()).setDifference(p.getZ());
+        p.getX().setReduced();
+        p.getZ().setValue(p.getX()).setProduct(two);
+        p.getX().setSum(p.getZ());
+
+        p.getZ().setValue(t1).setDifference(p.getX());
+        p.getX().setSum(t1);
+        p.getY().setProduct(b);
+
+        t1.setValue(t2).setProduct(two);
+        t2.setSum(t1);
+        t2.setReduced();
+        p.getY().setDifference(t2);
+
+        p.getY().setDifference(t0);
+        p.getY().setReduced();
+        t1.setValue(p.getY()).setProduct(two);
+        p.getY().setSum(t1);
+
+        t1.setValue(t0).setProduct(two);
+        t0.setSum(t1);
+        t0.setDifference(t2);
+
+        t1.setValue(t4).setProduct(p.getY());
+        t2.setValue(t0).setProduct(p.getY());
+        p.getY().setValue(p.getX()).setProduct(p.getZ());
+
+        p.getY().setSum(t2);
+        p.getX().setProduct(t3);
+        p.getX().setDifference(t1);
+
+        p.getZ().setProduct(t4);
+        t1.setValue(t3).setProduct(t0);
+        p.getZ().setSum(t1);
+
+    }
+
+    /*
+     * Projective point addition
+     */
+    private void setSum(ProjectivePoint.Mutable p, ProjectivePoint.Mutable p2,
+        MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+        MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+        MutableIntegerModuloP t4) {
+
+        t0.setValue(p.getX()).setProduct(p2.getX());
+        t1.setValue(p.getY()).setProduct(p2.getY());
+        t2.setValue(p.getZ()).setProduct(p2.getZ());
+
+        t3.setValue(p.getX()).setSum(p.getY());
+        t4.setValue(p2.getX()).setSum(p2.getY());
+        t3.setProduct(t4);
+
+        t4.setValue(t0).setSum(t1);
+        t3.setDifference(t4);
+        t4.setValue(p.getY()).setSum(p.getZ());
+
+        p.getY().setValue(p2.getY()).setSum(p2.getZ());
+        t4.setProduct(p.getY());
+        p.getY().setValue(t1).setSum(t2);
+
+        t4.setDifference(p.getY());
+        p.getX().setSum(p.getZ());
+        p.getY().setValue(p2.getX()).setSum(p2.getZ());
+
+        p.getX().setProduct(p.getY());
+        p.getY().setValue(t0).setSum(t2);
+        p.getY().setAdditiveInverse().setSum(p.getX());
+        p.getY().setReduced();
+
+        p.getZ().setValue(t2).setProduct(b);
+        p.getX().setValue(p.getY()).setDifference(p.getZ());
+        p.getZ().setValue(p.getX()).setProduct(two);
+
+        p.getX().setSum(p.getZ());
+        p.getX().setReduced();
+        p.getZ().setValue(t1).setDifference(p.getX());
+        p.getX().setSum(t1);
+
+        p.getY().setProduct(b);
+        t1.setValue(t2).setSum(t2);
+        t2.setSum(t1);
+        t2.setReduced();
+
+        p.getY().setDifference(t2);
+        p.getY().setDifference(t0);
+        p.getY().setReduced();
+        t1.setValue(p.getY()).setSum(p.getY());
+
+        p.getY().setSum(t1);
+        t1.setValue(t0).setProduct(two);
+        t0.setSum(t1);
+
+        t0.setDifference(t2);
+        t1.setValue(t4).setProduct(p.getY());
+        t2.setValue(t0).setProduct(p.getY());
+
+        p.getY().setValue(p.getX()).setProduct(p.getZ());
+        p.getY().setSum(t2);
+        p.getX().setProduct(t3);
+
+        p.getX().setDifference(t1);
+        p.getZ().setProduct(t4);
+        t1.setValue(t3).setProduct(t0);
+
+        p.getZ().setSum(t1);
+
+    }
+}
+
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -32,11 +32,7 @@
 import java.security.interfaces.*;
 import java.security.spec.*;
 
-import sun.security.util.DerInputStream;
-import sun.security.util.DerOutputStream;
-import sun.security.util.DerValue;
-import sun.security.util.ECParameters;
-import sun.security.util.ECUtil;
+import sun.security.util.*;
 import sun.security.x509.AlgorithmId;
 import sun.security.pkcs.PKCS8Key;
 
@@ -68,6 +64,7 @@
     private static final long serialVersionUID = 88695385615075129L;
 
     private BigInteger s;       // private value
+    private byte[] arrayS;      // private value as a little-endian array
     private ECParameterSpec params;
 
     /**
@@ -85,13 +82,25 @@
             throws InvalidKeyException {
         this.s = s;
         this.params = params;
-        // generate the encoding
+        makeEncoding(s);
+
+    }
+
+    ECPrivateKeyImpl(byte[] s, ECParameterSpec params)
+            throws InvalidKeyException {
+        this.arrayS = s.clone();
+        this.params = params;
+        makeEncoding(s);
+    }
+
+    private void makeEncoding(byte[] s) throws InvalidKeyException {
         algid = new AlgorithmId
-            (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+        (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
         try {
             DerOutputStream out = new DerOutputStream();
             out.putInteger(1); // version 1
-            byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
+            byte[] privBytes = s.clone();
+            ArrayUtil.reverse(privBytes);
             out.putOctetString(privBytes);
             DerValue val =
                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
@@ -102,6 +111,31 @@
         }
     }
 
+    private void makeEncoding(BigInteger s) throws InvalidKeyException {
+        algid = new AlgorithmId
+        (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+        try {
+            byte[] sArr = s.toByteArray();
+            // convert to fixed-length array
+            int numOctets = (params.getOrder().bitLength() + 7) / 8;
+            byte[] sOctets = new byte[numOctets];
+            int inPos = Math.max(sArr.length - sOctets.length, 0);
+            int outPos = Math.max(sOctets.length - sArr.length, 0);
+            int length = Math.min(sArr.length, sOctets.length);
+            System.arraycopy(sArr, inPos, sOctets, outPos, length);
+
+            DerOutputStream out = new DerOutputStream();
+            out.putInteger(1); // version 1
+            out.putOctetString(sOctets);
+            DerValue val =
+                new DerValue(DerValue.tag_Sequence, out.toByteArray());
+            key = val.toByteArray();
+        } catch (IOException exc) {
+            // should never occur
+            throw new InvalidKeyException(exc);
+        }
+    }
+
     // see JCA doc
     public String getAlgorithm() {
         return "EC";
@@ -109,9 +143,26 @@
 
     // see JCA doc
     public BigInteger getS() {
+        if (s == null) {
+            byte[] arrCopy = arrayS.clone();
+            ArrayUtil.reverse(arrCopy);
+            s = new BigInteger(1, arrCopy);
+        }
         return s;
     }
 
+    public byte[] getArrayS() {
+        if (arrayS == null) {
+            byte[] arr = getS().toByteArray();
+            ArrayUtil.reverse(arr);
+            int byteLength = (params.getOrder().bitLength() + 7) / 8;
+            arrayS = new byte[byteLength];
+            int length = Math.min(byteLength, arr.length);
+            System.arraycopy(arr, 0, arrayS, 0, length);
+        }
+        return arrayS.clone();
+    }
+
     // see JCA doc
     public ECParameterSpec getParams() {
         return params;
@@ -133,12 +184,13 @@
                 throw new IOException("Version must be 1");
             }
             byte[] privData = data.getOctetString();
-            s = new BigInteger(1, privData);
+            ArrayUtil.reverse(privData);
+            arrayS = privData;
             while (data.available() != 0) {
                 DerValue value = data.getDerValue();
-                if (value.isContextSpecific((byte)0)) {
+                if (value.isContextSpecific((byte) 0)) {
                     // ignore for now
-                } else if (value.isContextSpecific((byte)1)) {
+                } else if (value.isContextSpecific((byte) 1)) {
                     // ignore for now
                 } else {
                     throw new InvalidKeyException("Unexpected value: " + value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/AffinePoint.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package sun.security.ec.point;
+
+import sun.security.util.math.ImmutableIntegerModuloP;
+
+import java.util.Objects;
+
+/**
+ * Elliptic curve point represented using affine coordinates (x, y). This class
+ * is not part of the sun.security.ec.point.Point hierarchy because it is not
+ * used to hold intermediate values during point arithmetic, and so it does not
+ * have a mutable form.
+ */
+public class AffinePoint {
+
+    private final ImmutableIntegerModuloP x;
+    private final ImmutableIntegerModuloP y;
+
+    public AffinePoint(ImmutableIntegerModuloP x, ImmutableIntegerModuloP y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public ImmutableIntegerModuloP getX() {
+        return x;
+    }
+
+    public ImmutableIntegerModuloP getY() {
+        return y;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AffinePoint)) {
+            return false;
+        }
+        AffinePoint p = (AffinePoint) obj;
+        boolean xEquals = x.asBigInteger().equals(p.x.asBigInteger());
+        boolean yEquals = y.asBigInteger().equals(p.y.asBigInteger());
+        return xEquals && yEquals;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, y);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + x.asBigInteger().toString() + "," +
+            y.asBigInteger().toString() + ")";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ImmutablePoint.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package sun.security.ec.point;
+
+/**
+ * An interface for immutable points on an elliptic curve over a finite field.
+ */
+public interface ImmutablePoint extends Point {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/MutablePoint.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package sun.security.ec.point;
+
+/**
+ * An interface for mutable points on an elliptic curve over a finite field.
+ */
+public interface MutablePoint extends Point {
+
+    MutablePoint setValue(AffinePoint p);
+    MutablePoint setValue(Point p);
+    MutablePoint conditionalSet(Point p, int set);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/Point.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package sun.security.ec.point;
+
+import sun.security.util.math.IntegerFieldModuloP;
+
+/**
+ * A base interface for points on an elliptic curve over a finite field.
+ * Implementations may use different representations for points, and this
+ * interface creates a common API for manipulating points. This API has no
+ * methods for point arithmetic, which depends on group structure and curve
+ * parameters in addition to point representation.
+ */
+public interface Point {
+
+    IntegerFieldModuloP getField();
+    AffinePoint asAffine();
+
+    ImmutablePoint fixed();
+    MutablePoint mutable();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/point/ProjectivePoint.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+package sun.security.ec.point;
+
+import sun.security.util.math.*;
+
+/**
+ * Elliptic curve point in projective coordinates (X, Y, Z) where
+ * an affine point (x, y) is represented using any (X, Y, Z) s.t.
+ * x = X/Z and y = Y/Z.
+ */
+public abstract class ProjectivePoint
+    <T extends IntegerModuloP> implements Point {
+
+    protected final T x;
+    protected final T y;
+    protected final T z;
+
+    protected ProjectivePoint(T x, T y, T z) {
+
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    @Override
+    public IntegerFieldModuloP getField() {
+        return this.x.getField();
+    }
+
+    @Override
+    public Immutable fixed() {
+        return new Immutable(x.fixed(), y.fixed(), z.fixed());
+    }
+
+    @Override
+    public Mutable mutable() {
+        return new Mutable(x.mutable(), y.mutable(), z.mutable());
+    }
+
+    public T getX() {
+        return x;
+    }
+
+    public T getY() {
+        return y;
+    }
+
+    public T getZ() {
+        return z;
+    }
+
+    public AffinePoint asAffine() {
+        IntegerModuloP zInv = z.multiplicativeInverse();
+        return new AffinePoint(x.multiply(zInv), y.multiply(zInv));
+    }
+
+    public static class Immutable
+        extends ProjectivePoint<ImmutableIntegerModuloP>
+        implements ImmutablePoint {
+
+        public Immutable(ImmutableIntegerModuloP x,
+                         ImmutableIntegerModuloP y,
+                         ImmutableIntegerModuloP z) {
+            super(x, y, z);
+        }
+    }
+
+    public static class Mutable
+        extends ProjectivePoint<MutableIntegerModuloP>
+        implements MutablePoint {
+
+        public Mutable(MutableIntegerModuloP x,
+                       MutableIntegerModuloP y,
+                       MutableIntegerModuloP z) {
+            super(x, y, z);
+        }
+
+        public Mutable(IntegerFieldModuloP field) {
+            super(field.get0().mutable(),
+                field.get0().mutable(),
+                field.get0().mutable());
+        }
+
+        @Override
+        public Mutable conditionalSet(Point p, int set) {
+            if (!(p instanceof ProjectivePoint)) {
+                throw new RuntimeException("Incompatible point");
+            }
+            @SuppressWarnings("unchecked")
+            ProjectivePoint<IntegerModuloP> pp =
+                (ProjectivePoint<IntegerModuloP>) p;
+            return conditionalSet(pp, set);
+        }
+
+        private <T extends IntegerModuloP>
+        Mutable conditionalSet(ProjectivePoint<T> pp, int set) {
+
+            x.conditionalSet(pp.x, set);
+            y.conditionalSet(pp.y, set);
+            z.conditionalSet(pp.z, set);
+
+            return this;
+        }
+
+        @Override
+        public Mutable setValue(AffinePoint p) {
+            x.setValue(p.getX());
+            y.setValue(p.getY());
+            z.setValue(p.getX().getField().get1());
+
+            return this;
+        }
+
+        @Override
+        public Mutable setValue(Point p) {
+            if (!(p instanceof ProjectivePoint)) {
+                throw new RuntimeException("Incompatible point");
+            }
+            @SuppressWarnings("unchecked")
+            ProjectivePoint<IntegerModuloP> pp =
+                (ProjectivePoint<IntegerModuloP>) p;
+            return setValue(pp);
+        }
+
+        private <T extends IntegerModuloP>
+        Mutable setValue(ProjectivePoint<T> pp) {
+
+            x.setValue(pp.x);
+            y.setValue(pp.y);
+            z.setValue(pp.z);
+
+            return this;
+        }
+
+    }
+
+}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/DefaultTerminal2.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import jdk.internal.jline.internal.InfoCmp;
-
-/**
- * Terminal wrapper with default ansi capabilities
- */
-public class DefaultTerminal2 implements Terminal2 {
-
-    private final Terminal terminal;
-    private final Set<String> bools = new HashSet<String>();
-    private final Map<String, String> strings = new HashMap<String, String>();
-
-    public DefaultTerminal2(Terminal terminal) {
-        this.terminal = terminal;
-        registerCap("key_backspace", "^H");
-        registerCap("bell", "^G");
-        registerCap("carriage_return", "^M");
-        if (true/*isSupported() && isAnsiSupported()*/) {
-            registerCap("clr_eol", "\\E[K");
-            registerCap("clr_bol", "\\E[1K");
-            registerCap("cursor_up", "\\E[A");
-            registerCap("cursor_down", "^J");
-            registerCap("column_address", "\\E[%i%p1%dG");
-            registerCap("clear_screen", "\\E[H\\E[2J");
-            registerCap("parm_down_cursor", "\\E[%p1%dB");
-            registerCap("cursor_left", "^H");
-            registerCap("cursor_right", "\\E[C");
-        }
-        if (hasWeirdWrap()) {
-            registerCap("eat_newline_glitch");
-            registerCap("auto_right_margin");
-        }
-    }
-
-    public void init() throws Exception {
-        terminal.init();
-    }
-
-    public void restore() throws Exception {
-        terminal.restore();
-    }
-
-    public void reset() throws Exception {
-        terminal.reset();
-    }
-
-    public boolean isSupported() {
-        return terminal.isSupported();
-    }
-
-    public int getWidth() {
-        return terminal.getWidth();
-    }
-
-    public int getHeight() {
-        return terminal.getHeight();
-    }
-
-    public boolean isAnsiSupported() {
-        return terminal.isAnsiSupported();
-    }
-
-    public OutputStream wrapOutIfNeeded(OutputStream out) {
-        return terminal.wrapOutIfNeeded(out);
-    }
-
-    public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-        return terminal.wrapInIfNeeded(in);
-    }
-
-    public boolean hasWeirdWrap() {
-        return terminal.hasWeirdWrap();
-    }
-
-    public boolean isEchoEnabled() {
-        return terminal.isEchoEnabled();
-    }
-
-    public void setEchoEnabled(boolean enabled) {
-        terminal.setEchoEnabled(enabled);
-    }
-
-    public void disableInterruptCharacter() {
-        terminal.disableInterruptCharacter();
-    }
-
-    public void enableInterruptCharacter() {
-        terminal.enableInterruptCharacter();
-    }
-
-    public String getOutputEncoding() {
-        return terminal.getOutputEncoding();
-    }
-
-    private void registerCap(String cap, String value) {
-        for (String key : InfoCmp.getNames(cap)) {
-            strings.put(key, value);
-        }
-    }
-
-    private void registerCap(String cap) {
-        Collections.addAll(bools, InfoCmp.getNames(cap));
-    }
-
-    public boolean getBooleanCapability(String capability) {
-        return bools.contains(capability);
-    }
-
-    public Integer getNumericCapability(String capability) {
-        return null;
-    }
-
-    public String getStringCapability(String capability) {
-        return strings.get(capability);
-    }
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-// Based on Apache Karaf impl
-
-/**
- * Non-interruptible (via CTRL-C) {@link UnixTerminal}.
- *
- * @since 2.0
- */
-public class NoInterruptUnixTerminal
-    extends UnixTerminal
-{
-    private String intr;
-
-    public NoInterruptUnixTerminal() throws Exception {
-        super();
-    }
-
-    @Override
-    public void init() throws Exception {
-        super.init();
-        intr = getSettings().getPropertyAsString("intr");
-        if ("<undef>".equals(intr)) {
-            intr = null;
-        }
-        if (intr != null) {
-            getSettings().undef("intr");
-        }
-    }
-
-    @Override
-    public void restore() throws Exception {
-        if (intr != null) {
-            getSettings().set("intr", intr);
-        }
-        super.restore();
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/OSvTerminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import jdk.internal.jline.internal.Log;
-
-/**
- * Terminal that is used for OSv. This is seperate to unix terminal
- * implementation because exec cannot be used as currently used by UnixTerminal.
- *
- * This implimentation is derrived from the implementation at
- * https://github.com/cloudius-systems/mgmt/blob/master/crash/src/main/java/com/cloudius/cli/OSvTerminal.java
- * authored by Or Cohen.
- *
- * @author <a href-"mailto:orc@fewbytes.com">Or Cohen</a>
- * @author <a href="mailto:arun.neelicattu@gmail.com">Arun Neelicattu</a>
- * @since 2.13
- */
-public class OSvTerminal
-    extends TerminalSupport
-{
-
-    public Class<?> sttyClass = null;
-    public Object stty = null;
-
-    @SuppressWarnings("deprecation")
-    public OSvTerminal() {
-        super(true);
-
-        setAnsiSupported(true);
-
-        try {
-            if (stty == null) {
-                sttyClass = Class.forName("com.cloudius.util.Stty");
-                stty = sttyClass.newInstance();
-            }
-        } catch (Exception e) {
-            Log.warn("Failed to load com.cloudius.util.Stty", e);
-        }
-    }
-
-    @Override
-    public void init() throws Exception {
-        super.init();
-
-        if (stty != null) {
-            sttyClass.getMethod("jlineMode").invoke(stty);
-        }
-    }
-
-    @Override
-    public void restore() throws Exception {
-        if (stty != null) {
-            sttyClass.getMethod("reset").invoke(stty);
-        }
-        super.restore();
-
-        // Newline in end of restore like in jline.UnixTerminal
-        System.out.println();
-    }
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Representation of the input terminal for a platform.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public interface Terminal
-{
-    void init() throws Exception;
-
-    void restore() throws Exception;
-
-    void reset() throws Exception;
-
-    boolean isSupported();
-
-    int getWidth();
-
-    int getHeight();
-
-    boolean isAnsiSupported();
-
-    /**
-     * When ANSI is not natively handled, the output will have to be wrapped.
-     */
-    OutputStream wrapOutIfNeeded(OutputStream out);
-
-    /**
-     * When using native support, return the InputStream to use for reading characters
-     * else return the input stream passed as a parameter.
-     *
-     * @since 2.6
-     */
-    InputStream wrapInIfNeeded(InputStream in) throws IOException;
-
-    /**
-     * For terminals that don't wrap when character is written in last column,
-     * only when the next character is written.
-     * These are the ones that have 'am' and 'xn' termcap attributes (xterm and
-     * rxvt flavors falls under that category)
-     */
-    boolean hasWeirdWrap();
-
-    boolean isEchoEnabled();
-
-    void setEchoEnabled(boolean enabled);
-
-    void disableInterruptCharacter();
-    void enableInterruptCharacter();
-
-    String getOutputEncoding();
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal2.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-/**
- * Terminal extension.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.13
- */
-public interface Terminal2 extends Terminal
-{
-    boolean getBooleanCapability(String capability);
-
-    Integer getNumericCapability(String capability);
-
-    String getStringCapability(String capability);
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Log;
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Creates terminal instances.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class TerminalFactory
-{
-    public static final String JLINE_TERMINAL = "jline.terminal";
-
-    public static final String AUTO = "auto";
-
-    public static final String UNIX = "unix";
-
-    public static final String OSV = "osv";
-
-    public static final String WIN = "win";
-
-    public static final String WINDOWS = "windows";
-
-    public static final String FREEBSD = "freebsd";
-
-    public static final String NONE = "none";
-
-    public static final String OFF = "off";
-
-    public static final String FALSE = "false";
-
-    private static Terminal term = null;
-
-    public static synchronized Terminal create() {
-        return create(null);
-    }
-
-    public static synchronized Terminal create(String ttyDevice) {
-        if (Log.TRACE) {
-            //noinspection ThrowableInstanceNeverThrown
-            Log.trace(new Throwable("CREATE MARKER"));
-        }
-
-        String defaultType = "dumb".equals(System.getenv("TERM")) ? NONE : AUTO;
-        String type  = Configuration.getString(JLINE_TERMINAL, defaultType);
-
-        Log.debug("Creating terminal; type=", type);
-
-        Terminal t;
-        try {
-            String tmp = type.toLowerCase();
-
-            if (tmp.equals(UNIX)) {
-                t = getFlavor(Flavor.UNIX);
-            }
-            else if (tmp.equals(OSV)) {
-                t = getFlavor(Flavor.OSV);
-            }
-            else if (tmp.equals(WIN) || tmp.equals(WINDOWS)) {
-                t = getFlavor(Flavor.WINDOWS);
-            }
-            else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) {
-                if (System.getenv("INSIDE_EMACS") != null) {
-                    // emacs requires ansi on and echo off
-                    t = new UnsupportedTerminal(true, false);
-                } else  {
-                    // others the other way round
-                    t = new UnsupportedTerminal(false, true);
-                }
-            }
-            else {
-                if (tmp.equals(AUTO)) {
-                    String os = Configuration.getOsName();
-                    Flavor flavor = Flavor.UNIX;
-                    if (os.contains(WINDOWS)) {
-                        flavor = Flavor.WINDOWS;
-                    } else if (System.getenv("OSV_CPUS") != null) {
-                        flavor = Flavor.OSV;
-                    }
-                    t = getFlavor(flavor, ttyDevice);
-                }
-                else {
-                    try {
-                        @SuppressWarnings("deprecation")
-                        Object o = Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
-                        t = (Terminal) o;
-                    }
-                    catch (Exception e) {
-                        throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
-                    }
-                }
-            }
-        }
-        catch (Exception e) {
-            Log.error("Failed to construct terminal; falling back to unsupported", e);
-            t = new UnsupportedTerminal();
-        }
-
-        Log.debug("Created Terminal: ", t);
-
-        try {
-            t.init();
-        }
-        catch (Throwable e) {
-            Log.error("Terminal initialization failed; falling back to unsupported", e);
-            return new UnsupportedTerminal();
-        }
-
-        return t;
-    }
-
-    public static synchronized void reset() {
-        term = null;
-    }
-
-    public static synchronized void resetIf(final Terminal t) {
-        if(t == term) {
-            reset();
-        }
-    }
-
-    public static enum Type
-    {
-        AUTO,
-        WINDOWS,
-        UNIX,
-        OSV,
-        NONE
-    }
-
-    public static synchronized void configure(final String type) {
-        checkNotNull(type);
-        System.setProperty(JLINE_TERMINAL, type);
-    }
-
-    public static synchronized void configure(final Type type) {
-        checkNotNull(type);
-        configure(type.name().toLowerCase());
-    }
-
-    //
-    // Flavor Support
-    //
-
-    public static enum Flavor
-    {
-        WINDOWS,
-        UNIX,
-        OSV
-    }
-
-    private static final Map<Flavor, TerminalConstructor> FLAVORS = new HashMap<>();
-
-    static {
-        registerFlavor(Flavor.WINDOWS, ttyDevice -> new WindowsTerminal());
-        registerFlavor(Flavor.UNIX, ttyDevice -> new UnixTerminal(ttyDevice));
-        registerFlavor(Flavor.OSV, ttyDevice -> new OSvTerminal());
-    }
-
-    public static synchronized Terminal get(String ttyDevice) {
-        // The code is assuming we've got only one terminal per process.
-        // Continuing this assumption, if this terminal is already initialized,
-        // we don't check if it's using the same tty line either. Both assumptions
-        // are a bit crude. TODO: check single terminal assumption.
-        if (term == null) {
-            term = create(ttyDevice);
-        }
-        return term;
-    }
-
-    public static synchronized Terminal get() {
-        return get(null);
-    }
-
-    public static Terminal getFlavor(final Flavor flavor) throws Exception {
-        return getFlavor(flavor, null);
-    }
-
-    @SuppressWarnings("deprecation")
-    public static Terminal getFlavor(final Flavor flavor, String ttyDevice) throws Exception {
-        TerminalConstructor factory = FLAVORS.get(flavor);
-        if (factory != null) {
-            return factory.createTerminal(ttyDevice);
-        } else {
-            throw new InternalError();
-        }
-    }
-
-    public static void registerFlavor(final Flavor flavor, final TerminalConstructor factory) {
-        FLAVORS.put(flavor, factory);
-    }
-
-    public interface TerminalConstructor {
-        public Terminal createTerminal(String str) throws Exception;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.ShutdownHooks;
-import jdk.internal.jline.internal.ShutdownHooks.Task;
-
-/**
- * Provides support for {@link Terminal} instances.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public abstract class TerminalSupport
-    implements Terminal
-{
-    public static final int DEFAULT_WIDTH = 80;
-
-    public static final int DEFAULT_HEIGHT = 24;
-
-    private Task shutdownTask;
-
-    private boolean supported;
-
-    private boolean echoEnabled;
-
-    private boolean ansiSupported;
-
-    protected TerminalSupport(final boolean supported) {
-        this.supported = supported;
-    }
-
-    public void init() throws Exception {
-        if (shutdownTask != null) {
-            ShutdownHooks.remove(shutdownTask);
-        }
-        // Register a task to restore the terminal on shutdown
-        this.shutdownTask = ShutdownHooks.add(new Task()
-        {
-            public void run() throws Exception {
-                restore();
-            }
-        });
-    }
-
-    public void restore() throws Exception {
-        TerminalFactory.resetIf(this);
-        if (shutdownTask != null) {
-          ShutdownHooks.remove(shutdownTask);
-          shutdownTask = null;
-        }
-    }
-
-    public void reset() throws Exception {
-        restore();
-        init();
-    }
-
-    public final boolean isSupported() {
-        return supported;
-    }
-
-    public synchronized boolean isAnsiSupported() {
-        return ansiSupported;
-    }
-
-    protected synchronized void setAnsiSupported(final boolean supported) {
-        this.ansiSupported = supported;
-        Log.debug("Ansi supported: ", supported);
-    }
-
-    /**
-     * Subclass to change behavior if needed.
-     * @return the passed out
-     */
-    public OutputStream wrapOutIfNeeded(OutputStream out) {
-        return out;
-    }
-
-    /**
-     * Defaults to true which was the behaviour before this method was added.
-     */
-    public boolean hasWeirdWrap() {
-        return true;
-    }
-
-    public int getWidth() {
-        return DEFAULT_WIDTH;
-    }
-
-    public int getHeight() {
-        return DEFAULT_HEIGHT;
-    }
-
-    public synchronized boolean isEchoEnabled() {
-        return echoEnabled;
-    }
-
-    public synchronized void setEchoEnabled(final boolean enabled) {
-        this.echoEnabled = enabled;
-        Log.debug("Echo enabled: ", enabled);
-    }
-
-    public void disableInterruptCharacter() {
-    }
-
-    public void enableInterruptCharacter() {
-    }
-
-    public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-        return in;
-    }
-
-    public String getOutputEncoding() {
-        // null for unknown
-        return null;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.InfoCmp;
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.TerminalLineSettings;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Terminal that is used for unix platforms. Terminal initialization
- * is handled by issuing the <em>stty</em> command against the
- * <em>/dev/tty</em> file to disable character echoing and enable
- * character input. All known unix systems (including
- * Linux and Macintosh OS X) support the <em>stty</em>), so this
- * implementation should work for an reasonable POSIX system.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:dwkemp@gmail.com">Dale Kemp</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:jbonofre@apache.org">Jean-Baptiste Onofr\u00E9</a>
- * @since 2.0
- */
-public class UnixTerminal
-    extends TerminalSupport
-    implements Terminal2
-{
-    private final TerminalLineSettings settings;
-    private final String type;
-    private String intr;
-    private String lnext;
-    private Set<String> bools = new HashSet<String>();
-    private Map<String, Integer> ints = new HashMap<String, Integer>();
-    private Map<String, String> strings = new HashMap<String, String>();
-
-    public UnixTerminal() throws Exception {
-        this(TerminalLineSettings.DEFAULT_TTY, null);
-    }
-
-    public UnixTerminal(String ttyDevice) throws Exception {
-        this(ttyDevice, null);
-    }
-
-    public UnixTerminal(String ttyDevice, String type) throws Exception {
-        super(true);
-        checkNotNull(ttyDevice);
-        this.settings = TerminalLineSettings.getSettings(ttyDevice);
-        if (type == null) {
-            type = System.getenv("TERM");
-        }
-        this.type = type;
-        parseInfoCmp();
-    }
-
-    public TerminalLineSettings getSettings() {
-        return settings;
-    }
-
-    /**
-     * Remove line-buffered input by invoking "stty -icanon min 1"
-     * against the current terminal.
-     */
-    @Override
-    public void init() throws Exception {
-        super.init();
-
-        setAnsiSupported(true);
-
-        // Set the console to be character-buffered instead of line-buffered.
-        // Make sure we're distinguishing carriage return from newline.
-        // Allow ctrl-s keypress to be used (as forward search)
-        //
-        // Please note that FreeBSD does not seem to support -icrnl and thus
-        // has to be handled separately. Otherwise the console will be "stuck"
-        // and will neither accept input nor print anything to stdout.
-        if (Configuration.getOsName().contains(TerminalFactory.FREEBSD)) {
-            settings.set("-icanon min 1 -inlcr -ixon");
-        } else {
-            settings.set("-icanon min 1 -icrnl -inlcr -ixon");
-        }
-        settings.undef("dsusp");
-
-        setEchoEnabled(false);
-
-        parseInfoCmp();
-    }
-
-    /**
-     * Restore the original terminal configuration, which can be used when
-     * shutting down the console reader. The ConsoleReader cannot be
-     * used after calling this method.
-     */
-    @Override
-    public void restore() throws Exception {
-        settings.restore();
-        super.restore();
-    }
-
-    /**
-     * Returns the value of <tt>stty columns</tt> param.
-     */
-    @Override
-    public int getWidth() {
-        int w = settings.getProperty("columns");
-        return w < 1 ? DEFAULT_WIDTH : w;
-    }
-
-    /**
-     * Returns the value of <tt>stty rows>/tt> param.
-     */
-    @Override
-    public int getHeight() {
-        int h = settings.getProperty("rows");
-        return h < 1 ? DEFAULT_HEIGHT : h;
-    }
-
-    @Override
-    public boolean hasWeirdWrap() {
-        return getBooleanCapability("auto_right_margin")
-                && getBooleanCapability("eat_newline_glitch");
-    }
-
-    @Override
-    public synchronized void setEchoEnabled(final boolean enabled) {
-        try {
-            if (enabled) {
-                settings.set("echo");
-            }
-            else {
-                settings.set("-echo");
-            }
-            super.setEchoEnabled(enabled);
-        }
-        catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.error("Failed to ", enabled ? "enable" : "disable", " echo", e);
-        }
-    }
-
-    public void disableInterruptCharacter()
-    {
-        try {
-            intr = getSettings().getPropertyAsString("intr");
-            if ("<undef>".equals(intr)) {
-                intr = null;
-            }
-            settings.undef("intr");
-        }
-        catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.error("Failed to disable interrupt character", e);
-        }
-    }
-
-    public void enableInterruptCharacter()
-    {
-        try {
-            if (intr != null) {
-                settings.set("intr", intr);
-            }
-        }
-        catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.error("Failed to enable interrupt character", e);
-        }
-    }
-
-    public void disableLitteralNextCharacter()
-    {
-        try {
-            lnext = getSettings().getPropertyAsString("lnext");
-            if ("<undef>".equals(lnext)) {
-                lnext = null;
-            }
-            settings.undef("lnext");
-        }
-        catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.error("Failed to disable litteral next character", e);
-        }
-    }
-
-    public void enableLitteralNextCharacter()
-    {
-        try {
-            if (lnext != null) {
-                settings.set("lnext", lnext);
-            }
-        }
-        catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.error("Failed to enable litteral next character", e);
-        }
-    }
-
-    public boolean getBooleanCapability(String capability) {
-        return bools.contains(capability);
-    }
-
-    public Integer getNumericCapability(String capability) {
-        return ints.get(capability);
-    }
-
-    public String getStringCapability(String capability) {
-        return strings.get(capability);
-    }
-
-    private void parseInfoCmp() {
-        String capabilities = null;
-        if (type != null) {
-            try {
-                capabilities = InfoCmp.getInfoCmp(type);
-            } catch (Exception e) {
-            }
-        }
-        if (capabilities == null) {
-            capabilities = InfoCmp.getAnsiCaps();
-        }
-        InfoCmp.parseInfoCmp(capabilities, bools, ints, strings);
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-/**
- * An unsupported terminal.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class UnsupportedTerminal
-    extends TerminalSupport
-{
-    public UnsupportedTerminal() {
-        this(false, true);
-    }
-
-    public UnsupportedTerminal(boolean ansiSupported, boolean echoEnabled) {
-        super(false);
-        setAnsiSupported(ansiSupported);
-        setEchoEnabled(echoEnabled);
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.BufferState;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.Performer;
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Log;
-//import org.fusesource.jansi.internal.WindowsSupport;
-//import org.fusesource.jansi.internal.Kernel32;
-//import static org.fusesource.jansi.internal.Kernel32.*;
-
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
-import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
-
-/**
- * Terminal implementation for Microsoft Windows. Terminal initialization in
- * {@link #init} is accomplished by extracting the
- * <em>jline_<i>version</i>.dll</em>, saving it to the system temporary
- * directoy (determined by the setting of the <em>java.io.tmpdir</em> System
- * property), loading the library, and then calling the Win32 APIs <a
- * href="http://msdn.microsoft.com/library/default.asp?
- * url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a> and
- * <a href="http://msdn.microsoft.com/library/default.asp?
- * url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a> to
- * disable character echoing.
- * <p/>
- * <p>
- * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
- * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
- * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
- * directly invoke the readc() method in the JNI library. This is so the class
- * can read special keys (like arrow keys) which are otherwise inaccessible via
- * the {@link System#in} stream. Using JNI reading can be bypassed by setting
- * the <code>jline.WindowsTerminal.directConsole</code> system property
- * to <code>false</code>.
- * </p>
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class WindowsTerminal
-    extends TerminalSupport
-{
-    public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
-
-    public static final String ANSI = WindowsTerminal.class.getName() + ".ansi";
-
-    private boolean directConsole;
-
-    private int originalMode;
-
-    public WindowsTerminal() throws Exception {
-        super(true);
-    }
-
-    @Override
-    public void init() throws Exception {
-        super.init();
-
-//        setAnsiSupported(Configuration.getBoolean(ANSI, true));
-        setAnsiSupported(true);
-
-        //
-        // FIXME: Need a way to disable direct console and sysin detection muck
-        //
-
-        setDirectConsole(Configuration.getBoolean(DIRECT_CONSOLE, true));
-
-        this.originalMode = getConsoleMode();
-        setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code);
-        setEchoEnabled(false);
-    }
-
-    /**
-     * Restore the original terminal configuration, which can be used when
-     * shutting down the console reader. The ConsoleReader cannot be
-     * used after calling this method.
-     */
-    @Override
-    public void restore() throws Exception {
-        // restore the old console mode
-        setConsoleMode(originalMode);
-        super.restore();
-    }
-
-    @Override
-    public int getWidth() {
-        int w = getWindowsTerminalWidth();
-        return w < 1 ? DEFAULT_WIDTH : w;
-    }
-
-    @Override
-    public int getHeight() {
-        int h = getWindowsTerminalHeight();
-        return h < 1 ? DEFAULT_HEIGHT : h;
-    }
-
-    @Override
-    public void setEchoEnabled(final boolean enabled) {
-        // Must set these four modes at the same time to make it work fine.
-        if (enabled) {
-            setConsoleMode(getConsoleMode() |
-                ENABLE_ECHO_INPUT.code |
-                ENABLE_LINE_INPUT.code |
-                ENABLE_WINDOW_INPUT.code);
-        }
-        else {
-            setConsoleMode(getConsoleMode() &
-                ~(ENABLE_LINE_INPUT.code |
-                    ENABLE_ECHO_INPUT.code |
-                    ENABLE_WINDOW_INPUT.code));
-        }
-        super.setEchoEnabled(enabled);
-    }
-
-    public void disableInterruptCharacter() {
-        setConsoleMode(getConsoleMode() &
-            ~(ENABLE_PROCESSED_INPUT.code));
-    }
-
-    public void enableInterruptCharacter() {
-        setConsoleMode(getConsoleMode() |
-            ENABLE_PROCESSED_INPUT.code);
-    }
-
-    /**
-     * Whether or not to allow the use of the JNI console interaction.
-     */
-    public void setDirectConsole(final boolean flag) {
-        this.directConsole = flag;
-        Log.debug("Direct console: ", flag);
-    }
-
-    /**
-     * Whether or not to allow the use of the JNI console interaction.
-     */
-    public Boolean getDirectConsole() {
-        return directConsole;
-    }
-
-
-    @Override
-    public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-        if (directConsole && isSystemIn(in)) {
-            return new InputStream() {
-                private byte[] buf = null;
-                int bufIdx = 0;
-
-                @Override
-                public int read() throws IOException {
-                    while (buf == null || bufIdx == buf.length) {
-                        buf = readConsoleInput();
-                        bufIdx = 0;
-                    }
-                    int c = buf[bufIdx] & 0xFF;
-                    bufIdx++;
-                    return c;
-                }
-            };
-        } else {
-            return super.wrapInIfNeeded(in);
-        }
-    }
-
-    protected boolean isSystemIn(final InputStream in) throws IOException {
-        if (in == null) {
-            return false;
-        }
-        else if (in == System.in) {
-            return true;
-        }
-        else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public OutputStream wrapOutIfNeeded(OutputStream out) {
-        return new AnsiInterpretingOutputStream(getOutputEncoding(), out, new Performer() {
-            @Override
-            public BufferState getBufferState() throws IOException {
-                out.flush();
-                return WindowsTerminal.this.getBufferState();
-            }
-            @Override
-            public void setCursorPosition(int cursorX, int cursorY) throws IOException {
-                out.flush();
-                WindowsTerminal.this.setCursorPosition(cursorX, cursorY);
-            }
-        });
-    }
-
-    @Override
-    public String getOutputEncoding() {
-        int codepage = getConsoleOutputCodepage();
-        //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
-        String charsetMS = "ms" + codepage;
-        if (java.nio.charset.Charset.isSupported(charsetMS)) {
-            return charsetMS;
-        }
-        String charsetCP = "cp" + codepage;
-        if (java.nio.charset.Charset.isSupported(charsetCP)) {
-            return charsetCP;
-        }
-        Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")...");
-        return super.getOutputEncoding();
-    }
-
-    //
-    // Original code:
-    //
-//    private int getConsoleMode() {
-//        return WindowsSupport.getConsoleMode();
-//    }
-//
-//    private void setConsoleMode(int mode) {
-//        WindowsSupport.setConsoleMode(mode);
-//    }
-//
-//    private byte[] readConsoleInput() {
-//        // XXX does how many events to read in one call matter?
-//        INPUT_RECORD[] events = null;
-//        try {
-//            events = WindowsSupport.readConsoleInput(1);
-//        } catch (IOException e) {
-//            Log.debug("read Windows console input error: ", e);
-//        }
-//        if (events == null) {
-//            return new byte[0];
-//        }
-//        StringBuilder sb = new StringBuilder();
-//        for (int i = 0; i < events.length; i++ ) {
-//            KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
-//            //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
-//            if (keyEvent.keyDown) {
-//                if (keyEvent.uchar > 0) {
-//                    // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
-//                    // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
-//                    final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
-//                    // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
-//                    // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
-//                    final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
-//                    if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
-//                        && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
-//                        sb.append('\u001B'); // ESC
-//                    }
-//
-//                    sb.append(keyEvent.uchar);
-//                    continue;
-//                }
-//                // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
-//                // just add support for basic editing keys (no control state, no numpad keys)
-//                String escapeSequence = null;
-//                switch (keyEvent.keyCode) {
-//                case 0x21: // VK_PRIOR PageUp
-//                    escapeSequence = "\u001B[5~";
-//                    break;
-//                case 0x22: // VK_NEXT PageDown
-//                    escapeSequence = "\u001B[6~";
-//                    break;
-//                case 0x23: // VK_END
-//                    escapeSequence = "\u001B[4~";
-//                    break;
-//                case 0x24: // VK_HOME
-//                    escapeSequence = "\u001B[1~";
-//                    break;
-//                case 0x25: // VK_LEFT
-//                    escapeSequence = "\u001B[D";
-//                    break;
-//                case 0x26: // VK_UP
-//                    escapeSequence = "\u001B[A";
-//                    break;
-//                case 0x27: // VK_RIGHT
-//                    escapeSequence = "\u001B[C";
-//                    break;
-//                case 0x28: // VK_DOWN
-//                    escapeSequence = "\u001B[B";
-//                    break;
-//                case 0x2D: // VK_INSERT
-//                    escapeSequence = "\u001B[2~";
-//                    break;
-//                case 0x2E: // VK_DELETE
-//                    escapeSequence = "\u001B[3~";
-//                    break;
-//                default:
-//                    break;
-//                }
-//                if (escapeSequence != null) {
-//                    for (int k = 0; k < keyEvent.repeatCount; k++) {
-//                        sb.append(escapeSequence);
-//                    }
-//                }
-//            } else {
-//                // key up event
-//                // support ALT+NumPad input method
-//                if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
-//                    sb.append(keyEvent.uchar);
-//                }
-//            }
-//        }
-//        return sb.toString().getBytes();
-//    }
-//
-//    private int getConsoleOutputCodepage() {
-//        return Kernel32.GetConsoleOutputCP();
-//    }
-//
-//    private int getWindowsTerminalWidth() {
-//        return WindowsSupport.getWindowsTerminalWidth();
-//    }
-//
-//    private int getWindowsTerminalHeight() {
-//        return WindowsSupport.getWindowsTerminalHeight();
-//    }
-
-    //
-    // Native Bits
-    //
-    static {
-        System.loadLibrary("le");
-        initIDs();
-    }
-
-    private static native void initIDs();
-
-    protected native int getConsoleMode();
-
-    protected native void setConsoleMode(int mode);
-
-    private byte[] readConsoleInput() {
-        KEY_EVENT_RECORD keyEvent = readKeyEvent();
-
-        return convertKeys(keyEvent).getBytes();
-    }
-
-    public static String convertKeys(KEY_EVENT_RECORD keyEvent) {
-        if (keyEvent == null) {
-            return "";
-        }
-
-        StringBuilder sb = new StringBuilder();
-
-        if (keyEvent.keyDown) {
-            if (keyEvent.uchar > 0) {
-                // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
-                // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
-                final int altState = KEY_EVENT_RECORD.ALT_PRESSED;
-                // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
-                // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
-                final int ctrlState = KEY_EVENT_RECORD.CTRL_PRESSED;
-
-                boolean handled = false;
-
-                if ((keyEvent.controlKeyState & ctrlState) != 0) {
-                    switch (keyEvent.keyCode) {
-                        case 0x43: //Ctrl-C
-                            sb.append("\003");
-                            handled = true;
-                            break;
-                    }
-                }
-
-                if ((keyEvent.controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
-                    switch (keyEvent.keyCode) {
-                        case 0x09: //Shift-Tab
-                            sb.append("\033\133\132");
-                            handled = true;
-                            break;
-                    }
-                }
-
-                if (!handled) {
-                    if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
-                        && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
-                        sb.append('\u001B'); // ESC
-                    }
-
-                    sb.append(keyEvent.uchar);
-                }
-            } else {
-                // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
-                // xterm escape codes: E. Moy, S. Gildea and T. Dickey, "XTerm Control Sequences":
-                // http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
-                // http://xorg.freedesktop.org/releases/X11R6.8.1/PDF/ctlseqs.pdf
-                // just add support for basic editing keys and function keys
-                String escapeSequence = null;
-                switch (keyEvent.keyCode) {
-                case 0x21: // VK_PRIOR PageUp
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~");
-                    break;
-                case 0x22: // VK_NEXT PageDown
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~");
-                    break;
-                case 0x23: // VK_END
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~");
-                    break;
-                case 0x24: // VK_HOME
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~");
-                    break;
-                case 0x25: // VK_LEFT
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD");
-                    break;
-                case 0x26: // VK_UP
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA");
-                    break;
-                case 0x27: // VK_RIGHT
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC");
-                    break;
-                case 0x28: // VK_DOWN
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB");
-                    break;
-                case 0x2D: // VK_INSERT
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~");
-                    break;
-                case 0x2E: // VK_DELETE
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[3~", "\u001B[3;%d~");
-                    break;
-                case 0x70: // VK_F1
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOP", "\u001BO%dP");
-                    break;
-                case 0x71: // VK_F2
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOQ", "\u001BO%dQ");
-                    break;
-                case 0x72: // VK_F3
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOR", "\u001BO%dR");
-                    break;
-                case 0x73: // VK_F4
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOS", "\u001BO%dS");
-                    break;
-                case 0x74: // VK_F5
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[15~", "\u001B[15;%d~");
-                    break;
-                case 0x75: // VK_F6
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[17~", "\u001B[17;%d~");
-                    break;
-                case 0x76: // VK_F7
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[18~", "\u001B[18;%d~");
-                    break;
-                case 0x77: // VK_F8
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[19~", "\u001B[19;%d~");
-                    break;
-                case 0x78: // VK_F9
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[20~", "\u001B[20;%d~");
-                    break;
-                case 0x79: // VK_F10
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[21~", "\u001B[21;%d~");
-                    break;
-                case 0x7A: // VK_F11
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[23~", "\u001B[23;%d~");
-                    break;
-                case 0x7B: // VK_F12
-                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[24~", "\u001B[24;%d~");
-                    break;
-                default:
-                    break;
-                }
-                if (escapeSequence != null) {
-                    for (int k = 0; k < keyEvent.repeatCount; k++) {
-                        sb.append(escapeSequence);
-                    }
-                }
-            }
-        } else {
-            // key up event
-            // support ALT+NumPad input method
-            if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
-                sb.append(keyEvent.uchar);
-            }
-        }
-        return sb.toString();
-    }
-
-    private static String escapeSequence(int controlKeyState, String noControlSequence, String withControlSequence) {
-        int controlNum = 1;
-
-        if ((controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
-            controlNum += 1;
-        }
-
-        if ((controlKeyState & KEY_EVENT_RECORD.ALT_PRESSED) != 0) {
-            controlNum += 2;
-        }
-
-        if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) {
-            controlNum += 4;
-        }
-
-        if (controlNum > 1) {
-            return String.format(withControlSequence, controlNum);
-        } else {
-            return noControlSequence;
-        }
-    }
-
-    private native KEY_EVENT_RECORD readKeyEvent();
-
-    public static class KEY_EVENT_RECORD {
-        public final static int ALT_PRESSED = 0x3;
-        public final static int CTRL_PRESSED = 0xC;
-        public final static int SHIFT_PRESSED = 0x10;
-        public final boolean keyDown;
-        public final char uchar;
-        public final int controlKeyState;
-        public final int keyCode;
-        public final int repeatCount;
-
-        public KEY_EVENT_RECORD(boolean keyDown, char uchar, int controlKeyState, int keyCode, int repeatCount) {
-            this.keyDown = keyDown;
-            this.uchar = uchar;
-            this.controlKeyState = controlKeyState;
-            this.keyCode = keyCode;
-            this.repeatCount = repeatCount;
-        }
-
-    }
-
-    private native int getConsoleOutputCodepage();
-
-    private native int getWindowsTerminalWidth();
-
-    private native int getWindowsTerminalHeight();
-
-    private native BufferState getBufferState();
-
-    private native void setCursorPosition(int x, int y);
-
-    /**
-     * Console mode
-     * <p/>
-     * Constants copied <tt>wincon.h</tt>.
-     */
-    public static enum ConsoleMode
-    {
-        /**
-         * The ReadFile or ReadConsole function returns only when a carriage return
-         * character is read. If this mode is disable, the functions return when one
-         * or more characters are available.
-         */
-        ENABLE_LINE_INPUT(2),
-
-        /**
-         * Characters read by the ReadFile or ReadConsole function are written to
-         * the active screen buffer as they are read. This mode can be used only if
-         * the ENABLE_LINE_INPUT mode is also enabled.
-         */
-        ENABLE_ECHO_INPUT(4),
-
-        /**
-         * CTRL+C is processed by the system and is not placed in the input buffer.
-         * If the input buffer is being read by ReadFile or ReadConsole, other
-         * control keys are processed by the system and are not returned in the
-         * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
-         * enabled, backspace, carriage return, and linefeed characters are handled
-         * by the system.
-         */
-        ENABLE_PROCESSED_INPUT(1),
-
-        /**
-         * User interactions that change the size of the console screen buffer are
-         * reported in the console's input buffee. Information about these events
-         * can be read from the input buffer by applications using
-         * theReadConsoleInput function, but not by those using ReadFile
-         * orReadConsole.
-         */
-        ENABLE_WINDOW_INPUT(8),
-
-        /**
-         * If the mouse pointer is within the borders of the console window and the
-         * window has the keyboard focus, mouse events generated by mouse movement
-         * and button presses are placed in the input buffer. These events are
-         * discarded by ReadFile or ReadConsole, even when this mode is enabled.
-         */
-        ENABLE_MOUSE_INPUT(16),
-
-        /**
-         * When enabled, text entered in a console window will be inserted at the
-         * current cursor location and all text following that location will not be
-         * overwritten. When disabled, all following text will be overwritten. An OR
-         * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
-         * flag to enable this functionality.
-         */
-        ENABLE_PROCESSED_OUTPUT(1),
-
-        /**
-         * This flag enables the user to use the mouse to select and edit text. To
-         * enable this option, use the OR to combine this flag with
-         * ENABLE_EXTENDED_FLAGS.
-         */
-        ENABLE_WRAP_AT_EOL_OUTPUT(2),;
-
-        public final int code;
-
-        ConsoleMode(final int code) {
-            this.code = code;
-        }
-    }
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,387 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import jdk.internal.jline.internal.Log;
-
-/**
- * @author St\u00E5le W. Pedersen <stale.pedersen@jboss.org>
- */
-public class ConsoleKeys {
-
-    private KeyMap keys;
-
-    private Map<String, KeyMap> keyMaps;
-    private Map<String, String> variables = new HashMap<String,String>();
-
-    public ConsoleKeys(String appName, URL inputrcUrl) {
-        keyMaps = KeyMap.keyMaps();
-        setVar("editing-mode", "emacs");
-        loadKeys(appName, inputrcUrl);
-        String editingMode = variables.get("editing-mode");
-        if ("vi".equalsIgnoreCase(editingMode)) {
-            keys = keyMaps.get(KeyMap.VI_INSERT);
-        } else if ("emacs".equalsIgnoreCase(editingMode)) {
-            keys = keyMaps.get(KeyMap.EMACS);
-        }
-    }
-
-    protected boolean setKeyMap (String name) {
-        KeyMap map = keyMaps.get(name);
-        if (map == null) {
-            return false;
-        }
-        this.keys = map;
-        return true;
-    }
-
-    protected Map<String, KeyMap> getKeyMaps() {
-        return keyMaps;
-    }
-
-    protected KeyMap getKeys() {
-        return keys;
-    }
-
-    protected void setKeys(KeyMap keys) {
-        this.keys = keys;
-    }
-
-    protected void loadKeys(String appName, URL inputrcUrl) {
-        keys = keyMaps.get(KeyMap.EMACS);
-
-        try {
-            InputStream input = inputrcUrl.openStream();
-            try {
-                loadKeys(input, appName);
-                Log.debug("Loaded user configuration: ", inputrcUrl);
-            }
-            finally {
-                try {
-                    input.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        catch (IOException e) {
-            if (inputrcUrl.getProtocol().equals("file")) {
-                File file = new File(inputrcUrl.getPath());
-                if (file.exists()) {
-                    Log.warn("Unable to read user configuration: ", inputrcUrl, e);
-                }
-            } else {
-                Log.warn("Unable to read user configuration: ", inputrcUrl, e);
-            }
-        }
-    }
-
-    private void loadKeys(InputStream input, String appName) throws IOException {
-        BufferedReader reader = new BufferedReader( new java.io.InputStreamReader( input ) );
-        String line;
-        boolean parsing = true;
-        List<Boolean> ifsStack = new ArrayList<Boolean>();
-        while ( (line = reader.readLine()) != null ) {
-            try {
-                line = line.trim();
-                if (line.length() == 0) {
-                    continue;
-                }
-                if (line.charAt(0) == '#') {
-                    continue;
-                }
-                int i = 0;
-                if (line.charAt(i) == '$') {
-                    String cmd;
-                    String args;
-                    for (++i; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
-                    int s = i;
-                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
-                    cmd = line.substring(s, i);
-                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
-                    s = i;
-                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
-                    args = line.substring(s, i);
-                    if ("if".equalsIgnoreCase(cmd)) {
-                        ifsStack.add( parsing );
-                        if (!parsing) {
-                            continue;
-                        }
-                        if (args.startsWith("term=")) {
-                            // TODO
-                        } else if (args.startsWith("mode=")) {
-                            String mode = variables.get("editing-mode");
-                            parsing = args.substring("mode=".length()).equalsIgnoreCase(mode);
-                        } else {
-                            parsing = args.equalsIgnoreCase(appName);
-                        }
-                    } else if ("else".equalsIgnoreCase(cmd)) {
-                        if (ifsStack.isEmpty()) {
-                            throw new IllegalArgumentException("$else found without matching $if");
-                        }
-                        boolean invert = true;
-                        for (boolean b : ifsStack) {
-                            if (!b) {
-                                invert = false;
-                                break;
-                            }
-                        }
-                        if (invert) {
-                            parsing = !parsing;
-                        }
-                    } else if ("endif".equalsIgnoreCase(cmd)) {
-                        if (ifsStack.isEmpty()) {
-                            throw new IllegalArgumentException("endif found without matching $if");
-                        }
-                        parsing = ifsStack.remove( ifsStack.size() - 1 );
-                    } else if ("include".equalsIgnoreCase(cmd)) {
-                        // TODO
-                    }
-                    continue;
-                }
-                if (!parsing) {
-                    continue;
-                }
-                boolean equivalency;
-                String keySeq = "";
-                if (line.charAt(i++) == '"') {
-                    boolean esc = false;
-                    for (;; i++) {
-                        if (i >= line.length()) {
-                            throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
-                        }
-                        if (esc) {
-                            esc = false;
-                        } else if (line.charAt(i) == '\\') {
-                            esc = true;
-                        } else if (line.charAt(i) == '"') {
-                            break;
-                        }
-                    }
-                }
-                for (; i < line.length() && line.charAt(i) != ':'
-                        && line.charAt(i) != ' ' && line.charAt(i) != '\t'
-                        ; i++);
-                keySeq = line.substring(0, i);
-                equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=';
-                i++;
-                if (equivalency) {
-                    i++;
-                }
-                if (keySeq.equalsIgnoreCase("set")) {
-                    String key;
-                    String val;
-                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
-                    int s = i;
-                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
-                    key = line.substring( s, i );
-                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
-                    s = i;
-                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
-                    val = line.substring( s, i );
-                    setVar( key, val );
-                } else {
-                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
-                    int start = i;
-                    if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
-                        char delim = line.charAt(i++);
-                        boolean esc = false;
-                        for (;; i++) {
-                            if (i >= line.length()) {
-                                break;
-                            }
-                            if (esc) {
-                                esc = false;
-                            } else if (line.charAt(i) == '\\') {
-                                esc = true;
-                            } else if (line.charAt(i) == delim) {
-                                break;
-                            }
-                        }
-                    }
-                    for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++);
-                    String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
-                    if (keySeq.charAt(0) == '"') {
-                        keySeq = translateQuoted(keySeq);
-                    } else {
-                        // Bind key name
-                        String keyName = keySeq.lastIndexOf('-') > 0 ? keySeq.substring( keySeq.lastIndexOf('-') + 1 ) : keySeq;
-                        char key = getKeyFromName(keyName);
-                        keyName = keySeq.toLowerCase();
-                        keySeq = "";
-                        if (keyName.contains("meta-") || keyName.contains("m-")) {
-                            keySeq += "\u001b";
-                        }
-                        if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
-                            key = (char)(Character.toUpperCase( key ) & 0x1f);
-                        }
-                        keySeq += key;
-                    }
-                    if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
-                        keys.bind( keySeq, translateQuoted(val) );
-                    } else {
-                        String operationName = val.replace('-', '_').toUpperCase();
-                        try {
-                          keys.bind(keySeq, Operation.valueOf(operationName));
-                        } catch(IllegalArgumentException e) {
-                          Log.info("Unable to bind key for unsupported operation: ", val);
-                        }
-                    }
-                }
-            } catch (IllegalArgumentException e) {
-              Log.warn("Unable to parse user configuration: ", e);
-            }
-        }
-    }
-
-    private static String translateQuoted(String keySeq) {
-        int i;
-        String str = keySeq.substring( 1, keySeq.length() - 1 );
-        keySeq = "";
-        for (i = 0; i < str.length(); i++) {
-            char c = str.charAt(i);
-            if (c == '\\') {
-                boolean ctrl = str.regionMatches(i, "\\C-", 0, 3)|| str.regionMatches(i, "\\M-\\C-", 0, 6);
-                boolean meta = str.regionMatches(i, "\\M-", 0, 3)|| str.regionMatches(i, "\\C-\\M-", 0, 6);
-                i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0);
-                if (i >= str.length()) {
-                    break;
-                }
-                c = str.charAt(i);
-                if (meta) {
-                    keySeq += "\u001b";
-                }
-                if (ctrl) {
-                    c = c == '?' ? 0x7f : (char)(Character.toUpperCase( c ) & 0x1f);
-                }
-                if (!meta && !ctrl) {
-                    switch (c) {
-                        case 'a': c = 0x07; break;
-                        case 'b': c = '\b'; break;
-                        case 'd': c = 0x7f; break;
-                        case 'e': c = 0x1b; break;
-                        case 'f': c = '\f'; break;
-                        case 'n': c = '\n'; break;
-                        case 'r': c = '\r'; break;
-                        case 't': c = '\t'; break;
-                        case 'v': c = 0x0b; break;
-                        case '\\': c = '\\'; break;
-                        case '0': case '1': case '2': case '3':
-                        case '4': case '5': case '6': case '7':
-                            c = 0;
-                            for (int j = 0; j < 3; j++, i++) {
-                                if (i >= str.length()) {
-                                    break;
-                                }
-                                int k = Character.digit(str.charAt(i), 8);
-                                if (k < 0) {
-                                    break;
-                                }
-                                c = (char)(c * 8 + k);
-                            }
-                            c &= 0xFF;
-                            break;
-                        case 'x':
-                            i++;
-                            c = 0;
-                            for (int j = 0; j < 2; j++, i++) {
-                                if (i >= str.length()) {
-                                    break;
-                                }
-                                int k = Character.digit(str.charAt(i), 16);
-                                if (k < 0) {
-                                    break;
-                                }
-                                c = (char)(c * 16 + k);
-                            }
-                            c &= 0xFF;
-                            break;
-                        case 'u':
-                            i++;
-                            c = 0;
-                            for (int j = 0; j < 4; j++, i++) {
-                                if (i >= str.length()) {
-                                    break;
-                                }
-                                int k = Character.digit(str.charAt(i), 16);
-                                if (k < 0) {
-                                    break;
-                                }
-                                c = (char)(c * 16 + k);
-                            }
-                            break;
-                    }
-                }
-                keySeq += c;
-            } else {
-                keySeq += c;
-            }
-        }
-        return keySeq;
-    }
-
-    private static char getKeyFromName(String name) {
-        if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
-            return 0x7f;
-        } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
-            return '\033';
-        } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
-            return '\n';
-        } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
-            return '\r';
-        } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
-            return ' ';
-        } else if ("Tab".equalsIgnoreCase(name)) {
-            return '\t';
-        } else {
-            return name.charAt(0);
-        }
-    }
-
-    private void setVar(String key, String val) {
-        if ("keymap".equalsIgnoreCase(key)) {
-            if (keyMaps.containsKey(val)) {
-                keys = keyMaps.get(val);
-            }
-        } else if ("blink-matching-paren".equals(key)) {
-            if ("on".equalsIgnoreCase(val)) {
-              keys.setBlinkMatchingParen(true);
-            } else if ("off".equalsIgnoreCase(val)) {
-              keys.setBlinkMatchingParen(false);
-            }
-        }
-
-        /*
-         * Technically variables should be defined as a functor class
-         * so that validation on the variable value can be done at parse
-         * time. This is a stop-gap.
-         */
-        variables.put(key, val);
-    }
-
-    /**
-     * Retrieves the value of a variable that was set in the .inputrc file
-     * during processing
-     * @param var The variable name
-     * @return The variable value.
-     */
-    public String getVariable(String var) {
-        return variables.get (var);
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4086 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-//import java.awt.*;
-//import java.awt.datatransfer.Clipboard;
-//import java.awt.datatransfer.DataFlavor;
-//import java.awt.datatransfer.Transferable;
-//import java.awt.datatransfer.UnsupportedFlavorException;
-//import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.System;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.ResourceBundle;
-import java.util.Stack;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import jdk.internal.jline.DefaultTerminal2;
-import jdk.internal.jline.Terminal;
-import jdk.internal.jline.Terminal2;
-import jdk.internal.jline.TerminalFactory;
-import jdk.internal.jline.UnixTerminal;
-import jdk.internal.jline.console.completer.CandidateListCompletionHandler;
-import jdk.internal.jline.console.completer.Completer;
-import jdk.internal.jline.console.completer.CompletionHandler;
-import jdk.internal.jline.console.history.History;
-import jdk.internal.jline.console.history.MemoryHistory;
-import jdk.internal.jline.internal.Ansi;
-import jdk.internal.jline.internal.Configuration;
-import jdk.internal.jline.internal.Curses;
-import jdk.internal.jline.internal.InputStreamReader;
-import jdk.internal.jline.internal.Log;
-import jdk.internal.jline.internal.NonBlockingInputStream;
-import jdk.internal.jline.internal.Nullable;
-import jdk.internal.jline.internal.TerminalLineSettings;
-import jdk.internal.jline.internal.Urls;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A reader for console applications. It supports custom tab-completion,
- * saveable command history, and command line editing. On some platforms,
- * platform-specific commands will need to be issued before the reader will
- * function properly. See {@link jline.Terminal#init} for convenience
- * methods for issuing platform-specific setup commands.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- */
-public class ConsoleReader implements Closeable
-{
-    public static final String JLINE_NOBELL = "jline.nobell";
-
-    public static final String JLINE_ESC_TIMEOUT = "jline.esc.timeout";
-
-    public static final String JLINE_INPUTRC = "jline.inputrc";
-
-    public static final String INPUT_RC = ".inputrc";
-
-    public static final String DEFAULT_INPUT_RC = "/etc/inputrc";
-
-    public static final String JLINE_EXPAND_EVENTS = "jline.expandevents";
-
-    public static final char BACKSPACE = '\b';
-
-    public static final char RESET_LINE = '\r';
-
-    public static final char KEYBOARD_BELL = '\07';
-
-    public static final char NULL_MASK = 0;
-
-    public static final int TAB_WIDTH = 8;
-
-    private static final ResourceBundle
-        resources = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName());
-
-    private static final int ESCAPE = 27;
-    private static final int READ_EXPIRED = -2;
-
-    private final Terminal2 terminal;
-
-    private final Writer out;
-
-    private final CursorBuffer buf = new CursorBuffer();
-    private boolean cursorOk;
-
-    private String prompt;
-    private int    promptLen;
-
-    private boolean expandEvents = Configuration.getBoolean(JLINE_EXPAND_EVENTS, true);
-
-    private boolean bellEnabled = !Configuration.getBoolean(JLINE_NOBELL, true);
-
-    private boolean handleUserInterrupt = false;
-
-    private boolean handleLitteralNext = true;
-
-    private Character mask;
-
-    private Character echoCharacter;
-
-    private CursorBuffer originalBuffer = null;
-
-    private StringBuffer searchTerm = null;
-
-    private String previousSearchTerm = "";
-
-    private int searchIndex = -1;
-
-    private int parenBlinkTimeout = 500;
-
-    // Reading buffers
-    private final StringBuilder opBuffer = new StringBuilder();
-    private final Stack<Character> pushBackChar = new Stack<Character>();
-
-    /*
-     * The reader and the nonBlockingInput go hand-in-hand.  The reader wraps
-     * the nonBlockingInput, but we have to retain a handle to it so that
-     * we can shut down its blocking read thread when we go away.
-     */
-    private NonBlockingInputStream in;
-    private long                   escapeTimeout;
-    private Reader                 reader;
-
-    /**
-     * Last character searched for with a vi character search
-     */
-    private char  charSearchChar = 0;           // Character to search for
-    private char  charSearchLastInvokeChar = 0; // Most recent invocation key
-    private char  charSearchFirstInvokeChar = 0;// First character that invoked
-
-    /**
-     * The vi yank buffer
-     */
-    private String yankBuffer = "";
-
-    private KillRing killRing = new KillRing();
-
-    private String encoding;
-
-    private boolean quotedInsert;
-
-    private boolean recording;
-
-    private String macro = "";
-
-    private String appName;
-
-    private URL inputrcUrl;
-
-    private ConsoleKeys consoleKeys;
-
-    private String commentBegin = null;
-
-    private boolean skipLF = false;
-
-    /**
-     * Set to true if the reader should attempt to detect copy-n-paste. The
-     * effect of this that an attempt is made to detect if tab is quickly
-     * followed by another character, then it is assumed that the tab was
-     * a literal tab as part of a copy-and-paste operation and is inserted as
-     * such.
-     */
-    private boolean copyPasteDetection = false;
-
-    /*
-     * Current internal state of the line reader
-     */
-    private State   state = State.NORMAL;
-
-    /**
-     * Possible states in which the current readline operation may be in.
-     */
-    private static enum State {
-        /**
-         * The user is just typing away
-         */
-        NORMAL,
-        /**
-         * In the middle of a emacs seach
-         */
-        SEARCH,
-        FORWARD_SEARCH,
-        /**
-         * VI "yank-to" operation ("y" during move mode)
-         */
-        VI_YANK_TO,
-        /**
-         * VI "delete-to" operation ("d" during move mode)
-         */
-        VI_DELETE_TO,
-        /**
-         * VI "change-to" operation ("c" during move mode)
-         */
-        VI_CHANGE_TO
-    }
-
-    public ConsoleReader() throws IOException {
-        this(null, new FileInputStream(FileDescriptor.in), System.out, null);
-    }
-
-    public ConsoleReader(final InputStream in, final OutputStream out) throws IOException {
-        this(null, in, out, null);
-    }
-
-    public ConsoleReader(final InputStream in, final OutputStream out, final Terminal term) throws IOException {
-        this(null, in, out, term);
-    }
-
-    public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term) throws IOException {
-        this(appName, in, out, term, null);
-    }
-
-    public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term, final @Nullable String encoding)
-        throws IOException
-    {
-        this.appName = appName != null ? appName : "JLine";
-        this.encoding = encoding != null ? encoding : Configuration.getEncoding();
-        Terminal terminal = term != null ? term : TerminalFactory.get();
-        this.terminal = terminal instanceof Terminal2 ? (Terminal2) terminal : new DefaultTerminal2(terminal);
-        String outEncoding = terminal.getOutputEncoding() != null? terminal.getOutputEncoding() : this.encoding;
-        this.out = new OutputStreamWriter(terminal.wrapOutIfNeeded(out), outEncoding);
-        setInput( in );
-
-        this.inputrcUrl = getInputRc();
-
-        consoleKeys = new ConsoleKeys(this.appName, inputrcUrl);
-
-        if (terminal instanceof UnixTerminal
-                && TerminalLineSettings.DEFAULT_TTY.equals(((UnixTerminal) terminal).getSettings().getTtyDevice())
-                && Configuration.getBoolean("jline.sigcont", false)) {
-            setupSigCont();
-        }
-    }
-
-    private void setupSigCont() {
-        // Check that sun.misc.SignalHandler and sun.misc.Signal exists
-        try {
-            Class<?> signalClass = Class.forName("sun.misc.Signal");
-            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
-            // Implement signal handler
-            Object signalHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
-                    new Class<?>[]{signalHandlerClass}, new InvocationHandler() {
-                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                            // only method we are proxying is handle()
-                            terminal.init();
-                            try {
-                                drawLine();
-                                flush();
-                            } catch (IOException e) {
-                                e.printStackTrace();
-                            }
-                            return null;
-                        }
-                    });
-            // Register the signal handler, this code is equivalent to:
-            // Signal.handle(new Signal("CONT"), signalHandler);
-            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("CONT"), signalHandler);
-        } catch (ClassNotFoundException cnfe) {
-            // sun.misc Signal handler classes don't exist
-        } catch (Exception e) {
-            // Ignore this one too, if the above failed, the signal API is incompatible with what we're expecting
-        }
-    }
-
-    /**
-     * Retrieve the URL for the inputrc configuration file in effect. Intended
-     * use is for instantiating ConsoleKeys, to read inputrc variables.
-     */
-    public static URL getInputRc() throws IOException {
-        String path = Configuration.getString(JLINE_INPUTRC);
-        if (path == null) {
-            File f = new File(Configuration.getUserHome(), INPUT_RC);
-            if (!f.exists()) {
-                f = new File(DEFAULT_INPUT_RC);
-            }
-            return f.toURI().toURL();
-        } else {
-            return Urls.create(path);
-        }
-    }
-
-    public KeyMap getKeys() {
-        return consoleKeys.getKeys();
-    }
-
-    void setInput(final InputStream in) throws IOException {
-        this.escapeTimeout = Configuration.getLong(JLINE_ESC_TIMEOUT, 100);
-        boolean nonBlockingEnabled =
-               escapeTimeout > 0L
-            && terminal.isSupported()
-            && in != null;
-
-        /*
-         * If we had a non-blocking thread already going, then shut it down
-         * and start a new one.
-         */
-        if (this.in != null) {
-            this.in.shutdown();
-        }
-
-        final InputStream wrapped = terminal.wrapInIfNeeded( in );
-
-        this.in = new NonBlockingInputStream(wrapped, nonBlockingEnabled);
-        this.reader = new InputStreamReader( this.in, encoding );
-    }
-
-    /**
-     * Shuts the console reader down.  This method should be called when you
-     * have completed using the reader as it shuts down and cleans up resources
-     * that would otherwise be "leaked".
-     */
-    @Override
-    public void close() {
-        if (in != null) {
-            in.shutdown();
-        }
-    }
-
-    /**
-     * Shuts the console reader down.  The same as {@link #close()}.
-     * @deprecated Use {@link #close()} instead.
-     */
-    @Deprecated
-    public void shutdown() {
-        this.close();
-    }
-
-    /**
-     * Shuts down the ConsoleReader if the JVM attempts to clean it up.
-     */
-    @Override
-    @SuppressWarnings("deprecation")
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        }
-        finally {
-            super.finalize();
-        }
-    }
-
-    public InputStream getInput() {
-        return in;
-    }
-
-    public Writer getOutput() {
-        return out;
-    }
-
-    public Terminal getTerminal() {
-        return terminal;
-    }
-
-    public CursorBuffer getCursorBuffer() {
-        return buf;
-    }
-
-    public void setExpandEvents(final boolean expand) {
-        this.expandEvents = expand;
-    }
-
-    public boolean getExpandEvents() {
-        return expandEvents;
-    }
-
-    /**
-     * Enables or disables copy and paste detection. The effect of enabling this
-     * this setting is that when a tab is received immediately followed by another
-     * character, the tab will not be treated as a completion, but as a tab literal.
-     * @param onoff true if detection is enabled
-     */
-    public void setCopyPasteDetection(final boolean onoff) {
-        copyPasteDetection = onoff;
-    }
-
-    /**
-     * @return true if copy and paste detection is enabled.
-     */
-    public boolean isCopyPasteDetectionEnabled() {
-        return copyPasteDetection;
-    }
-
-    /**
-     * Set whether the console bell is enabled.
-     *
-     * @param enabled true if enabled; false otherwise
-     * @since 2.7
-     */
-    public void setBellEnabled(boolean enabled) {
-        this.bellEnabled = enabled;
-    }
-
-    /**
-     * Get whether the console bell is enabled
-     *
-     * @return true if enabled; false otherwise
-     * @since 2.7
-     */
-    public boolean getBellEnabled() {
-        return bellEnabled;
-    }
-
-    /**
-     * Set whether user interrupts (ctrl-C) are handled by having JLine
-     * throw {@link UserInterruptException} from {@link #readLine}.
-     * Otherwise, the JVM will handle {@code SIGINT} as normal, which
-     * usually causes it to exit. The default is {@code false}.
-     *
-     * @since 2.10
-     */
-    public void setHandleUserInterrupt(boolean enabled)
-    {
-        this.handleUserInterrupt = enabled;
-    }
-
-    /**
-     * Get whether user interrupt handling is enabled
-     *
-     * @return true if enabled; false otherwise
-     * @since 2.10
-     */
-    public boolean getHandleUserInterrupt()
-    {
-        return handleUserInterrupt;
-    }
-
-    /**
-     * Set wether literal next are handled by JLine.
-     *
-     * @since 2.13
-     */
-    public void setHandleLitteralNext(boolean handleLitteralNext) {
-        this.handleLitteralNext = handleLitteralNext;
-    }
-
-    /**
-     * Get wether literal next are handled by JLine.
-     *
-     * @since 2.13
-     */
-    public boolean getHandleLitteralNext() {
-        return handleLitteralNext;
-    }
-
-    /**
-     * Sets the string that will be used to start a comment when the
-     * insert-comment key is struck.
-     * @param commentBegin The begin comment string.
-     * @since 2.7
-     */
-    public void setCommentBegin(String commentBegin) {
-        this.commentBegin = commentBegin;
-    }
-
-    /**
-     * @return the string that will be used to start a comment when the
-     * insert-comment key is struck.
-     * @since 2.7
-     */
-    public String getCommentBegin() {
-        String str = commentBegin;
-
-        if (str == null) {
-            str = consoleKeys.getVariable("comment-begin");
-            if (str == null) {
-                str = "#";
-            }
-        }
-        return str;
-    }
-
-    public void setPrompt(final String prompt) {
-        this.prompt = prompt;
-        this.promptLen = (prompt == null) ? 0 : wcwidth(Ansi.stripAnsi(lastLine(prompt)), 0);
-    }
-
-    public String getPrompt() {
-        return prompt;
-    }
-
-    /**
-     * Set the echo character. For example, to have "*" entered when a password is typed:
-     * <pre>
-     * myConsoleReader.setEchoCharacter(new Character('*'));
-     * </pre>
-     * Setting the character to <code>null</code> will restore normal character echoing.<p/>
-     * Setting the character to <code>Character.valueOf(0)</code> will cause nothing to be echoed.
-     *
-     * @param c the character to echo to the console in place of the typed character.
-     */
-    public void setEchoCharacter(final Character c) {
-        this.echoCharacter = c;
-    }
-
-    /**
-     * Returns the echo character.
-     */
-    public Character getEchoCharacter() {
-        return echoCharacter;
-    }
-
-    /**
-     * Erase the current line.
-     *
-     * @return false if we failed (e.g., the buffer was empty)
-     */
-    protected final boolean resetLine() throws IOException {
-        if (buf.cursor == 0) {
-            return false;
-        }
-
-        StringBuilder killed = new StringBuilder();
-
-        while (buf.cursor > 0) {
-            char c = buf.current();
-            if (c == 0) {
-                break;
-            }
-
-            killed.append(c);
-            backspace();
-        }
-
-        String copy = killed.reverse().toString();
-        killRing.addBackwards(copy);
-
-        return true;
-    }
-
-    int wcwidth(CharSequence str, int pos) {
-        return wcwidth(str, 0, str.length(), pos);
-    }
-
-    int wcwidth(CharSequence str, int start, int end, int pos) {
-        int cur = pos;
-        for (int i = start; i < end;) {
-            int ucs;
-            char c1 = str.charAt(i++);
-            if (!Character.isHighSurrogate(c1) || i >= end) {
-                ucs = c1;
-            } else {
-                char c2 = str.charAt(i);
-                if (Character.isLowSurrogate(c2)) {
-                    i++;
-                    ucs = Character.toCodePoint(c1, c2);
-                } else {
-                    ucs = c1;
-                }
-            }
-            cur += wcwidth(ucs, cur);
-        }
-        return cur - pos;
-    }
-
-    int wcwidth(int ucs, int pos) {
-        if (ucs == '\t') {
-            return nextTabStop(pos);
-        } else if (ucs < 32) {
-            return 2;
-        } else  {
-            int w = WCWidth.wcwidth(ucs);
-            return w > 0 ? w : 0;
-        }
-    }
-
-    int nextTabStop(int pos) {
-        int tabWidth = TAB_WIDTH;
-        int width = getTerminal().getWidth();
-        int mod = (pos + tabWidth - 1) % tabWidth;
-        int npos = pos + tabWidth - mod;
-        return npos < width ? npos - pos : width - pos;
-    }
-
-    int getCursorPosition() {
-        return promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
-    }
-
-    /**
-     * Returns the text after the last '\n'.
-     * prompt is returned if no '\n' characters are present.
-     * null is returned if prompt is null.
-     */
-    private static String lastLine(String str) {
-        if (str == null) return "";
-        int last = str.lastIndexOf("\n");
-
-        if (last >= 0) {
-            return str.substring(last + 1, str.length());
-        }
-
-        return str;
-    }
-
-    /**
-     * Move the cursor position to the specified absolute index.
-     */
-    public boolean setCursorPosition(final int position) throws IOException {
-        if (position == buf.cursor) {
-            return true;
-        }
-
-        return moveCursor(position - buf.cursor) != 0;
-    }
-
-    /**
-     * Set the current buffer's content to the specified {@link String}. The
-     * visual console will be modified to show the current buffer.
-     *
-     * @param buffer the new contents of the buffer.
-     */
-    private void setBuffer(final String buffer) throws IOException {
-        // don't bother modifying it if it is unchanged
-        if (buffer.equals(buf.buffer.toString())) {
-            return;
-        }
-
-        // obtain the difference between the current buffer and the new one
-        int sameIndex = 0;
-
-        for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1)
-            && (i < l2); i++) {
-            if (buffer.charAt(i) == buf.buffer.charAt(i)) {
-                sameIndex++;
-            }
-            else {
-                break;
-            }
-        }
-
-        int diff = buf.cursor - sameIndex;
-        if (diff < 0) { // we can't backspace here so try from the end of the buffer
-            moveToEnd();
-            diff = buf.buffer.length() - sameIndex;
-        }
-
-        backspace(diff); // go back for the differences
-        killLine(); // clear to the end of the line
-        buf.buffer.setLength(sameIndex); // the new length
-        putString(buffer.substring(sameIndex)); // append the differences
-    }
-
-    private void setBuffer(final CharSequence buffer) throws IOException {
-        setBuffer(String.valueOf(buffer));
-    }
-
-    private void setBufferKeepPos(final String buffer) throws IOException {
-        int pos = buf.cursor;
-        setBuffer(buffer);
-        setCursorPosition(pos);
-    }
-
-    private void setBufferKeepPos(final CharSequence buffer) throws IOException {
-        setBufferKeepPos(String.valueOf(buffer));
-    }
-
-    /**
-     * Output put the prompt + the current buffer
-     */
-    public void drawLine() throws IOException {
-        String prompt = getPrompt();
-        if (prompt != null) {
-            rawPrint(prompt);
-        }
-
-        fmtPrint(buf.buffer, 0, buf.cursor, promptLen);
-
-        // force drawBuffer to check for weird wrap (after clear screen)
-        drawBuffer();
-    }
-
-    /**
-     * Clear the line and redraw it.
-     */
-    public void redrawLine() throws IOException {
-        tputs("carriage_return");
-        drawLine();
-    }
-
-    /**
-     * Clear the buffer and add its contents to the history.
-     *
-     * @return the former contents of the buffer.
-     */
-    final String finishBuffer() throws IOException { // FIXME: Package protected because used by tests
-        String str = buf.buffer.toString();
-        String historyLine = str;
-
-        if (expandEvents) {
-            try {
-                str = expandEvents(str);
-                // all post-expansion occurrences of '!' must have been escaped, so re-add escape to each
-                historyLine = str.replace("!", "\\!");
-                // only leading '^' results in expansion, so only re-add escape for that case
-                historyLine = historyLine.replaceAll("^\\^", "\\\\^");
-            } catch(IllegalArgumentException e) {
-                Log.error("Could not expand event", e);
-                beep();
-                buf.clear();
-                str = "";
-            }
-        }
-
-        // we only add it to the history if the buffer is not empty
-        // and if mask is null, since having a mask typically means
-        // the string was a password. We clear the mask after this call
-        if (str.length() > 0) {
-            if (mask == null && isHistoryEnabled()) {
-                history.add(historyLine);
-            }
-            else {
-                mask = null;
-            }
-        }
-
-        history.moveToEnd();
-
-        buf.buffer.setLength(0);
-        buf.cursor = 0;
-
-        return str;
-    }
-
-    /**
-     * Expand event designator such as !!, !#, !3, etc...
-     * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
-     */
-    @SuppressWarnings("fallthrough")
-    protected String expandEvents(String str) throws IOException {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < str.length(); i++) {
-            char c = str.charAt(i);
-            switch (c) {
-                case '\\':
-                    // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
-                    // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
-                    // otherwise, add the escape
-                    if (i + 1 < str.length()) {
-                        char nextChar = str.charAt(i+1);
-                        if (nextChar == '!' || (nextChar == '^' && i == 0)) {
-                            c = nextChar;
-                            i++;
-                        }
-                    }
-                    sb.append(c);
-                    break;
-                case '!':
-                    if (i + 1 < str.length()) {
-                        c = str.charAt(++i);
-                        boolean neg = false;
-                        String rep = null;
-                        int i1, idx;
-                        switch (c) {
-                            case '!':
-                                if (history.size() == 0) {
-                                    throw new IllegalArgumentException("!!: event not found");
-                                }
-                                rep = history.get(history.index() - 1).toString();
-                                break;
-                            case '#':
-                                sb.append(sb.toString());
-                                break;
-                            case '?':
-                                i1 = str.indexOf('?', i + 1);
-                                if (i1 < 0) {
-                                    i1 = str.length();
-                                }
-                                String sc = str.substring(i + 1, i1);
-                                i = i1;
-                                idx = searchBackwards(sc);
-                                if (idx < 0) {
-                                    throw new IllegalArgumentException("!?" + sc + ": event not found");
-                                } else {
-                                    rep = history.get(idx).toString();
-                                }
-                                break;
-                            case '$':
-                                if (history.size() == 0) {
-                                    throw new IllegalArgumentException("!$: event not found");
-                                }
-                                String previous = history.get(history.index() - 1).toString().trim();
-                                int lastSpace = previous.lastIndexOf(' ');
-                                if(lastSpace != -1) {
-                                    rep = previous.substring(lastSpace+1);
-                                } else {
-                                    rep = previous;
-                                }
-                                break;
-                            case ' ':
-                            case '\t':
-                                sb.append('!');
-                                sb.append(c);
-                                break;
-                            case '-':
-                                neg = true;
-                                i++;
-                                // fall through
-                            case '0':
-                            case '1':
-                            case '2':
-                            case '3':
-                            case '4':
-                            case '5':
-                            case '6':
-                            case '7':
-                            case '8':
-                            case '9':
-                                i1 = i;
-                                for (; i < str.length(); i++) {
-                                    c = str.charAt(i);
-                                    if (c < '0' || c > '9') {
-                                        break;
-                                    }
-                                }
-                                idx = 0;
-                                try {
-                                    idx = Integer.parseInt(str.substring(i1, i));
-                                } catch (NumberFormatException e) {
-                                    throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
-                                }
-                                if (neg) {
-                                    if (idx > 0 && idx <= history.size()) {
-                                        rep = (history.get(history.index() - idx)).toString();
-                                    } else {
-                                        throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
-                                    }
-                                } else {
-                                    if (idx > history.index() - history.size() && idx <= history.index()) {
-                                        rep = (history.get(idx - 1)).toString();
-                                    } else {
-                                        throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
-                                    }
-                                }
-                                break;
-                            default:
-                                String ss = str.substring(i);
-                                i = str.length();
-                                idx = searchBackwards(ss, history.index(), true);
-                                if (idx < 0) {
-                                    throw new IllegalArgumentException("!" + ss + ": event not found");
-                                } else {
-                                    rep = history.get(idx).toString();
-                                }
-                                break;
-                        }
-                        if (rep != null) {
-                            sb.append(rep);
-                        }
-                    } else {
-                        sb.append(c);
-                    }
-                    break;
-                case '^':
-                    if (i == 0) {
-                        int i1 = str.indexOf('^', i + 1);
-                        int i2 = str.indexOf('^', i1 + 1);
-                        if (i2 < 0) {
-                            i2 = str.length();
-                        }
-                        if (i1 > 0 && i2 > 0) {
-                            String s1 = str.substring(i + 1, i1);
-                            String s2 = str.substring(i1 + 1, i2);
-                            String s = history.get(history.index() - 1).toString().replace(s1, s2);
-                            sb.append(s);
-                            i = i2 + 1;
-                            break;
-                        }
-                    }
-                    sb.append(c);
-                    break;
-                default:
-                    sb.append(c);
-                    break;
-            }
-        }
-        String result = sb.toString();
-        if (!str.equals(result)) {
-            fmtPrint(result, getCursorPosition());
-            println();
-            flush();
-        }
-        return result;
-
-    }
-
-    /**
-     * Write out the specified string to the buffer and the output stream.
-     */
-    public void putString(final CharSequence str) throws IOException {
-        int pos = getCursorPosition();
-        buf.write(str);
-        if (mask == null) {
-            // no masking
-            fmtPrint(str, pos);
-        } else if (mask == NULL_MASK) {
-            // don't print anything
-        } else {
-            rawPrint(mask, str.length());
-        }
-        drawBuffer();
-    }
-
-    /**
-     * Redraw the rest of the buffer from the cursor onwards. This is necessary
-     * for inserting text into the buffer.
-     *
-     * @param clear the number of characters to clear after the end of the buffer
-     */
-    private void drawBuffer(final int clear) throws IOException {
-        // debug ("drawBuffer: " + clear);
-        int nbChars = buf.length() - buf.cursor;
-        if (buf.cursor != buf.length() || clear != 0) {
-            if (mask != null) {
-                if (mask != NULL_MASK) {
-                    rawPrint(mask, nbChars);
-                } else {
-                    nbChars = 0;
-                }
-            } else {
-                fmtPrint(buf.buffer, buf.cursor, buf.length());
-            }
-        }
-        int cursorPos = promptLen + wcwidth(buf.buffer, 0, buf.length(), promptLen);
-        if (terminal.hasWeirdWrap() && !cursorOk) {
-            int width = terminal.getWidth();
-            // best guess on whether the cursor is in that weird location...
-            // Need to do this without calling ansi cursor location methods
-            // otherwise it breaks paste of wrapped lines in xterm.
-            if (cursorPos > 0 && (cursorPos % width == 0)) {
-                // the following workaround is reverse-engineered from looking
-                // at what bash sent to the terminal in the same situation
-                rawPrint(' '); // move cursor to next line by printing dummy space
-                tputs("carriage_return"); // CR / not newline.
-            }
-            cursorOk = true;
-        }
-        clearAhead(clear, cursorPos);
-        back(nbChars);
-    }
-
-    /**
-     * Redraw the rest of the buffer from the cursor onwards. This is necessary
-     * for inserting text into the buffer.
-     */
-    private void drawBuffer() throws IOException {
-        drawBuffer(0);
-    }
-
-    /**
-     * Clear ahead the specified number of characters without moving the cursor.
-     *
-     * @param num the number of characters to clear
-     * @param pos the current screen cursor position
-     */
-    private void clearAhead(int num, final int pos) throws IOException {
-        if (num == 0) return;
-
-        int width = terminal.getWidth();
-        // Use kill line
-        if (terminal.getStringCapability("clr_eol") != null) {
-            int cur = pos;
-            int c0 = cur % width;
-            // Erase end of current line
-            int nb = Math.min(num, width - c0);
-            tputs("clr_eol");
-            num -= nb;
-            // Loop
-            while (num > 0) {
-                // Move to beginning of next line
-                int prev = cur;
-                cur = cur - cur % width + width;
-                moveCursorFromTo(prev, cur);
-                // Erase
-                nb = Math.min(num, width);
-                tputs("clr_eol");
-                num -= nb;
-            }
-            moveCursorFromTo(cur, pos);
-        }
-        // Terminal does not wrap on the right margin
-        else if (!terminal.getBooleanCapability("auto_right_margin")) {
-            int cur = pos;
-            int c0 = cur % width;
-            // Erase end of current line
-            int nb = Math.min(num, width - c0);
-            rawPrint(' ', nb);
-            num -= nb;
-            cur += nb;
-            // Loop
-            while (num > 0) {
-                // Move to beginning of next line
-                moveCursorFromTo(cur, ++cur);
-                // Erase
-                nb = Math.min(num, width);
-                rawPrint(' ', nb);
-                num -= nb;
-                cur += nb;
-            }
-            moveCursorFromTo(cur, pos);
-        }
-        // Simple erasure
-        else {
-            rawPrint(' ', num);
-            moveCursorFromTo(pos + num, pos);
-        }
-    }
-
-    /**
-     * Move the visual cursor backward without modifying the buffer cursor.
-     */
-    protected void back(final int num) throws IOException {
-        if (num == 0) return;
-        int i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
-        int i1 = i0 + ((mask != null) ? num : wcwidth(buf.buffer, buf.cursor, buf.cursor + num, i0));
-        moveCursorFromTo(i1, i0);
-    }
-
-    /**
-     * Flush the console output stream. This is important for printout out single characters (like a backspace or
-     * keyboard) that we want the console to handle immediately.
-     */
-    public void flush() throws IOException {
-        out.flush();
-    }
-
-    private int backspaceAll() throws IOException {
-        return backspace(Integer.MAX_VALUE);
-    }
-
-    /**
-     * Issue <em>num</em> backspaces.
-     *
-     * @return the number of characters backed up
-     */
-    private int backspace(final int num) throws IOException {
-        if (buf.cursor == 0) {
-            return 0;
-        }
-
-        int count = - moveCursor(-num);
-        int clear = wcwidth(buf.buffer, buf.cursor, buf.cursor + count, getCursorPosition());
-        buf.buffer.delete(buf.cursor, buf.cursor + count);
-
-        drawBuffer(clear);
-        return count;
-    }
-
-    /**
-     * Issue a backspace.
-     *
-     * @return true if successful
-     */
-    public boolean backspace() throws IOException {
-        return backspace(1) == 1;
-    }
-
-    protected boolean moveToEnd() throws IOException {
-        if (buf.cursor == buf.length()) {
-            return true;
-        }
-        return moveCursor(buf.length() - buf.cursor) > 0;
-    }
-
-    /**
-     * Delete the character at the current position and redraw the remainder of the buffer.
-     */
-    private boolean deleteCurrentCharacter() throws IOException {
-        if (buf.length() == 0 || buf.cursor == buf.length()) {
-            return false;
-        }
-
-        buf.buffer.deleteCharAt(buf.cursor);
-        drawBuffer(1);
-        return true;
-    }
-
-    /**
-     * This method is calling while doing a delete-to ("d"), change-to ("c"),
-     * or yank-to ("y") and it filters out only those movement operations
-     * that are allowable during those operations. Any operation that isn't
-     * allow drops you back into movement mode.
-     *
-     * @param op The incoming operation to remap
-     * @return The remaped operation
-     */
-    private Operation viDeleteChangeYankToRemap (Operation op) {
-        switch (op) {
-            case VI_EOF_MAYBE:
-            case ABORT:
-            case BACKWARD_CHAR:
-            case FORWARD_CHAR:
-            case END_OF_LINE:
-            case VI_MATCH:
-            case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
-            case VI_ARG_DIGIT:
-            case VI_PREV_WORD:
-            case VI_END_WORD:
-            case VI_CHAR_SEARCH:
-            case VI_NEXT_WORD:
-            case VI_FIRST_PRINT:
-            case VI_GOTO_MARK:
-            case VI_COLUMN:
-            case VI_DELETE_TO:
-            case VI_YANK_TO:
-            case VI_CHANGE_TO:
-                return op;
-
-            default:
-                return Operation.VI_MOVEMENT_MODE;
-        }
-    }
-
-    /**
-     * Deletes the previous character from the cursor position
-     * @param count number of times to do it.
-     * @return true if it was done.
-     */
-    private boolean viRubout(int count) throws IOException {
-        boolean ok = true;
-        for (int i = 0; ok && i < count; i++) {
-            ok = backspace();
-        }
-        return ok;
-    }
-
-    /**
-     * Deletes the character you are sitting on and sucks the rest of
-     * the line in from the right.
-     * @param count Number of times to perform the operation.
-     * @return true if its works, false if it didn't
-     */
-    private boolean viDelete(int count) throws IOException {
-        boolean ok = true;
-        for (int i = 0; ok && i < count; i++) {
-            ok = deleteCurrentCharacter();
-        }
-        return ok;
-    }
-
-    /**
-     * Switches the case of the current character from upper to lower
-     * or lower to upper as necessary and advances the cursor one
-     * position to the right.
-     * @param count The number of times to repeat
-     * @return true if it completed successfully, false if not all
-     *   case changes could be completed.
-     */
-    private boolean viChangeCase(int count) throws IOException {
-        boolean ok = true;
-        for (int i = 0; ok && i < count; i++) {
-
-            ok = buf.cursor < buf.buffer.length ();
-            if (ok) {
-                char ch = buf.buffer.charAt(buf.cursor);
-                if (Character.isUpperCase(ch)) {
-                    ch = Character.toLowerCase(ch);
-                }
-                else if (Character.isLowerCase(ch)) {
-                    ch = Character.toUpperCase(ch);
-                }
-                buf.buffer.setCharAt(buf.cursor, ch);
-                drawBuffer(1);
-                moveCursor(1);
-            }
-        }
-        return ok;
-    }
-
-    /**
-     * Implements the vi change character command (in move-mode "r"
-     * followed by the character to change to).
-     * @param count Number of times to perform the action
-     * @param c The character to change to
-     * @return Whether or not there were problems encountered
-     */
-    private boolean viChangeChar(int count, int c) throws IOException {
-        // EOF, ESC, or CTRL-C aborts.
-        if (c < 0 || c == '\033' || c == '\003') {
-            return true;
-        }
-
-        boolean ok = true;
-        for (int i = 0; ok && i < count; i++) {
-            ok = buf.cursor < buf.buffer.length ();
-            if (ok) {
-                buf.buffer.setCharAt(buf.cursor, (char) c);
-                drawBuffer(1);
-                if (i < (count-1)) {
-                    moveCursor(1);
-                }
-            }
-        }
-        return ok;
-    }
-
-    /**
-     * This is a close facsimile of the actual vi previous word logic. In
-     * actual vi words are determined by boundaries of identity characterse.
-     * This logic is a bit more simple and simply looks at white space or
-     * digits or characters.  It should be revised at some point.
-     *
-     * @param count number of iterations
-     * @return true if the move was successful, false otherwise
-     */
-    private boolean viPreviousWord(int count) throws IOException {
-        boolean ok = true;
-        if (buf.cursor == 0) {
-            return false;
-        }
-
-        int pos = buf.cursor - 1;
-        for (int i = 0; pos > 0 && i < count; i++) {
-            // If we are on white space, then move back.
-            while (pos > 0 && isWhitespace(buf.buffer.charAt(pos))) {
-                --pos;
-            }
-
-            while (pos > 0 && !isDelimiter(buf.buffer.charAt(pos-1))) {
-                --pos;
-            }
-
-            if (pos > 0 && i < (count-1)) {
-                --pos;
-            }
-        }
-        setCursorPosition(pos);
-        return ok;
-    }
-
-    /**
-     * Performs the vi "delete-to" action, deleting characters between a given
-     * span of the input line.
-     * @param startPos The start position
-     * @param endPos The end position.
-     * @param isChange If true, then the delete is part of a change operationg
-     *    (e.g. "c$" is change-to-end-of line, so we first must delete to end
-     *    of line to start the change
-     * @return true if it succeeded, false otherwise
-     */
-    private boolean viDeleteTo(int startPos, int endPos, boolean isChange) throws IOException {
-        if (startPos == endPos) {
-            return true;
-        }
-
-        if (endPos < startPos) {
-            int tmp = endPos;
-            endPos = startPos;
-            startPos = tmp;
-        }
-
-        setCursorPosition(startPos);
-        buf.cursor = startPos;
-        buf.buffer.delete(startPos, endPos);
-        drawBuffer(endPos - startPos);
-
-        // If we are doing a delete operation (e.g. "d$") then don't leave the
-        // cursor dangling off the end. In reality the "isChange" flag is silly
-        // what is really happening is that if we are in "move-mode" then the
-        // cursor can't be moved off the end of the line, but in "edit-mode" it
-        // is ok, but I have no easy way of knowing which mode we are in.
-        if (! isChange && startPos > 0 && startPos == buf.length()) {
-            moveCursor(-1);
-        }
-        return true;
-    }
-
-    /**
-     * Implement the "vi" yank-to operation.  This operation allows you
-     * to yank the contents of the current line based upon a move operation,
-     * for exaple "yw" yanks the current word, "3yw" yanks 3 words, etc.
-     *
-     * @param startPos The starting position from which to yank
-     * @param endPos The ending position to which to yank
-     * @return true if the yank succeeded
-     */
-    private boolean viYankTo(int startPos, int endPos) throws IOException {
-        int cursorPos = startPos;
-
-        if (endPos < startPos) {
-            int tmp = endPos;
-            endPos = startPos;
-            startPos = tmp;
-        }
-
-        if (startPos == endPos) {
-            yankBuffer = "";
-            return true;
-        }
-
-        yankBuffer = buf.buffer.substring(startPos, endPos);
-
-        /*
-         * It was a movement command that moved the cursor to find the
-         * end position, so put the cursor back where it started.
-         */
-        setCursorPosition(cursorPos);
-        return true;
-    }
-
-    /**
-     * Pasts the yank buffer to the right of the current cursor position
-     * and moves the cursor to the end of the pasted region.
-     *
-     * @param count Number of times to perform the operation.
-     * @return true if it worked, false otherwise
-     */
-    private boolean viPut(int count) throws IOException {
-        if (yankBuffer.length () == 0) {
-            return true;
-        }
-        if (buf.cursor < buf.buffer.length ()) {
-            moveCursor(1);
-        }
-        for (int i = 0; i < count; i++) {
-            putString(yankBuffer);
-        }
-        moveCursor(-1);
-        return true;
-    }
-
-    /**
-     * Searches forward of the current position for a character and moves
-     * the cursor onto it.
-     * @param count Number of times to repeat the process.
-     * @param ch The character to search for
-     * @return true if the char was found, false otherwise
-     */
-    private boolean viCharSearch(int count, int invokeChar, int ch) throws IOException {
-        if (ch < 0 || invokeChar < 0) {
-            return false;
-        }
-
-        char    searchChar = (char)ch;
-        boolean isForward;
-        boolean stopBefore;
-
-        /*
-         * The character stuff turns out to be hairy. Here is how it works:
-         *   f - search forward for ch
-         *   F - search backward for ch
-         *   t - search forward for ch, but stop just before the match
-         *   T - search backward for ch, but stop just after the match
-         *   ; - After [fFtT;], repeat the last search, after ',' reverse it
-         *   , - After [fFtT;], reverse the last search, after ',' repeat it
-         */
-        if (invokeChar == ';' || invokeChar == ',') {
-            // No recent search done? Then bail
-            if (charSearchChar == 0) {
-                return false;
-            }
-
-            // Reverse direction if switching between ',' and ';'
-            if (charSearchLastInvokeChar == ';' || charSearchLastInvokeChar == ',') {
-                if (charSearchLastInvokeChar != invokeChar) {
-                    charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
-                }
-            }
-            else {
-                if (invokeChar == ',') {
-                    charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
-                }
-            }
-
-            searchChar = charSearchChar;
-        }
-        else {
-            charSearchChar            = searchChar;
-            charSearchFirstInvokeChar = (char) invokeChar;
-        }
-
-        charSearchLastInvokeChar = (char)invokeChar;
-
-        isForward = Character.isLowerCase(charSearchFirstInvokeChar);
-        stopBefore = (Character.toLowerCase(charSearchFirstInvokeChar) == 't');
-
-        boolean ok = false;
-
-        if (isForward) {
-            while (count-- > 0) {
-                int pos = buf.cursor + 1;
-                while (pos < buf.buffer.length()) {
-                    if (buf.buffer.charAt(pos) == searchChar) {
-                        setCursorPosition(pos);
-                        ok = true;
-                        break;
-                    }
-                    ++pos;
-                }
-            }
-
-            if (ok) {
-                if (stopBefore)
-                    moveCursor(-1);
-
-                /*
-                 * When in yank-to, move-to, del-to state we actually want to
-                 * go to the character after the one we landed on to make sure
-                 * that the character we ended up on is included in the
-                 * operation
-                 */
-                if (isInViMoveOperationState()) {
-                    moveCursor(1);
-                }
-            }
-        }
-        else {
-            while (count-- > 0) {
-                int pos = buf.cursor - 1;
-                while (pos >= 0) {
-                    if (buf.buffer.charAt(pos) == searchChar) {
-                        setCursorPosition(pos);
-                        ok = true;
-                        break;
-                    }
-                    --pos;
-                }
-            }
-
-            if (ok && stopBefore)
-                moveCursor(1);
-        }
-
-        return ok;
-    }
-
-    private static char switchCase(char ch) {
-        if (Character.isUpperCase(ch)) {
-            return Character.toLowerCase(ch);
-        }
-        return Character.toUpperCase(ch);
-    }
-
-    /**
-     * @return true if line reader is in the middle of doing a change-to
-     *   delete-to or yank-to.
-     */
-    private final boolean isInViMoveOperationState() {
-        return state == State.VI_CHANGE_TO
-            || state == State.VI_DELETE_TO
-            || state == State.VI_YANK_TO;
-    }
-
-    /**
-     * This is a close facsimile of the actual vi next word logic.
-     * As with viPreviousWord() this probably needs to be improved
-     * at some point.
-     *
-     * @param count number of iterations
-     * @return true if the move was successful, false otherwise
-     */
-    private boolean viNextWord(int count) throws IOException {
-        int pos = buf.cursor;
-        int end = buf.buffer.length();
-
-        for (int i = 0; pos < end && i < count; i++) {
-            // Skip over letter/digits
-            while (pos < end && !isDelimiter(buf.buffer.charAt(pos))) {
-                ++pos;
-            }
-
-            /*
-             * Don't you love special cases? During delete-to and yank-to
-             * operations the word movement is normal. However, during a
-             * change-to, the trailing spaces behind the last word are
-             * left in tact.
-             */
-            if (i < (count-1) || !(state == State.VI_CHANGE_TO)) {
-                while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
-                    ++pos;
-                }
-            }
-        }
-
-        setCursorPosition(pos);
-        return true;
-    }
-
-    /**
-     * Implements a close facsimile of the vi end-of-word movement.
-     * If the character is on white space, it takes you to the end
-     * of the next word.  If it is on the last character of a word
-     * it takes you to the next of the next word.  Any other character
-     * of a word, takes you to the end of the current word.
-     *
-     * @param count Number of times to repeat the action
-     * @return true if it worked.
-     */
-    private boolean viEndWord(int count) throws IOException {
-        int pos = buf.cursor;
-        int end = buf.buffer.length();
-
-        for (int i = 0; pos < end && i < count; i++) {
-            if (pos < (end-1)
-                    && !isDelimiter(buf.buffer.charAt(pos))
-                    && isDelimiter(buf.buffer.charAt (pos+1))) {
-                ++pos;
-            }
-
-            // If we are on white space, then move back.
-            while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
-                ++pos;
-            }
-
-            while (pos < (end-1) && !isDelimiter(buf.buffer.charAt(pos+1))) {
-                ++pos;
-            }
-        }
-        setCursorPosition(pos);
-        return true;
-    }
-
-    private boolean previousWord() throws IOException {
-        while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
-            // nothing
-        }
-
-        while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
-            // nothing
-        }
-
-        return true;
-    }
-
-    private boolean nextWord() throws IOException {
-        while (isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
-            // nothing
-        }
-
-        while (!isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
-            // nothing
-        }
-
-        return true;
-    }
-
-    /**
-     * Deletes to the beginning of the word that the cursor is sitting on.
-     * If the cursor is on white-space, it deletes that and to the beginning
-     * of the word before it.  If the user is not on a word or whitespace
-     * it deletes up to the end of the previous word.
-     *
-     * @param count Number of times to perform the operation
-     * @return true if it worked, false if you tried to delete too many words
-     */
-    private boolean unixWordRubout(int count) throws IOException {
-        boolean success = true;
-        StringBuilder killed = new StringBuilder();
-
-        for (; count > 0; --count) {
-            if (buf.cursor == 0) {
-                success = false;
-                break;
-            }
-
-            while (isWhitespace(buf.current())) {
-                char c = buf.current();
-                if (c == 0) {
-                    break;
-                }
-
-                killed.append(c);
-                backspace();
-            }
-
-            while (!isWhitespace(buf.current())) {
-                char c = buf.current();
-                if (c == 0) {
-                    break;
-                }
-
-                killed.append(c);
-                backspace();
-            }
-        }
-
-        String copy = killed.reverse().toString();
-        killRing.addBackwards(copy);
-
-        return success;
-    }
-
-    private String insertComment(boolean isViMode) throws IOException {
-        String comment = this.getCommentBegin();
-        setCursorPosition(0);
-        putString(comment);
-        if (isViMode) {
-            consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-        }
-        return accept();
-    }
-
-    /**
-     * Implements vi search ("/" or "?").
-     */
-    @SuppressWarnings("fallthrough")
-    private int viSearch(char searchChar) throws IOException {
-        boolean isForward = (searchChar == '/');
-
-        /*
-         * This is a little gross, I'm sure there is a more appropriate way
-         * of saving and restoring state.
-         */
-        CursorBuffer origBuffer = buf.copy();
-
-        // Clear the contents of the current line and
-        setCursorPosition (0);
-        killLine();
-
-        // Our new "prompt" is the character that got us into search mode.
-        putString(Character.toString(searchChar));
-        flush();
-
-        boolean isAborted = false;
-        boolean isComplete = false;
-
-        /*
-         * Readline doesn't seem to do any special character map handling
-         * here, so I think we are safe.
-         */
-        int ch = -1;
-        while (!isAborted && !isComplete && (ch = readCharacter()) != -1) {
-            switch (ch) {
-                case '\033':  // ESC
-                    /*
-                     * The ESC behavior doesn't appear to be readline behavior,
-                     * but it is a little tweak of my own. I like it.
-                     */
-                    isAborted = true;
-                    break;
-                case '\010':  // Backspace
-                case '\177':  // Delete
-                    backspace();
-                    /*
-                     * Backspacing through the "prompt" aborts the search.
-                     */
-                    if (buf.cursor == 0) {
-                        isAborted = true;
-                    }
-                    break;
-                case '\012': // NL
-                case '\015': // CR
-                    isComplete = true;
-                    break;
-                default:
-                    putString(Character.toString((char) ch));
-            }
-
-            flush();
-        }
-
-        // If we aborted, then put ourself at the end of the original buffer.
-        if (ch == -1 || isAborted) {
-            setCursorPosition(0);
-            killLine();
-            putString(origBuffer.buffer);
-            setCursorPosition(origBuffer.cursor);
-            return -1;
-        }
-
-        /*
-         * The first character of the buffer was the search character itself
-         * so we discard it.
-         */
-        String searchTerm = buf.buffer.substring(1);
-        int idx = -1;
-
-        /*
-         * The semantics of the history thing is gross when you want to
-         * explicitly iterate over entries (without an iterator) as size()
-         * returns the actual number of entries in the list but get()
-         * doesn't work the way you think.
-         */
-        int end   = history.index();
-        int start = (end <= history.size()) ? 0 : end - history.size();
-
-        if (isForward) {
-            for (int i = start; i < end; i++) {
-                if (history.get(i).toString().contains(searchTerm)) {
-                    idx = i;
-                    break;
-                }
-            }
-        }
-        else {
-            for (int i = end-1; i >= start; i--) {
-                if (history.get(i).toString().contains(searchTerm)) {
-                    idx = i;
-                    break;
-                }
-            }
-        }
-
-        /*
-         * No match? Then restore what we were working on, but make sure
-         * the cursor is at the beginning of the line.
-         */
-        if (idx == -1) {
-            setCursorPosition(0);
-            killLine();
-            putString(origBuffer.buffer);
-            setCursorPosition(0);
-            return -1;
-        }
-
-        /*
-         * Show the match.
-         */
-        setCursorPosition(0);
-        killLine();
-        putString(history.get(idx));
-        setCursorPosition(0);
-        flush();
-
-        /*
-         * While searching really only the "n" and "N" keys are interpreted
-         * as movement, any other key is treated as if you are editing the
-         * line with it, so we return it back up to the caller for interpretation.
-         */
-        isComplete = false;
-        while (!isComplete && (ch = readCharacter()) != -1) {
-            boolean forward = isForward;
-            switch (ch) {
-                case 'p': case 'P':
-                    forward = !isForward;
-                    // Fallthru
-                case 'n': case 'N':
-                    boolean isMatch = false;
-                    if (forward) {
-                        for (int i = idx+1; !isMatch && i < end; i++) {
-                            if (history.get(i).toString().contains(searchTerm)) {
-                                idx = i;
-                                isMatch = true;
-                            }
-                        }
-                    }
-                    else {
-                        for (int i = idx - 1; !isMatch && i >= start; i--) {
-                            if (history.get(i).toString().contains(searchTerm)) {
-                                idx = i;
-                                isMatch = true;
-                            }
-                        }
-                    }
-                    if (isMatch) {
-                        setCursorPosition(0);
-                        killLine();
-                        putString(history.get(idx));
-                        setCursorPosition(0);
-                    }
-                    break;
-                default:
-                    isComplete = true;
-            }
-            flush();
-        }
-
-        /*
-         * Complete?
-         */
-        return ch;
-    }
-
-    public void setParenBlinkTimeout(int timeout) {
-        parenBlinkTimeout = timeout;
-    }
-
-    private void insertClose(String s) throws IOException {
-        putString(s);
-        int closePosition = buf.cursor;
-
-        moveCursor(-1);
-        viMatch();
-
-
-        if (in.isNonBlockingEnabled()) {
-            in.peek(parenBlinkTimeout);
-        }
-
-        setCursorPosition(closePosition);
-        flush();
-    }
-
-    /**
-     * Implements vi style bracket matching ("%" command). The matching
-     * bracket for the current bracket type that you are sitting on is matched.
-     * The logic works like so:
-     * @return true if it worked, false if the cursor was not on a bracket
-     *   character or if there was no matching bracket.
-     */
-    private boolean viMatch() throws IOException {
-        int pos        = buf.cursor;
-
-        if (pos == buf.length()) {
-            return false;
-        }
-
-        int type       = getBracketType(buf.buffer.charAt (pos));
-        int move       = (type < 0) ? -1 : 1;
-        int count      = 1;
-
-        if (type == 0)
-            return false;
-
-        while (count > 0) {
-            pos += move;
-
-            // Fell off the start or end.
-            if (pos < 0 || pos >= buf.buffer.length ()) {
-                return false;
-            }
-
-            int curType = getBracketType(buf.buffer.charAt (pos));
-            if (curType == type) {
-                ++count;
-            }
-            else if (curType == -type) {
-                --count;
-            }
-        }
-
-        /*
-         * Slight adjustment for delete-to, yank-to, change-to to ensure
-         * that the matching paren is consumed
-         */
-        if (move > 0 && isInViMoveOperationState())
-            ++pos;
-
-        setCursorPosition(pos);
-        flush();
-        return true;
-    }
-
-    /**
-     * Given a character determines what type of bracket it is (paren,
-     * square, curly, or none).
-     * @param ch The character to check
-     * @return 1 is square, 2 curly, 3 parent, or zero for none.  The value
-     *   will be negated if it is the closing form of the bracket.
-     */
-    private static int getBracketType (char ch) {
-        switch (ch) {
-            case '[': return  1;
-            case ']': return -1;
-            case '{': return  2;
-            case '}': return -2;
-            case '(': return  3;
-            case ')': return -3;
-            default:
-                return 0;
-        }
-    }
-
-    private boolean deletePreviousWord() throws IOException {
-        StringBuilder killed = new StringBuilder();
-        char c;
-
-        while (isDelimiter((c = buf.current()))) {
-            if (c == 0) {
-                break;
-            }
-
-            killed.append(c);
-            backspace();
-        }
-
-        while (!isDelimiter((c = buf.current()))) {
-            if (c == 0) {
-                break;
-            }
-
-            killed.append(c);
-            backspace();
-        }
-
-        String copy = killed.reverse().toString();
-        killRing.addBackwards(copy);
-        return true;
-    }
-
-    private boolean deleteNextWord() throws IOException {
-        StringBuilder killed = new StringBuilder();
-        char c;
-
-        while (isDelimiter((c = buf.nextChar()))) {
-            if (c == 0) {
-                break;
-            }
-            killed.append(c);
-            delete();
-        }
-
-        while (!isDelimiter((c = buf.nextChar()))) {
-            if (c == 0) {
-                break;
-            }
-            killed.append(c);
-            delete();
-        }
-
-        String copy = killed.toString();
-        killRing.add(copy);
-
-        return true;
-    }
-
-    private boolean capitalizeWord() throws IOException {
-        boolean first = true;
-        int i = 1;
-        char c;
-        while (buf.cursor + i  - 1< buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
-            buf.buffer.setCharAt(buf.cursor + i - 1, first ? Character.toUpperCase(c) : Character.toLowerCase(c));
-            first = false;
-            i++;
-        }
-        drawBuffer();
-        moveCursor(i - 1);
-        return true;
-    }
-
-    private boolean upCaseWord() throws IOException {
-        int i = 1;
-        char c;
-        while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
-            buf.buffer.setCharAt(buf.cursor + i - 1, Character.toUpperCase(c));
-            i++;
-        }
-        drawBuffer();
-        moveCursor(i - 1);
-        return true;
-    }
-
-    private boolean downCaseWord() throws IOException {
-        int i = 1;
-        char c;
-        while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
-            buf.buffer.setCharAt(buf.cursor + i - 1, Character.toLowerCase(c));
-            i++;
-        }
-        drawBuffer();
-        moveCursor(i - 1);
-        return true;
-    }
-
-    /**
-     * Performs character transpose. The character prior to the cursor and the
-     * character under the cursor are swapped and the cursor is advanced one
-     * character unless you are already at the end of the line.
-     *
-     * @param count The number of times to perform the transpose
-     * @return true if the operation succeeded, false otherwise (e.g. transpose
-     *   cannot happen at the beginning of the line).
-     */
-    private boolean transposeChars(int count) throws IOException {
-        for (; count > 0; --count) {
-            if (buf.cursor == 0 || buf.cursor == buf.buffer.length()) {
-                return false;
-            }
-
-            int first  = buf.cursor-1;
-            int second = buf.cursor;
-
-            char tmp = buf.buffer.charAt (first);
-            buf.buffer.setCharAt(first, buf.buffer.charAt(second));
-            buf.buffer.setCharAt(second, tmp);
-
-            // This could be done more efficiently by only re-drawing at the end.
-            moveInternal(-1);
-            drawBuffer();
-            moveInternal(2);
-        }
-
-        return true;
-    }
-
-    public boolean isKeyMap(String name) {
-        // Current keymap.
-        KeyMap map = consoleKeys.getKeys();
-        KeyMap mapByName = consoleKeys.getKeyMaps().get(name);
-
-        if (mapByName == null)
-            return false;
-
-        /*
-         * This may not be safe to do, but there doesn't appear to be a
-         * clean way to find this information out.
-         */
-        return map == mapByName;
-    }
-
-
-    /**
-     * The equivalent of hitting &lt;RET&gt;.  The line is considered
-     * complete and is returned.
-     *
-     * @return The completed line of text.
-     */
-    public String accept() throws IOException {
-        moveToEnd();
-        println(); // output newline
-        flush();
-        return finishBuffer();
-    }
-
-    private void abort() throws IOException {
-        beep();
-        buf.clear();
-        println();
-        redrawLine();
-    }
-
-    /**
-     * Move the cursor <i>where</i> characters.
-     *
-     * @param num   If less than 0, move abs(<i>where</i>) to the left, otherwise move <i>where</i> to the right.
-     * @return      The number of spaces we moved
-     */
-    public int moveCursor(final int num) throws IOException {
-        int where = num;
-
-        if ((buf.cursor == 0) && (where <= 0)) {
-            return 0;
-        }
-
-        if ((buf.cursor == buf.buffer.length()) && (where >= 0)) {
-            return 0;
-        }
-
-        if ((buf.cursor + where) < 0) {
-            where = -buf.cursor;
-        }
-        else if ((buf.cursor + where) > buf.buffer.length()) {
-            where = buf.buffer.length() - buf.cursor;
-        }
-
-        moveInternal(where);
-
-        return where;
-    }
-
-    /**
-     * Move the cursor <i>where</i> characters, without checking the current buffer.
-     *
-     * @param where the number of characters to move to the right or left.
-     */
-    private void moveInternal(final int where) throws IOException {
-        // debug ("move cursor " + where + " ("
-        // + buf.cursor + " => " + (buf.cursor + where) + ")");
-        buf.cursor += where;
-
-        int i0;
-        int i1;
-        if (mask == null) {
-            if (where < 0) {
-                i1 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
-                i0 = i1 + wcwidth(buf.buffer, buf.cursor, buf.cursor - where, i1);
-            } else {
-                i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor - where, promptLen);
-                i1 = i0 + wcwidth(buf.buffer, buf.cursor - where, buf.cursor, i0);
-            }
-        } else if (mask != NULL_MASK) {
-            i1 = promptLen + buf.cursor;
-            i0 = i1 - where;
-        } else {
-            return;
-        }
-        moveCursorFromTo(i0, i1);
-    }
-
-    private void moveCursorFromTo(int i0, int i1) throws IOException {
-        if (i0 == i1) return;
-        int width = getTerminal().getWidth();
-        int l0 = i0 / width;
-        int c0 = i0 % width;
-        int l1 = i1 / width;
-        int c1 = i1 % width;
-        if (l0 == l1 + 1) {
-            if (!tputs("cursor_up")) {
-                tputs("parm_up_cursor", 1);
-            }
-        } else if (l0 > l1) {
-            if (!tputs("parm_up_cursor", l0 - l1)) {
-                for (int i = l1; i < l0; i++) {
-                    tputs("cursor_up");
-                }
-            }
-        } else if (l0 < l1) {
-            tputs("carriage_return");
-            rawPrint('\n', l1 - l0);
-            c0 = 0;
-        }
-        if (c0 == c1 - 1) {
-            tputs("cursor_right");
-        } else if (c0 == c1 + 1) {
-            tputs("cursor_left");
-        } else if (c0 < c1) {
-            if (!tputs("parm_right_cursor", c1 - c0)) {
-                for (int i = c0; i < c1; i++) {
-                    tputs("cursor_right");
-                }
-            }
-        } else if (c0 > c1) {
-            if (!tputs("parm_left_cursor", c0 - c1)) {
-                for (int i = c1; i < c0; i++) {
-                    tputs("cursor_left");
-                }
-            }
-        }
-        cursorOk = true;
-    }
-
-    /**
-     * Read a character from the console.
-     *
-     * @return the character, or -1 if an EOF is received.
-     */
-    public int readCharacter() throws IOException {
-      return readCharacter(false);
-    }
-
-    /**
-     * Read a character from the console.  If boolean parameter is "true", it will check whether the keystroke was an "alt-" key combination, and
-     * if so add 1000 to the value returned.  Better way...?
-     *
-     * @return the character, or -1 if an EOF is received.
-     */
-    public int readCharacter(boolean checkForAltKeyCombo) throws IOException {
-        int c = reader.read();
-        if (c >= 0) {
-            Log.trace("Keystroke: ", c);
-            // clear any echo characters
-            if (terminal.isSupported()) {
-                clearEcho(c);
-            }
-            if (c == ESCAPE && checkForAltKeyCombo && in.peek(escapeTimeout) >= 32) {
-              /* When ESC is encountered and there is a pending
-               * character in the pushback queue, then it seems to be
-               * an Alt-[key] combination.  Is this true, cross-platform?
-               * It's working for me on Debian GNU/Linux at the moment anyway.
-               * I removed the "isNonBlockingEnabled" check, though it was
-               * in the similar code in "readLine(String prompt, final Character mask)" (way down),
-               * as I am not sure / didn't look up what it's about, and things are working so far w/o it.
-               */
-              int next = reader.read();
-              // with research, there's probably a much cleaner way to do this, but, this is now it flags an Alt key combination for now:
-              next = next + 1000;
-              return next;
-            }
-        }
-        return c;
-    }
-
-    /**
-     * Clear the echoed characters for the specified character code.
-     */
-    private int clearEcho(final int c) throws IOException {
-        // if the terminal is not echoing, then ignore
-        if (!terminal.isEchoEnabled()) {
-            return 0;
-        }
-
-        // otherwise, clear
-        int pos = getCursorPosition();
-        int num = wcwidth(c, pos);
-        moveCursorFromTo(pos + num, pos);
-        drawBuffer(num);
-
-        return num;
-    }
-
-    public int readCharacter(final char... allowed) throws IOException {
-      return readCharacter(false, allowed);
-    }
-
-    public int readCharacter(boolean checkForAltKeyCombo, final char... allowed) throws IOException {
-        // if we restrict to a limited set and the current character is not in the set, then try again.
-        char c;
-
-        Arrays.sort(allowed); // always need to sort before binarySearch
-
-        while (Arrays.binarySearch(allowed, c = (char) readCharacter(checkForAltKeyCombo)) < 0) {
-            // nothing
-        }
-
-        return c;
-    }
-
-    /**
-     * Read from the input stream and decode an operation from the key map.
-     *
-     * The input stream will be read character by character until a matching
-     * binding can be found.  Characters that can't possibly be matched to
-     * any binding will be discarded.
-     *
-     * @param keys the KeyMap to use for decoding the input stream
-     * @return the decoded binding or <code>null</code> if the end of
-     *         stream has been reached
-     */
-    public Object readBinding(KeyMap keys) throws IOException {
-        Object o;
-        opBuffer.setLength(0);
-        do {
-            int c = pushBackChar.isEmpty() ? readCharacter() : pushBackChar.pop();
-            if (c == -1) {
-                return null;
-            }
-            opBuffer.appendCodePoint(c);
-
-            if (recording) {
-                macro += new String(Character.toChars(c));
-            }
-
-            if (quotedInsert) {
-                o = Operation.SELF_INSERT;
-                quotedInsert = false;
-            } else {
-                o = keys.getBound(opBuffer);
-            }
-
-            /*
-             * The kill ring keeps record of whether or not the
-             * previous command was a yank or a kill. We reset
-             * that state here if needed.
-             */
-            if (!recording && !(o instanceof KeyMap)) {
-                if (o != Operation.YANK_POP && o != Operation.YANK) {
-                    killRing.resetLastYank();
-                }
-                if (o != Operation.KILL_LINE && o != Operation.KILL_WHOLE_LINE
-                        && o != Operation.BACKWARD_KILL_WORD && o != Operation.KILL_WORD
-                        && o != Operation.UNIX_LINE_DISCARD && o != Operation.UNIX_WORD_RUBOUT) {
-                    killRing.resetLastKill();
-                }
-            }
-
-            if (o == Operation.DO_LOWERCASE_VERSION) {
-                opBuffer.setLength(opBuffer.length() - 1);
-                opBuffer.append(Character.toLowerCase((char) c));
-                o = keys.getBound(opBuffer);
-            }
-
-            /*
-             * A KeyMap indicates that the key that was struck has a
-             * number of keys that can follow it as indicated in the
-             * map. This is used primarily for Emacs style ESC-META-x
-             * lookups. Since more keys must follow, go back to waiting
-             * for the next key.
-             */
-            if (o instanceof KeyMap) {
-                /*
-                 * The ESC key (#27) is special in that it is ambiguous until
-                 * you know what is coming next.  The ESC could be a literal
-                 * escape, like the user entering vi-move mode, or it could
-                 * be part of a terminal control sequence.  The following
-                 * logic attempts to disambiguate things in the same
-                 * fashion as regular vi or readline.
-                 *
-                 * When ESC is encountered and there is no other pending
-                 * character in the pushback queue, then attempt to peek
-                 * into the input stream (if the feature is enabled) for
-                 * 150ms. If nothing else is coming, then assume it is
-                 * not a terminal control sequence, but a raw escape.
-                 */
-                if (c == ESCAPE
-                        && pushBackChar.isEmpty()
-                        && in.isNonBlockingEnabled()
-                        && in.peek(escapeTimeout) == READ_EXPIRED) {
-                    o = ((KeyMap) o).getAnotherKey();
-                    if (o == null || o instanceof KeyMap) {
-                        continue;
-                    }
-                    opBuffer.setLength(0);
-                } else {
-                    continue;
-                }
-            }
-
-            /*
-             * If we didn't find a binding for the key and there is
-             * more than one character accumulated then start checking
-             * the largest span of characters from the beginning to
-             * see if there is a binding for them.
-             *
-             * For example if our buffer has ESC,CTRL-M,C the getBound()
-             * called previously indicated that there is no binding for
-             * this sequence, so this then checks ESC,CTRL-M, and failing
-             * that, just ESC. Each keystroke that is pealed off the end
-             * during these tests is stuffed onto the pushback buffer so
-             * they won't be lost.
-             *
-             * If there is no binding found, then we go back to waiting for
-             * input.
-             */
-            while (o == null && opBuffer.length() > 0) {
-                c = opBuffer.charAt(opBuffer.length() - 1);
-                opBuffer.setLength(opBuffer.length() - 1);
-                Object o2 = keys.getBound(opBuffer);
-                if (o2 instanceof KeyMap) {
-                    o = ((KeyMap) o2).getAnotherKey();
-                    if (o == null) {
-                        continue;
-                    } else {
-                        pushBackChar.push((char) c);
-                    }
-                }
-            }
-
-        } while (o == null || o instanceof KeyMap);
-
-        return o;
-    }
-
-    public String getLastBinding() {
-        return opBuffer.toString();
-    }
-
-    //
-    // Key Bindings
-    //
-
-    public static final String JLINE_COMPLETION_THRESHOLD = "jline.completion.threshold";
-
-    //
-    // Line Reading
-    //
-
-    /**
-     * Read the next line and return the contents of the buffer.
-     */
-    public String readLine() throws IOException {
-        return readLine((String) null);
-    }
-
-    /**
-     * Read the next line with the specified character mask. If null, then
-     * characters will be echoed. If 0, then no characters will be echoed.
-     */
-    public String readLine(final Character mask) throws IOException {
-        return readLine(null, mask);
-    }
-
-    public String readLine(final String prompt) throws IOException {
-        return readLine(prompt, null);
-    }
-
-    /**
-     * Read a line from the <i>in</i> {@link InputStream}, and return the line
-     * (without any trailing newlines).
-     *
-     * @param prompt    The prompt to issue to the console, may be null.
-     * @return          A line that is read from the terminal, or null if there was null input (e.g., <i>CTRL-D</i>
-     *                  was pressed).
-     */
-    public String readLine(String prompt, final Character mask) throws IOException {
-        return readLine(prompt, mask, null);
-    }
-
-    /**
-     * Sets the current keymap by name. Supported keymaps are "emacs",
-     * "vi-insert", "vi-move".
-     * @param name The name of the keymap to switch to
-     * @return true if the keymap was set, or false if the keymap is
-     *    not recognized.
-     */
-    public boolean setKeyMap(String name) {
-        return consoleKeys.setKeyMap(name);
-    }
-
-    /**
-     * Returns the name of the current key mapping.
-     * @return the name of the key mapping. This will be the canonical name
-     *   of the current mode of the key map and may not reflect the name that
-     *   was used with {@link #setKeyMap(String)}.
-     */
-    public String getKeyMap() {
-        return consoleKeys.getKeys().getName();
-    }
-
-    /**
-     * Read a line from the <i>in</i> {@link InputStream}, and return the line
-     * (without any trailing newlines).
-     *
-     * @param prompt    The prompt to issue to the console, may be null.
-     * @return          A line that is read from the terminal, or null if there was null input (e.g., <i>CTRL-D</i>
-     *                  was pressed).
-     */
-    public String readLine(String prompt, final Character mask, String buffer) throws IOException {
-        // prompt may be null
-        // mask may be null
-        // buffer may be null
-
-        /*
-         * This is the accumulator for VI-mode repeat count. That is, while in
-         * move mode, if you type 30x it will delete 30 characters. This is
-         * where the "30" is accumulated until the command is struck.
-         */
-        int repeatCount = 0;
-
-        // FIXME: This blows, each call to readLine will reset the console's state which doesn't seem very nice.
-        this.mask = mask != null ? mask : this.echoCharacter;
-        if (prompt != null) {
-            setPrompt(prompt);
-        }
-        else {
-            prompt = getPrompt();
-        }
-
-        try {
-            if (buffer != null) {
-                buf.write(buffer);
-            }
-
-            if (!terminal.isSupported()) {
-                beforeReadLine(prompt, mask);
-            }
-
-            if (buffer != null && buffer.length() > 0
-                    || prompt != null && prompt.length() > 0) {
-                drawLine();
-                out.flush();
-            }
-
-            if (terminal.isAnsiSupported() && System.console() != null) {
-                //detect the prompt length by reading the cursor position from the terminal
-                //the real prompt length could differ from the simple prompt length due to
-                //use of escape sequences:
-                out.write("\033[6n");
-                out.flush();
-                StringBuilder input = new StringBuilder();
-                while (true) {
-                    int read;
-                    while ((read = in.read()) != 'R') {
-                        input.appendCodePoint(read);
-                    }
-                    input.appendCodePoint(read);
-                    Matcher m = CURSOR_COLUMN_PATTERN.matcher(input);
-                    if (m.matches()) {
-                        promptLen = Integer.parseInt(m.group("column")) - 1;
-                        String prefix = m.group("prefix");
-                        List<Character> chars = new ArrayList<>();
-                        for (int i = prefix.length() - 1; i >= 0; i--) {
-                            chars.add(prefix.charAt(i));
-                        }
-                        pushBackChar.addAll(0, chars);
-                        break;
-                    }
-                }
-            }
-
-            // if the terminal is unsupported, just use plain-java reading
-            if (!terminal.isSupported()) {
-                return readLineSimple();
-            }
-
-            if (handleUserInterrupt) {
-                terminal.disableInterruptCharacter();
-            }
-            if (handleLitteralNext && (terminal instanceof UnixTerminal)) {
-                ((UnixTerminal) terminal).disableLitteralNextCharacter();
-            }
-
-            String originalPrompt = this.prompt;
-
-            state = State.NORMAL;
-
-            boolean success = true;
-
-            while (true) {
-
-                Object o = readBinding(getKeys());
-                if (o == null) {
-                    return null;
-                }
-                int c = 0;
-                if (opBuffer.length() > 0) {
-                    c = opBuffer.codePointBefore(opBuffer.length());
-                }
-                Log.trace("Binding: ", o);
-
-
-                // Handle macros
-                if (o instanceof String) {
-                    String macro = (String) o;
-                    for (int i = 0; i < macro.length(); i++) {
-                        pushBackChar.push(macro.charAt(macro.length() - 1 - i));
-                    }
-                    opBuffer.setLength(0);
-                    continue;
-                }
-
-                // Handle custom callbacks
-                //original code:
-//                if (o instanceof ActionListener) {
-//                    ((ActionListener) o).actionPerformed(null);
-//                    sb.setLength( 0 );
-//                    continue;
-//                }
-                //using reflection to avoid dependency on java.desktop:
-                try {
-                    Class<?> actionListener =
-                            Class.forName("java.awt.event.ActionListener", false, ClassLoader.getSystemClassLoader());
-                    Class<?> actionEvent =
-                            Class.forName("java.awt.event.ActionEvent", false, ClassLoader.getSystemClassLoader());
-                    if (actionListener.isAssignableFrom(o.getClass())) {
-                        Method actionPerformed =
-                                actionListener.getMethod("actionPerformed", actionEvent);
-                        try {
-                            actionPerformed.invoke(o, (Object) null);
-                        } catch (InvocationTargetException ex ) {
-                            Log.error("Exception while running registered action", ex);
-                        }
-                        opBuffer.setLength(0);
-                        continue;
-                    }
-                } catch (ReflectiveOperationException ex) {
-                    //ignore
-                }
-
-                if (o instanceof Runnable) {
-                    ((Runnable) o).run();
-                    opBuffer.setLength(0);
-                    continue;
-                }
-
-                CursorBuffer oldBuf = new CursorBuffer();
-                oldBuf.buffer.append(buf.buffer);
-                oldBuf.cursor = buf.cursor;
-
-                // Search mode.
-                //
-                // Note that we have to do this first, because if there is a command
-                // not linked to a search command, we leave the search mode and fall
-                // through to the normal state.
-                if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
-                    int cursorDest = -1;
-                    // TODO: check the isearch-terminators variable terminating the search
-                    switch ( ((Operation) o )) {
-                        case ABORT:
-                            state = State.NORMAL;
-                            buf.clear();
-                            buf.write(originalBuffer.buffer);
-                            buf.cursor = originalBuffer.cursor;
-                            break;
-
-                        case REVERSE_SEARCH_HISTORY:
-                            state = State.SEARCH;
-                            if (searchTerm.length() == 0) {
-                                searchTerm.append(previousSearchTerm);
-                            }
-
-                            if (searchIndex > 0) {
-                                searchIndex = searchBackwards(searchTerm.toString(), searchIndex);
-                            }
-                            break;
-
-                        case FORWARD_SEARCH_HISTORY:
-                            state = State.FORWARD_SEARCH;
-                            if (searchTerm.length() == 0) {
-                                searchTerm.append(previousSearchTerm);
-                            }
-
-                            if (searchIndex > -1 && searchIndex < history.size() - 1) {
-                                searchIndex = searchForwards(searchTerm.toString(), searchIndex);
-                            }
-                            break;
-
-                        case BACKWARD_DELETE_CHAR:
-                            if (searchTerm.length() > 0) {
-                                searchTerm.deleteCharAt(searchTerm.length() - 1);
-                                if (state == State.SEARCH) {
-                                    searchIndex = searchBackwards(searchTerm.toString());
-                                } else {
-                                    searchIndex = searchForwards(searchTerm.toString());
-                                }
-                            }
-                            break;
-
-                        case SELF_INSERT:
-                            searchTerm.appendCodePoint(c);
-                            if (state == State.SEARCH) {
-                                searchIndex = searchBackwards(searchTerm.toString());
-                            } else {
-                                searchIndex = searchForwards(searchTerm.toString());
-                            }
-                            break;
-
-                        default:
-                            // Set buffer and cursor position to the found string.
-                            if (searchIndex != -1) {
-                                history.moveTo(searchIndex);
-                                // set cursor position to the found string
-                                cursorDest = history.current().toString().indexOf(searchTerm.toString());
-                            }
-                            if (o != Operation.ACCEPT_LINE) {
-                                o = null;
-                            }
-                            state = State.NORMAL;
-                            break;
-                    }
-
-                    // if we're still in search mode, print the search status
-                    if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
-                        if (searchTerm.length() == 0) {
-                            if (state == State.SEARCH) {
-                                printSearchStatus("", "");
-                            } else {
-                                printForwardSearchStatus("", "");
-                            }
-                            searchIndex = -1;
-                        } else {
-                            if (searchIndex == -1) {
-                                beep();
-                                printSearchStatus(searchTerm.toString(), "");
-                            } else if (state == State.SEARCH) {
-                                printSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
-                            } else {
-                                printForwardSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
-                            }
-                        }
-                    }
-                    // otherwise, restore the line
-                    else {
-                        restoreLine(originalPrompt, cursorDest);
-                    }
-                }
-                if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
-                    /*
-                     * If this is still false at the end of the switch, then
-                     * we reset our repeatCount to 0.
-                     */
-                    boolean isArgDigit = false;
-
-                    /*
-                     * Every command that can be repeated a specified number
-                     * of times, needs to know how many times to repeat, so
-                     * we figure that out here.
-                     */
-                    int count = (repeatCount == 0) ? 1 : repeatCount;
-
-                    /*
-                     * Default success to true. You only need to explicitly
-                     * set it if something goes wrong.
-                     */
-                    success = true;
-
-                    if (o instanceof Operation) {
-                        Operation op = (Operation)o;
-                        /*
-                         * Current location of the cursor (prior to the operation).
-                         * These are used by vi *-to operation (e.g. delete-to)
-                         * so we know where we came from.
-                         */
-                        int     cursorStart = buf.cursor;
-                        State   origState   = state;
-
-                        /*
-                         * If we are on a "vi" movement based operation, then we
-                         * need to restrict the sets of inputs pretty heavily.
-                         */
-                        if (state == State.VI_CHANGE_TO
-                            || state == State.VI_YANK_TO
-                            || state == State.VI_DELETE_TO) {
-
-                            op = viDeleteChangeYankToRemap(op);
-                        }
-
-                        switch ( op ) {
-                            case COMPLETE: // tab
-                                // There is an annoyance with tab completion in that
-                                // sometimes the user is actually pasting input in that
-                                // has physical tabs in it.  This attempts to look at how
-                                // quickly a character follows the tab, if the character
-                                // follows *immediately*, we assume it is a tab literal.
-                                boolean isTabLiteral = false;
-                                if (copyPasteDetection
-                                    && c == 9
-                                    && (!pushBackChar.isEmpty()
-                                        || (in.isNonBlockingEnabled() && in.peek(escapeTimeout) != -2))) {
-                                    isTabLiteral = true;
-                                }
-
-                                if (! isTabLiteral) {
-                                    success = complete();
-                                }
-                                else {
-                                    putString(opBuffer);
-                                }
-                                break;
-
-                            case POSSIBLE_COMPLETIONS:
-                                printCompletionCandidates();
-                                break;
-
-                            case BEGINNING_OF_LINE:
-                                success = setCursorPosition(0);
-                                break;
-
-                            case YANK:
-                                success = yank();
-                                break;
-
-                            case YANK_POP:
-                                success = yankPop();
-                                break;
-
-                            case KILL_LINE: // CTRL-K
-                                success = killLine();
-                                break;
-
-                            case KILL_WHOLE_LINE:
-                                success = setCursorPosition(0) && killLine();
-                                break;
-
-                            case CLEAR_SCREEN: // CTRL-L
-                                success = clearScreen();
-                                redrawLine();
-                                break;
-
-                            case OVERWRITE_MODE:
-                                buf.setOverTyping(!buf.isOverTyping());
-                                break;
-
-                            case SELF_INSERT:
-                                putString(opBuffer);
-                                break;
-
-                            case ACCEPT_LINE:
-                                return accept();
-
-                            case ABORT:
-                                if (searchTerm == null) {
-                                    abort();
-                                }
-                                break;
-
-                            case INTERRUPT:
-                                if (handleUserInterrupt) {
-                                    println();
-                                    flush();
-                                    String partialLine = buf.buffer.toString();
-                                    buf.clear();
-                                    history.moveToEnd();
-                                    throw new UserInterruptException(partialLine);
-                                }
-                                break;
-
-                            /*
-                             * VI_MOVE_ACCEPT_LINE is the result of an ENTER
-                             * while in move mode. This is the same as a normal
-                             * ACCEPT_LINE, except that we need to enter
-                             * insert mode as well.
-                             */
-                            case VI_MOVE_ACCEPT_LINE:
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                return accept();
-
-                            case BACKWARD_WORD:
-                                success = previousWord();
-                                break;
-
-                            case FORWARD_WORD:
-                                success = nextWord();
-                                break;
-
-                            case PREVIOUS_HISTORY:
-                                success = moveHistory(false);
-                                break;
-
-                            /*
-                             * According to bash/readline move through history
-                             * in "vi" mode will move the cursor to the
-                             * start of the line. If there is no previous
-                             * history, then the cursor doesn't move.
-                             */
-                            case VI_PREVIOUS_HISTORY:
-                                success = moveHistory(false, count)
-                                    && setCursorPosition(0);
-                                break;
-
-                            case NEXT_HISTORY:
-                                success = moveHistory(true);
-                                break;
-
-                            /*
-                             * According to bash/readline move through history
-                             * in "vi" mode will move the cursor to the
-                             * start of the line. If there is no next history,
-                             * then the cursor doesn't move.
-                             */
-                            case VI_NEXT_HISTORY:
-                                success = moveHistory(true, count)
-                                    && setCursorPosition(0);
-                                break;
-
-                            case BACKWARD_DELETE_CHAR: // backspace
-                                success = backspace();
-                                break;
-
-                            case EXIT_OR_DELETE_CHAR:
-                                if (buf.buffer.length() == 0) {
-                                    return null;
-                                }
-                                success = deleteCurrentCharacter();
-                                break;
-
-                            case DELETE_CHAR: // delete
-                                success = deleteCurrentCharacter();
-                                break;
-
-                            case BACKWARD_CHAR:
-                                success = moveCursor(-(count)) != 0;
-                                break;
-
-                            case FORWARD_CHAR:
-                                success = moveCursor(count) != 0;
-                                break;
-
-                            case UNIX_LINE_DISCARD:
-                                success = resetLine();
-                                break;
-
-                            case UNIX_WORD_RUBOUT:
-                                success = unixWordRubout(count);
-                                break;
-
-                            case BACKWARD_KILL_WORD:
-                                success = deletePreviousWord();
-                                break;
-
-                            case KILL_WORD:
-                                success = deleteNextWord();
-                                break;
-
-                            case BEGINNING_OF_HISTORY:
-                                success = history.moveToFirst();
-                                if (success) {
-                                    setBuffer(history.current());
-                                }
-                                break;
-
-                            case END_OF_HISTORY:
-                                success = history.moveToLast();
-                                if (success) {
-                                    setBuffer(history.current());
-                                }
-                                break;
-
-                            case HISTORY_SEARCH_BACKWARD:
-                                searchTerm = new StringBuffer(buf.upToCursor());
-                                searchIndex = searchBackwards(searchTerm.toString(), history.index(), true);
-
-                                if (searchIndex == -1) {
-                                    beep();
-                                } else {
-                                    // Maintain cursor position while searching.
-                                    success = history.moveTo(searchIndex);
-                                    if (success) {
-                                        setBufferKeepPos(history.current());
-                                    }
-                                }
-                                break;
-
-                            case HISTORY_SEARCH_FORWARD:
-                                searchTerm = new StringBuffer(buf.upToCursor());
-                                int index = history.index() + 1;
-
-                                if (index == history.size()) {
-                                    history.moveToEnd();
-                                    setBufferKeepPos(searchTerm.toString());
-                                } else if (index < history.size()) {
-                                    searchIndex = searchForwards(searchTerm.toString(), index, true);
-                                    if (searchIndex == -1) {
-                                        beep();
-                                    } else {
-                                        // Maintain cursor position while searching.
-                                        success = history.moveTo(searchIndex);
-                                        if (success) {
-                                            setBufferKeepPos(history.current());
-                                        }
-                                    }
-                                }
-                                break;
-
-                            case REVERSE_SEARCH_HISTORY:
-                                originalBuffer = new CursorBuffer();
-                                originalBuffer.write(buf.buffer);
-                                originalBuffer.cursor = buf.cursor;
-                                if (searchTerm != null) {
-                                    previousSearchTerm = searchTerm.toString();
-                                }
-                                searchTerm = new StringBuffer(buf.buffer);
-                                state = State.SEARCH;
-                                if (searchTerm.length() > 0) {
-                                    searchIndex = searchBackwards(searchTerm.toString());
-                                    if (searchIndex == -1) {
-                                        beep();
-                                    }
-                                    printSearchStatus(searchTerm.toString(),
-                                            searchIndex > -1 ? history.get(searchIndex).toString() : "");
-                                } else {
-                                    searchIndex = -1;
-                                    printSearchStatus("", "");
-                                }
-                                break;
-
-                            case FORWARD_SEARCH_HISTORY:
-                                originalBuffer = new CursorBuffer();
-                                originalBuffer.write(buf.buffer);
-                                originalBuffer.cursor = buf.cursor;
-                                if (searchTerm != null) {
-                                    previousSearchTerm = searchTerm.toString();
-                                }
-                                searchTerm = new StringBuffer(buf.buffer);
-                                state = State.FORWARD_SEARCH;
-                                if (searchTerm.length() > 0) {
-                                    searchIndex = searchForwards(searchTerm.toString());
-                                    if (searchIndex == -1) {
-                                        beep();
-                                    }
-                                    printForwardSearchStatus(searchTerm.toString(),
-                                            searchIndex > -1 ? history.get(searchIndex).toString() : "");
-                                } else {
-                                    searchIndex = -1;
-                                    printForwardSearchStatus("", "");
-                                }
-                                break;
-
-                            case CAPITALIZE_WORD:
-                                success = capitalizeWord();
-                                break;
-
-                            case UPCASE_WORD:
-                                success = upCaseWord();
-                                break;
-
-                            case DOWNCASE_WORD:
-                                success = downCaseWord();
-                                break;
-
-                            case END_OF_LINE:
-                                success = moveToEnd();
-                                break;
-
-                            case TAB_INSERT:
-                                putString( "\t" );
-                                break;
-
-                            case RE_READ_INIT_FILE:
-                                consoleKeys.loadKeys(appName, inputrcUrl);
-                                break;
-
-                            case START_KBD_MACRO:
-                                recording = true;
-                                break;
-
-                            case END_KBD_MACRO:
-                                recording = false;
-                                macro = macro.substring(0, macro.length() - opBuffer.length());
-                                break;
-
-                            case CALL_LAST_KBD_MACRO:
-                                for (int i = 0; i < macro.length(); i++) {
-                                    pushBackChar.push(macro.charAt(macro.length() - 1 - i));
-                                }
-                                opBuffer.setLength(0);
-                                break;
-
-                            case VI_EDITING_MODE:
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case VI_MOVEMENT_MODE:
-                                /*
-                                 * If we are re-entering move mode from an
-                                 * aborted yank-to, delete-to, change-to then
-                                 * don't move the cursor back. The cursor is
-                                 * only move on an expclit entry to movement
-                                 * mode.
-                                 */
-                                if (state == State.NORMAL) {
-                                    moveCursor(-1);
-                                }
-                                consoleKeys.setKeyMap(KeyMap.VI_MOVE);
-                                break;
-
-                            case VI_INSERTION_MODE:
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case VI_APPEND_MODE:
-                                moveCursor(1);
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case VI_APPEND_EOL:
-                                success = moveToEnd();
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            /*
-                             * Handler for CTRL-D. Attempts to follow readline
-                             * behavior. If the line is empty, then it is an EOF
-                             * otherwise it is as if the user hit enter.
-                             */
-                            case VI_EOF_MAYBE:
-                                if (buf.buffer.length() == 0) {
-                                    return null;
-                                }
-                                return accept();
-
-                            case TRANSPOSE_CHARS:
-                                success = transposeChars(count);
-                                break;
-
-                            case INSERT_COMMENT:
-                                return insertComment (false);
-
-                            case INSERT_CLOSE_CURLY:
-                                insertClose("}");
-                                break;
-
-                            case INSERT_CLOSE_PAREN:
-                                insertClose(")");
-                                break;
-
-                            case INSERT_CLOSE_SQUARE:
-                                insertClose("]");
-                                break;
-
-                            case VI_INSERT_COMMENT:
-                                return insertComment (true);
-
-                            case VI_MATCH:
-                                success = viMatch ();
-                                break;
-
-                            case VI_SEARCH:
-                                int lastChar = viSearch(opBuffer.charAt(0));
-                                if (lastChar != -1) {
-                                    pushBackChar.push((char)lastChar);
-                                }
-                                break;
-
-                            case VI_ARG_DIGIT:
-                                repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
-                                isArgDigit = true;
-                                break;
-
-                            case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
-                                if (repeatCount > 0) {
-                                    repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
-                                    isArgDigit = true;
-                                }
-                                else {
-                                    success = setCursorPosition(0);
-                                }
-                                break;
-
-                            case VI_FIRST_PRINT:
-                                success = setCursorPosition(0) && viNextWord(1);
-                                break;
-
-                            case VI_PREV_WORD:
-                                success = viPreviousWord(count);
-                                break;
-
-                            case VI_NEXT_WORD:
-                                success = viNextWord(count);
-                                break;
-
-                            case VI_END_WORD:
-                                success = viEndWord(count);
-                                break;
-
-                            case VI_INSERT_BEG:
-                                success = setCursorPosition(0);
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case VI_RUBOUT:
-                                success = viRubout(count);
-                                break;
-
-                            case VI_DELETE:
-                                success = viDelete(count);
-                                break;
-
-                            case VI_DELETE_TO:
-                                /*
-                                 * This is a weird special case. In vi
-                                 * "dd" deletes the current line. So if we
-                                 * get a delete-to, followed by a delete-to,
-                                 * we delete the line.
-                                 */
-                                if (state == State.VI_DELETE_TO) {
-                                    success = setCursorPosition(0) && killLine();
-                                    state = origState = State.NORMAL;
-                                }
-                                else {
-                                    state = State.VI_DELETE_TO;
-                                }
-                                break;
-
-                            case VI_YANK_TO:
-                                // Similar to delete-to, a "yy" yanks the whole line.
-                                if (state == State.VI_YANK_TO) {
-                                    yankBuffer = buf.buffer.toString();
-                                    state = origState = State.NORMAL;
-                                }
-                                else {
-                                    state = State.VI_YANK_TO;
-                                }
-                                break;
-
-                            case VI_CHANGE_TO:
-                                if (state == State.VI_CHANGE_TO) {
-                                    success = setCursorPosition(0) && killLine();
-                                    state = origState = State.NORMAL;
-                                    consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                }
-                                else {
-                                    state = State.VI_CHANGE_TO;
-                                }
-                                break;
-
-                            case VI_KILL_WHOLE_LINE:
-                                success = setCursorPosition(0) && killLine();
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case VI_PUT:
-                                success = viPut(count);
-                                break;
-
-                            case VI_CHAR_SEARCH: {
-                                 // ';' and ',' don't need another character. They indicate repeat next or repeat prev.
-                                int searchChar = (c != ';' && c != ',')
-                                    ? (pushBackChar.isEmpty()
-                                        ? readCharacter()
-                                        : pushBackChar.pop ())
-                                    : 0;
-
-                                    success = viCharSearch(count, c, searchChar);
-                                }
-                                break;
-
-                            case VI_CHANGE_CASE:
-                                success = viChangeCase(count);
-                                break;
-
-                            case VI_CHANGE_CHAR:
-                                success = viChangeChar(count,
-                                    pushBackChar.isEmpty()
-                                        ? readCharacter()
-                                        : pushBackChar.pop());
-                                break;
-
-                            case VI_DELETE_TO_EOL:
-                                success = viDeleteTo(buf.cursor, buf.buffer.length(), false);
-                                break;
-
-                            case VI_CHANGE_TO_EOL:
-                                success = viDeleteTo(buf.cursor, buf.buffer.length(), true);
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                                break;
-
-                            case EMACS_EDITING_MODE:
-                                consoleKeys.setKeyMap(KeyMap.EMACS);
-                                break;
-
-                            case QUIT:
-                                getCursorBuffer().clear();
-                                return accept();
-
-                            case QUOTED_INSERT:
-                                quotedInsert = true;
-                                break;
-
-                            case PASTE_FROM_CLIPBOARD:
-//                                paste();
-                                break;
-
-                            default:
-                                break;
-                        }
-
-                        /*
-                         * If we were in a yank-to, delete-to, move-to
-                         * when this operation started, then fall back to
-                         */
-                        if (origState != State.NORMAL) {
-                            if (origState == State.VI_DELETE_TO) {
-                                success = viDeleteTo(cursorStart, buf.cursor, false);
-                            }
-                            else if (origState == State.VI_CHANGE_TO) {
-                                success = viDeleteTo(cursorStart, buf.cursor, true);
-                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
-                            }
-                            else if (origState == State.VI_YANK_TO) {
-                                success = viYankTo(cursorStart, buf.cursor);
-                            }
-                            state = State.NORMAL;
-                        }
-
-                        /*
-                         * Another subtly. The check for the NORMAL state is
-                         * to ensure that we do not clear out the repeat
-                         * count when in delete-to, yank-to, or move-to modes.
-                         */
-                        if (state == State.NORMAL && !isArgDigit) {
-                            /*
-                             * If the operation performed wasn't a vi argument
-                             * digit, then clear out the current repeatCount;
-                             */
-                            repeatCount = 0;
-                        }
-
-                        if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
-                            originalBuffer = null;
-                            previousSearchTerm = "";
-                            searchTerm = null;
-                            searchIndex = -1;
-                        }
-                    }
-                }
-                if (!success) {
-                    beep();
-                }
-                opBuffer.setLength(0);
-
-                flush();
-            }
-        }
-        finally {
-            if (!terminal.isSupported()) {
-                afterReadLine();
-            }
-            if (handleUserInterrupt) {
-                terminal.enableInterruptCharacter();
-            }
-        }
-    }
-    //where:
-        private Pattern CURSOR_COLUMN_PATTERN =
-                Pattern.compile("(?<prefix>.*)\033\\[[0-9]+;(?<column>[0-9]+)R", Pattern.DOTALL);
-
-    /**
-     * Read a line for unsupported terminals.
-     */
-    private String readLineSimple() throws IOException {
-
-        if (skipLF) {
-            skipLF = false;
-
-            int i = readCharacter();
-
-            if (i == -1 || i == '\r') {
-                return finishBuffer();
-            } else if (i == '\n') {
-                // ignore
-            } else {
-                buf.buffer.append((char) i);
-            }
-        }
-
-        while (true) {
-            int i = readCharacter();
-
-            if (i == -1 && buf.buffer.length() == 0) {
-              return null;
-            }
-
-            if (i == -1 || i == '\n') {
-                return finishBuffer();
-            } else if (i == '\r') {
-                skipLF = true;
-                return finishBuffer();
-            } else {
-                buf.buffer.append((char) i);
-            }
-        }
-    }
-
-    //
-    // Completion
-    //
-
-    private final List<Completer> completers = new LinkedList<Completer>();
-
-    private CompletionHandler completionHandler = new CandidateListCompletionHandler();
-
-    /**
-     * Add the specified {@link jline.console.completer.Completer} to the list of handlers for tab-completion.
-     *
-     * @param completer the {@link jline.console.completer.Completer} to add
-     * @return true if it was successfully added
-     */
-    public boolean addCompleter(final Completer completer) {
-        return completers.add(completer);
-    }
-
-    /**
-     * Remove the specified {@link jline.console.completer.Completer} from the list of handlers for tab-completion.
-     *
-     * @param completer     The {@link Completer} to remove
-     * @return              True if it was successfully removed
-     */
-    public boolean removeCompleter(final Completer completer) {
-        return completers.remove(completer);
-    }
-
-    /**
-     * Returns an unmodifiable list of all the completers.
-     */
-    public Collection<Completer> getCompleters() {
-        return Collections.unmodifiableList(completers);
-    }
-
-    public void setCompletionHandler(final CompletionHandler handler) {
-        this.completionHandler = checkNotNull(handler);
-    }
-
-    public CompletionHandler getCompletionHandler() {
-        return this.completionHandler;
-    }
-
-    /**
-     * Use the completers to modify the buffer with the appropriate completions.
-     *
-     * @return true if successful
-     */
-    protected boolean complete() throws IOException {
-        // debug ("tab for (" + buf + ")");
-        if (completers.size() == 0) {
-            return false;
-        }
-
-        List<CharSequence> candidates = new LinkedList<CharSequence>();
-        String bufstr = buf.buffer.toString();
-        int cursor = buf.cursor;
-
-        int position = -1;
-
-        for (Completer comp : completers) {
-            if ((position = comp.complete(bufstr, cursor, candidates)) != -1) {
-                break;
-            }
-        }
-
-        return candidates.size() != 0 && getCompletionHandler().complete(this, candidates, position);
-    }
-
-    protected void printCompletionCandidates() throws IOException {
-        // debug ("tab for (" + buf + ")");
-        if (completers.size() == 0) {
-            return;
-        }
-
-        List<CharSequence> candidates = new LinkedList<CharSequence>();
-        String bufstr = buf.buffer.toString();
-        int cursor = buf.cursor;
-
-        for (Completer comp : completers) {
-            if (comp.complete(bufstr, cursor, candidates) != -1) {
-                break;
-            }
-        }
-        CandidateListCompletionHandler.printCandidates(this, candidates);
-        drawLine();
-    }
-
-    /**
-     * The number of tab-completion candidates above which a warning will be
-     * prompted before showing all the candidates.
-     */
-    private int autoprintThreshold = Configuration.getInteger(JLINE_COMPLETION_THRESHOLD, 100); // same default as bash
-
-    /**
-     * @param threshold the number of candidates to print without issuing a warning.
-     */
-    public void setAutoprintThreshold(final int threshold) {
-        this.autoprintThreshold = threshold;
-    }
-
-    /**
-     * @return the number of candidates to print without issuing a warning.
-     */
-    public int getAutoprintThreshold() {
-        return autoprintThreshold;
-    }
-
-    private boolean paginationEnabled;
-
-    /**
-     * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
-     */
-    public void setPaginationEnabled(final boolean enabled) {
-        this.paginationEnabled = enabled;
-    }
-
-    /**
-     * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
-     */
-    public boolean isPaginationEnabled() {
-        return paginationEnabled;
-    }
-
-    //
-    // History
-    //
-
-    private History history = new MemoryHistory();
-
-    public void setHistory(final History history) {
-        this.history = history;
-    }
-
-    public History getHistory() {
-        return history;
-    }
-
-    private boolean historyEnabled = true;
-
-    /**
-     * Whether or not to add new commands to the history buffer.
-     */
-    public void setHistoryEnabled(final boolean enabled) {
-        this.historyEnabled = enabled;
-    }
-
-    /**
-     * Whether or not to add new commands to the history buffer.
-     */
-    public boolean isHistoryEnabled() {
-        return historyEnabled;
-    }
-
-    /**
-     * Used in "vi" mode for argumented history move, to move a specific
-     * number of history entries forward or back.
-     *
-     * @param next If true, move forward
-     * @param count The number of entries to move
-     * @return true if the move was successful
-     */
-    private boolean moveHistory(final boolean next, int count) throws IOException {
-        boolean ok = true;
-        for (int i = 0; i < count && (ok = moveHistory(next)); i++) {
-            /* empty */
-        }
-        return ok;
-    }
-
-    /**
-     * Move up or down the history tree.
-     */
-    private boolean moveHistory(final boolean next) throws IOException {
-        if (next && !history.next()) {
-            return false;
-        }
-        else if (!next && !history.previous()) {
-            return false;
-        }
-
-        setBuffer(history.current());
-
-        return true;
-    }
-
-    //
-    // Printing
-    //
-
-    /**
-     * Output the specified characters to the output stream without manipulating the current buffer.
-     */
-    private int fmtPrint(final CharSequence buff, int cursorPos) throws IOException {
-        return fmtPrint(buff, 0, buff.length(), cursorPos);
-    }
-
-    private int fmtPrint(final CharSequence buff, int start, int end) throws IOException {
-        return fmtPrint(buff, start, end, getCursorPosition());
-    }
-
-    private int fmtPrint(final CharSequence buff, int start, int end, int cursorPos) throws IOException {
-        checkNotNull(buff);
-        for (int i = start; i < end; i++) {
-            char c = buff.charAt(i);
-            if (c == '\t') {
-                int nb = nextTabStop(cursorPos);
-                cursorPos += nb;
-                while (nb-- > 0) {
-                    out.write(' ');
-                }
-            } else if (c < 32) {
-                out.write('^');
-                out.write((char) (c + '@'));
-                cursorPos += 2;
-            } else {
-                int w = WCWidth.wcwidth(c);
-                if (w > 0) {
-                    out.write(c);
-                    cursorPos += w;
-                }
-            }
-        }
-        cursorOk = false;
-        return cursorPos;
-    }
-
-    /**
-     * Output the specified string to the output stream (but not the buffer).
-     */
-    public void print(final CharSequence s) throws IOException {
-        rawPrint(s.toString());
-    }
-
-    public void println(final CharSequence s) throws IOException {
-        print(s);
-        println();
-    }
-
-    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
-
-    /**
-     * Output a platform-dependent newline.
-     */
-    public void println() throws IOException {
-        rawPrint(LINE_SEPARATOR);
-    }
-
-    /**
-     * Raw output printing
-     */
-    final void rawPrint(final int c) throws IOException {
-        out.write(c);
-        cursorOk = false;
-    }
-
-    final void rawPrint(final String str) throws IOException {
-        out.write(str);
-        cursorOk = false;
-    }
-
-    private void rawPrint(final char c, final int num) throws IOException {
-        for (int i = 0; i < num; i++) {
-            rawPrint(c);
-        }
-    }
-
-    private void rawPrintln(final String s) throws IOException {
-        rawPrint(s);
-        println();
-    }
-
-
-    //
-    // Actions
-    //
-
-    /**
-     * Issue a delete.
-     *
-     * @return true if successful
-     */
-    public boolean delete() throws IOException {
-        if (buf.cursor == buf.buffer.length()) {
-          return false;
-        }
-
-        buf.buffer.delete(buf.cursor, buf.cursor + 1);
-        drawBuffer(1);
-
-        return true;
-    }
-
-    /**
-     * Kill the buffer ahead of the current cursor position.
-     *
-     * @return true if successful
-     */
-    public boolean killLine() throws IOException {
-        int cp = buf.cursor;
-        int len = buf.buffer.length();
-
-        if (cp >= len) {
-            return false;
-        }
-
-        int num = len - cp;
-        int pos = getCursorPosition();
-        int width = wcwidth(buf.buffer, cp, len, pos);
-        clearAhead(width, pos);
-
-        char[] killed = new char[num];
-        buf.buffer.getChars(cp, (cp + num), killed, 0);
-        buf.buffer.delete(cp, (cp + num));
-
-        String copy = new String(killed);
-        killRing.add(copy);
-
-        return true;
-    }
-
-    public boolean yank() throws IOException {
-        String yanked = killRing.yank();
-
-        if (yanked == null) {
-            return false;
-        }
-        putString(yanked);
-        return true;
-    }
-
-    public boolean yankPop() throws IOException {
-        if (!killRing.lastYank()) {
-            return false;
-        }
-        String current = killRing.yank();
-        if (current == null) {
-            // This shouldn't happen.
-            return false;
-        }
-        backspace(current.length());
-        String yanked = killRing.yankPop();
-        if (yanked == null) {
-            // This shouldn't happen.
-            return false;
-        }
-
-        putString(yanked);
-        return true;
-    }
-
-    /**
-     * Clear the screen by issuing the ANSI "clear screen" code.
-     */
-    public boolean clearScreen() throws IOException {
-        if (!tputs("clear_screen")) {
-            println();
-        }
-        return true;
-    }
-
-    /**
-     * Issue an audible keyboard bell.
-     */
-    public void beep() throws IOException {
-        if (bellEnabled) {
-            if (tputs("bell")) {
-                // need to flush so the console actually beeps
-                flush();
-            }
-        }
-    }
-
-    //disabled to avoid dependency on java.desktop:
-//    /**
-//     * Paste the contents of the clipboard into the console buffer
-//     *
-//     * @return true if clipboard contents pasted
-//     */
-//    public boolean paste() throws IOException {
-//        Clipboard clipboard;
-//        try { // May throw ugly exception on system without X
-//            clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-//        }
-//        catch (Exception e) {
-//            return false;
-//        }
-//
-//        if (clipboard == null) {
-//            return false;
-//        }
-//
-//        Transferable transferable = clipboard.getContents(null);
-//
-//        if (transferable == null) {
-//            return false;
-//        }
-//
-//        try {
-//            @SuppressWarnings("deprecation")
-//            Object content = transferable.getTransferData(DataFlavor.plainTextFlavor);
-//
-//            // This fix was suggested in bug #1060649 at
-//            // http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056
-//            // to get around the deprecated DataFlavor.plainTextFlavor, but it
-//            // raises a UnsupportedFlavorException on Mac OS X
-//
-//            if (content == null) {
-//                try {
-//                    content = new DataFlavor().getReaderForText(transferable);
-//                }
-//                catch (Exception e) {
-//                    // ignore
-//                }
-//            }
-//
-//            if (content == null) {
-//                return false;
-//            }
-//
-//            String value;
-//
-//            if (content instanceof Reader) {
-//                // TODO: we might want instead connect to the input stream
-//                // so we can interpret individual lines
-//                value = "";
-//                String line;
-//
-//                BufferedReader read = new BufferedReader((Reader) content);
-//                while ((line = read.readLine()) != null) {
-//                    if (value.length() > 0) {
-//                        value += "\n";
-//                    }
-//
-//                    value += line;
-//                }
-//            }
-//            else {
-//                value = content.toString();
-//            }
-//
-//            if (value == null) {
-//                return true;
-//            }
-//
-//            putString(value);
-//
-//            return true;
-//        }
-//        catch (UnsupportedFlavorException e) {
-//            Log.error("Paste failed: ", e);
-//
-//            return false;
-//        }
-//    }
-
-    //disabled to avoid dependency on java.desktop:
-//    /**
-//     * Adding a triggered Action allows to give another curse of action if a character passed the pre-processing.
-//     * <p/>
-//     * Say you want to close the application if the user enter q.
-//     * addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick.
-//     */
-//    public void addTriggeredAction(final char c, final ActionListener listener) {
-//        getKeys().bind(Character.toString(c), listener);
-//    }
-
-    //
-    // Formatted Output
-    //
-
-    /**
-     * Output the specified {@link Collection} in proper columns.
-     */
-    public void printColumns(final Collection<? extends CharSequence> items) throws IOException {
-        if (items == null || items.isEmpty()) {
-            return;
-        }
-
-        int width = getTerminal().getWidth();
-        int height = getTerminal().getHeight();
-
-        int maxWidth = 0;
-        for (CharSequence item : items) {
-            // we use 0 here, as we don't really support tabulations inside candidates
-            int len = wcwidth(Ansi.stripAnsi(item.toString()), 0);
-            maxWidth = Math.max(maxWidth, len);
-        }
-        maxWidth = maxWidth + 3;
-        Log.debug("Max width: ", maxWidth);
-
-        int showLines;
-        if (isPaginationEnabled()) {
-            showLines = height - 1; // page limit
-        }
-        else {
-            showLines = Integer.MAX_VALUE;
-        }
-
-        StringBuilder buff = new StringBuilder();
-        int realLength = 0;
-        for (CharSequence item : items) {
-            if ((realLength + maxWidth) > width) {
-                rawPrintln(buff.toString());
-                buff.setLength(0);
-                realLength = 0;
-
-                if (--showLines == 0) {
-                    // Overflow
-                    print(resources.getString("DISPLAY_MORE"));
-                    flush();
-                    int c = readCharacter();
-                    if (c == '\r' || c == '\n') {
-                        // one step forward
-                        showLines = 1;
-                    }
-                    else if (c != 'q') {
-                        // page forward
-                        showLines = height - 1;
-                    }
-
-                    tputs("carriage_return");
-                    if (c == 'q') {
-                        // cancel
-                        break;
-                    }
-                }
-            }
-
-            // NOTE: toString() is important here due to AnsiString being retarded
-            buff.append(item.toString());
-            int strippedItemLength = wcwidth(Ansi.stripAnsi(item.toString()), 0);
-            for (int i = 0; i < (maxWidth - strippedItemLength); i++) {
-                buff.append(' ');
-            }
-            realLength += maxWidth;
-        }
-
-        if (buff.length() > 0) {
-            rawPrintln(buff.toString());
-        }
-    }
-
-    //
-    // Non-supported Terminal Support
-    //
-
-    private Thread maskThread;
-
-    private void beforeReadLine(final String prompt, final Character mask) {
-        if (mask != null && maskThread == null) {
-            final String fullPrompt = "\r" + prompt
-                + "                 "
-                + "                 "
-                + "                 "
-                + "\r" + prompt;
-
-            maskThread = new Thread()
-            {
-                public void run() {
-                    while (!interrupted()) {
-                        try {
-                            Writer out = getOutput();
-                            out.write(fullPrompt);
-                            out.flush();
-                            sleep(3);
-                        }
-                        catch (IOException e) {
-                            return;
-                        }
-                        catch (InterruptedException e) {
-                            return;
-                        }
-                    }
-                }
-            };
-
-            maskThread.setPriority(Thread.MAX_PRIORITY);
-            maskThread.setDaemon(true);
-            maskThread.start();
-        }
-    }
-
-    private void afterReadLine() {
-        if (maskThread != null && maskThread.isAlive()) {
-            maskThread.interrupt();
-        }
-
-        maskThread = null;
-    }
-
-    /**
-     * Erases the current line with the existing prompt, then redraws the line
-     * with the provided prompt and buffer
-     * @param prompt
-     *            the new prompt
-     * @param buffer
-     *            the buffer to be drawn
-     * @param cursorDest
-     *            where you want the cursor set when the line has been drawn.
-     *            -1 for end of line.
-     * */
-    public void resetPromptLine(String prompt, String buffer, int cursorDest) throws IOException {
-        // move cursor to end of line
-        moveToEnd();
-
-        // backspace all text, including prompt
-        buf.buffer.append(this.prompt);
-        int promptLength = 0;
-        if (this.prompt != null) {
-            promptLength = this.prompt.length();
-        }
-
-        buf.cursor += promptLength;
-        setPrompt("");
-        backspaceAll();
-
-        setPrompt(prompt);
-        redrawLine();
-        setBuffer(buffer);
-
-        // move cursor to destination (-1 will move to end of line)
-        if (cursorDest < 0) cursorDest = buffer.length();
-        setCursorPosition(cursorDest);
-
-        flush();
-    }
-
-    public void printSearchStatus(String searchTerm, String match) throws IOException {
-        printSearchStatus(searchTerm, match, "(reverse-i-search)`");
-    }
-
-    public void printForwardSearchStatus(String searchTerm, String match) throws IOException {
-        printSearchStatus(searchTerm, match, "(i-search)`");
-    }
-
-    private void printSearchStatus(String searchTerm, String match, String searchLabel) throws IOException {
-        String prompt = searchLabel + searchTerm + "': ";
-        int cursorDest = match.indexOf(searchTerm);
-        resetPromptLine(prompt, match, cursorDest);
-    }
-
-    public void restoreLine(String originalPrompt, int cursorDest) throws IOException {
-        // TODO move cursor to matched string
-        String prompt = lastLine(originalPrompt);
-        String buffer = buf.buffer.toString();
-        resetPromptLine(prompt, buffer, cursorDest);
-    }
-
-    //
-    // History search
-    //
-    /**
-     * Search backward in history from a given position.
-     *
-     * @param searchTerm substring to search for.
-     * @param startIndex the index from which on to search
-     * @return index where this substring has been found, or -1 else.
-     */
-    public int searchBackwards(String searchTerm, int startIndex) {
-        return searchBackwards(searchTerm, startIndex, false);
-    }
-
-    /**
-     * Search backwards in history from the current position.
-     *
-     * @param searchTerm substring to search for.
-     * @return index where the substring has been found, or -1 else.
-     */
-    public int searchBackwards(String searchTerm) {
-        return searchBackwards(searchTerm, history.index());
-    }
-
-
-    public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) {
-        ListIterator<History.Entry> it = history.entries(startIndex);
-        while (it.hasPrevious()) {
-            History.Entry e = it.previous();
-            if (startsWith) {
-                if (e.value().toString().startsWith(searchTerm)) {
-                    return e.index();
-                }
-            } else {
-                if (e.value().toString().contains(searchTerm)) {
-                    return e.index();
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Search forward in history from a given position.
-     *
-     * @param searchTerm substring to search for.
-     * @param startIndex the index from which on to search
-     * @return index where this substring has been found, or -1 else.
-     */
-    public int searchForwards(String searchTerm, int startIndex) {
-        return searchForwards(searchTerm, startIndex, false);
-    }
-    /**
-     * Search forwards in history from the current position.
-     *
-     * @param searchTerm substring to search for.
-     * @return index where the substring has been found, or -1 else.
-     */
-    public int searchForwards(String searchTerm) {
-        return searchForwards(searchTerm, history.index());
-    }
-
-    public int searchForwards(String searchTerm, int startIndex, boolean startsWith) {
-        if (startIndex >= history.size()) {
-            startIndex = history.size() - 1;
-        }
-
-        ListIterator<History.Entry> it = history.entries(startIndex);
-
-        if (searchIndex != -1 && it.hasNext()) {
-            it.next();
-        }
-
-        while (it.hasNext()) {
-            History.Entry e = it.next();
-            if (startsWith) {
-                if (e.value().toString().startsWith(searchTerm)) {
-                    return e.index();
-                }
-            } else {
-                if (e.value().toString().contains(searchTerm)) {
-                    return e.index();
-                }
-            }
-        }
-        return -1;
-    }
-
-    //
-    // Helpers
-    //
-
-    /**
-     * Checks to see if the specified character is a delimiter. We consider a
-     * character a delimiter if it is anything but a letter or digit.
-     *
-     * @param c     The character to test
-     * @return      True if it is a delimiter
-     */
-    private static boolean isDelimiter(final char c) {
-        return !Character.isLetterOrDigit(c);
-    }
-
-    /**
-     * Checks to see if a character is a whitespace character. Currently
-     * this delegates to {@link Character#isWhitespace(char)}, however
-     * eventually it should be hooked up so that the definition of whitespace
-     * can be configured, as readline does.
-     *
-     * @param c The character to check
-     * @return true if the character is a whitespace
-     */
-    private static boolean isWhitespace(final char c) {
-        return Character.isWhitespace (c);
-    }
-
-    private boolean tputs(String cap, Object... params) throws IOException {
-        String str = terminal.getStringCapability(cap);
-        if (str == null) {
-            return false;
-        }
-        Curses.tputs(out, str, params);
-        return true;
-    }
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A holder for a {@link StringBuilder} that also contains the current cursor position.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class CursorBuffer
-{
-    private boolean overTyping = false;
-
-    public int cursor = 0;
-
-    public final StringBuilder buffer = new StringBuilder();
-
-    public CursorBuffer copy () {
-        CursorBuffer that = new CursorBuffer();
-        that.overTyping = this.overTyping;
-        that.cursor = this.cursor;
-        that.buffer.append (this.toString());
-
-        return that;
-    }
-
-    public boolean isOverTyping() {
-        return overTyping;
-    }
-
-    public void setOverTyping(final boolean b) {
-        overTyping = b;
-    }
-
-    public int length() {
-        return buffer.length();
-    }
-
-    public char nextChar() {
-        if (cursor == buffer.length()) {
-            return 0;
-        } else {
-            return buffer.charAt(cursor);
-        }
-    }
-
-    public char current() {
-        if (cursor <= 0) {
-            return 0;
-        }
-
-        return buffer.charAt(cursor - 1);
-    }
-
-    /**
-     * Write the specific character into the buffer, setting the cursor position
-     * ahead one. The text may overwrite or insert based on the current setting
-     * of {@link #isOverTyping}.
-     *
-     * @param c the character to insert
-     */
-    public void write(final char c) {
-        buffer.insert(cursor++, c);
-        if (isOverTyping() && cursor < buffer.length()) {
-            buffer.deleteCharAt(cursor);
-        }
-    }
-
-    /**
-     * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point.
-     */
-    public void write(final CharSequence str) {
-        checkNotNull(str);
-
-        if (buffer.length() == 0) {
-            buffer.append(str);
-        }
-        else {
-            buffer.insert(cursor, str);
-        }
-
-        cursor += str.length();
-
-        if (isOverTyping() && cursor < buffer.length()) {
-            buffer.delete(cursor, cursor + str.length());
-        }
-    }
-
-    public boolean clear() {
-        if (buffer.length() == 0) {
-            return false;
-        }
-
-        buffer.delete(0, buffer.length());
-        cursor = 0;
-        return true;
-    }
-
-    public String upToCursor() {
-        if (cursor <= 0) {
-            return "";
-        }
-
-        return buffer.substring(0, cursor);
-    }
-
-    @Override
-    public String toString() {
-        return buffer.toString();
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,577 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The KeyMap class contains all bindings from keys to operations.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.6
- */
-public class KeyMap {
-
-    public static final String VI_MOVE        = "vi-move";
-    public static final String VI_INSERT      = "vi-insert";
-    public static final String EMACS          = "emacs";
-    public static final String EMACS_STANDARD = "emacs-standard";
-    public static final String EMACS_CTLX     = "emacs-ctlx";
-    public static final String EMACS_META     = "emacs-meta";
-
-    private static final int KEYMAP_LENGTH = 256;
-
-    private static final Object NULL_FUNCTION = new Object();
-
-    private Object[] mapping = new Object[KEYMAP_LENGTH];
-    private Object anotherKey = null;
-    private String name;
-
-    public KeyMap(String name) {
-        this(name, new Object[KEYMAP_LENGTH]);
-    }
-
-    @Deprecated
-    public KeyMap(String name, boolean unused) {
-        this(name);
-    }
-
-    protected KeyMap(String name, Object[] mapping) {
-        this.mapping = mapping;
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public Object getAnotherKey() {
-        return anotherKey;
-    }
-
-    public void from(KeyMap other) {
-        this.mapping = other.mapping;
-        this.anotherKey = other.anotherKey;
-    }
-
-    public Object getBound( CharSequence keySeq ) {
-        if (keySeq != null && keySeq.length() > 0) {
-            KeyMap map = this;
-            for (int i = 0; i < keySeq.length(); i++) {
-                char c = keySeq.charAt(i);
-                if (c > 255) {
-                    return Operation.SELF_INSERT;
-                }
-                if (map.mapping[c] instanceof KeyMap) {
-                    if (i == keySeq.length() - 1) {
-                        return map.mapping[c];
-                    } else {
-                        map = (KeyMap) map.mapping[c];
-                    }
-                } else {
-                    return map.mapping[c];
-                }
-            }
-        }
-        return null;
-    }
-
-    public void bindIfNotBound( CharSequence keySeq, Object function ) {
-
-        bind (this, keySeq, function, true);
-    }
-
-    public void bind( CharSequence keySeq, Object function ) {
-
-        bind (this, keySeq, function, false);
-    }
-
-    private static void bind( KeyMap map, CharSequence keySeq, Object function ) {
-
-        bind (map, keySeq, function, false);
-    }
-
-    private static void bind( KeyMap map, CharSequence keySeq, Object function,
-            boolean onlyIfNotBound ) {
-
-        if (keySeq != null && keySeq.length() > 0) {
-            for (int i = 0; i < keySeq.length(); i++) {
-                char c = keySeq.charAt(i);
-                if (c >= map.mapping.length) {
-                    return;
-                }
-                if (i < keySeq.length() - 1) {
-                    if (!(map.mapping[c] instanceof KeyMap)) {
-                        KeyMap m = new KeyMap("anonymous");
-                        if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) {
-                            m.anotherKey = map.mapping[c];
-                        }
-                        map.mapping[c] = m;
-                    }
-                    map = (KeyMap) map.mapping[c];
-                } else {
-                    if (function == null) {
-                        function = NULL_FUNCTION;
-                    }
-                    if (map.mapping[c] instanceof KeyMap) {
-                        map.anotherKey = function;
-                    } else {
-                        Object op = map.mapping[c];
-                        if (onlyIfNotBound == false
-                            || op == null
-                            || op == Operation.DO_LOWERCASE_VERSION
-                            || op == Operation.VI_MOVEMENT_MODE ) {
-
-                        }
-
-                        map.mapping[c] = function;
-                    }
-                }
-            }
-        }
-    }
-
-    public void setBlinkMatchingParen(boolean on) {
-        if (on) {
-            bind( "}", Operation.INSERT_CLOSE_CURLY );
-            bind( ")", Operation.INSERT_CLOSE_PAREN );
-            bind( "]", Operation.INSERT_CLOSE_SQUARE );
-        }
-    }
-
-    private static void bindArrowKeys(KeyMap map) {
-
-        // MS-DOS
-        bind( map, "\033[0A", Operation.PREVIOUS_HISTORY );
-        bind( map, "\033[0B", Operation.BACKWARD_CHAR );
-        bind( map, "\033[0C", Operation.FORWARD_CHAR );
-        bind( map, "\033[0D", Operation.NEXT_HISTORY );
-
-        // Windows
-        bind( map, "\340\000", Operation.KILL_WHOLE_LINE );
-        bind( map, "\340\107", Operation.BEGINNING_OF_LINE );
-        bind( map, "\340\110", Operation.PREVIOUS_HISTORY );
-        bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY );
-        bind( map, "\340\113", Operation.BACKWARD_CHAR );
-        bind( map, "\340\115", Operation.FORWARD_CHAR );
-        bind( map, "\340\117", Operation.END_OF_LINE );
-        bind( map, "\340\120", Operation.NEXT_HISTORY );
-        bind( map, "\340\121", Operation.END_OF_HISTORY );
-        bind( map, "\340\122", Operation.OVERWRITE_MODE );
-        bind( map, "\340\123", Operation.DELETE_CHAR );
-
-        bind( map, "\000\107", Operation.BEGINNING_OF_LINE );
-        bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
-        bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY );
-        bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
-        bind( map, "\000\113", Operation.BACKWARD_CHAR );
-        bind( map, "\000\115", Operation.FORWARD_CHAR );
-        bind( map, "\000\117", Operation.END_OF_LINE );
-        bind( map, "\000\120", Operation.NEXT_HISTORY );
-        bind( map, "\000\121", Operation.END_OF_HISTORY );
-        bind( map, "\000\122", Operation.OVERWRITE_MODE );
-        bind( map, "\000\123", Operation.DELETE_CHAR );
-
-        bind( map, "\033[A", Operation.PREVIOUS_HISTORY );
-        bind( map, "\033[B", Operation.NEXT_HISTORY );
-        bind( map, "\033[C", Operation.FORWARD_CHAR );
-        bind( map, "\033[D", Operation.BACKWARD_CHAR );
-        bind( map, "\033[H", Operation.BEGINNING_OF_LINE );
-        bind( map, "\033[F", Operation.END_OF_LINE );
-
-        bind( map, "\033OA", Operation.PREVIOUS_HISTORY );
-        bind( map, "\033OB", Operation.NEXT_HISTORY );
-        bind( map, "\033OC", Operation.FORWARD_CHAR );
-        bind( map, "\033OD", Operation.BACKWARD_CHAR );
-        bind( map, "\033OH", Operation.BEGINNING_OF_LINE );
-        bind( map, "\033OF", Operation.END_OF_LINE );
-
-        bind( map, "\033[1~", Operation.BEGINNING_OF_LINE);
-        bind( map, "\033[4~", Operation.END_OF_LINE);
-        bind( map, "\033[3~", Operation.DELETE_CHAR);
-
-        // MINGW32
-        bind( map, "\0340H", Operation.PREVIOUS_HISTORY );
-        bind( map, "\0340P", Operation.NEXT_HISTORY );
-        bind( map, "\0340M", Operation.FORWARD_CHAR );
-        bind( map, "\0340K", Operation.BACKWARD_CHAR );
-    }
-
-//    public boolean isConvertMetaCharsToAscii() {
-//        return convertMetaCharsToAscii;
-//    }
-
-//    public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) {
-//        this.convertMetaCharsToAscii = convertMetaCharsToAscii;
-//    }
-
-    public static boolean isMeta( char c ) {
-        return c > 0x7f && c <= 0xff;
-    }
-
-    public static char unMeta( char c ) {
-        return (char) (c & 0x7F);
-    }
-
-    public static char meta( char c ) {
-        return (char) (c | 0x80);
-    }
-
-    public static Map<String, KeyMap> keyMaps() {
-        Map<String, KeyMap> keyMaps = new HashMap<String, KeyMap>();
-
-        KeyMap emacs = emacs();
-        bindArrowKeys(emacs);
-        keyMaps.put(EMACS, emacs);
-        keyMaps.put(EMACS_STANDARD, emacs);
-        keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018"));
-        keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b"));
-
-        KeyMap viMov = viMovement();
-        bindArrowKeys(viMov);
-        keyMaps.put(VI_MOVE, viMov);
-        keyMaps.put("vi-command", viMov);
-        keyMaps.put("vi", viMov);
-
-        KeyMap viIns = viInsertion();
-        bindArrowKeys(viIns);
-        keyMaps.put(VI_INSERT, viIns);
-
-        return keyMaps;
-    }
-
-    public static KeyMap emacs() {
-        Object[] map = new Object[KEYMAP_LENGTH];
-        Object[] ctrl = new Object[] {
-                        // Control keys.
-                        Operation.SET_MARK,                 /* Control-@ */
-                        Operation.BEGINNING_OF_LINE,        /* Control-A */
-                        Operation.BACKWARD_CHAR,            /* Control-B */
-                        Operation.INTERRUPT,                /* Control-C */
-                        Operation.EXIT_OR_DELETE_CHAR,      /* Control-D */
-                        Operation.END_OF_LINE,              /* Control-E */
-                        Operation.FORWARD_CHAR,             /* Control-F */
-                        Operation.ABORT,                    /* Control-G */
-                        Operation.BACKWARD_DELETE_CHAR,     /* Control-H */
-                        Operation.COMPLETE,                 /* Control-I */
-                        Operation.ACCEPT_LINE,              /* Control-J */
-                        Operation.KILL_LINE,                /* Control-K */
-                        Operation.CLEAR_SCREEN,             /* Control-L */
-                        Operation.ACCEPT_LINE,              /* Control-M */
-                        Operation.NEXT_HISTORY,             /* Control-N */
-                        null,                               /* Control-O */
-                        Operation.PREVIOUS_HISTORY,         /* Control-P */
-                        Operation.QUOTED_INSERT,            /* Control-Q */
-                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
-                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
-                        Operation.TRANSPOSE_CHARS,          /* Control-T */
-                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
-                        Operation.QUOTED_INSERT,            /* Control-V */
-                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
-                        emacsCtrlX(),                       /* Control-X */
-                        Operation.YANK,                     /* Control-Y */
-                        null,                               /* Control-Z */
-                        emacsMeta(),                        /* Control-[ */
-                        null,                               /* Control-\ */
-                        Operation.CHARACTER_SEARCH,         /* Control-] */
-                        null,                               /* Control-^ */
-                        Operation.UNDO,                     /* Control-_ */
-                };
-        System.arraycopy( ctrl, 0, map, 0, ctrl.length );
-        for (int i = 32; i < 256; i++) {
-            map[i] = Operation.SELF_INSERT;
-        }
-        map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
-        return new KeyMap(EMACS, map);
-    }
-
-    public static final char CTRL_D = (char) 4;
-    public static final char CTRL_G = (char) 7;
-    public static final char CTRL_H = (char) 8;
-    public static final char CTRL_I = (char) 9;
-    public static final char CTRL_J = (char) 10;
-    public static final char CTRL_M = (char) 13;
-    public static final char CTRL_R = (char) 18;
-    public static final char CTRL_S = (char) 19;
-    public static final char CTRL_U = (char) 21;
-    public static final char CTRL_X = (char) 24;
-    public static final char CTRL_Y = (char) 25;
-    public static final char ESCAPE = (char) 27; /* Ctrl-[ */
-    public static final char CTRL_OB = (char) 27; /* Ctrl-[ */
-    public static final char CTRL_CB = (char) 29; /* Ctrl-] */
-
-    public static final int DELETE = (char) 127;
-
-    public static KeyMap emacsCtrlX() {
-        Object[] map = new Object[KEYMAP_LENGTH];
-        map[CTRL_G] = Operation.ABORT;
-        map[CTRL_R] = Operation.RE_READ_INIT_FILE;
-        map[CTRL_U] = Operation.UNDO;
-        map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK;
-        map['('] = Operation.START_KBD_MACRO;
-        map[')'] = Operation.END_KBD_MACRO;
-        for (int i = 'A'; i <= 'Z'; i++) {
-            map[i] = Operation.DO_LOWERCASE_VERSION;
-        }
-        map['e'] = Operation.CALL_LAST_KBD_MACRO;
-        map[DELETE] = Operation.KILL_LINE;
-        return new KeyMap(EMACS_CTLX, map);
-    }
-
-    public static KeyMap emacsMeta() {
-        Object[] map = new Object[KEYMAP_LENGTH];
-        map[CTRL_G] = Operation.ABORT;
-        map[CTRL_H] = Operation.BACKWARD_KILL_WORD;
-        map[CTRL_I] = Operation.TAB_INSERT;
-        map[CTRL_J] = Operation.VI_EDITING_MODE;
-        map[CTRL_M] = Operation.VI_EDITING_MODE;
-        map[CTRL_R] = Operation.REVERT_LINE;
-        map[CTRL_Y] = Operation.YANK_NTH_ARG;
-        map[CTRL_OB] = Operation.COMPLETE;
-        map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD;
-        map[' '] = Operation.SET_MARK;
-        map['#'] = Operation.INSERT_COMMENT;
-        map['&'] = Operation.TILDE_EXPAND;
-        map['*'] = Operation.INSERT_COMPLETIONS;
-        map['-'] = Operation.DIGIT_ARGUMENT;
-        map['.'] = Operation.YANK_LAST_ARG;
-        map['<'] = Operation.BEGINNING_OF_HISTORY;
-        map['='] = Operation.POSSIBLE_COMPLETIONS;
-        map['>'] = Operation.END_OF_HISTORY;
-        map['?'] = Operation.POSSIBLE_COMPLETIONS;
-        for (int i = 'A'; i <= 'Z'; i++) {
-            map[i] = Operation.DO_LOWERCASE_VERSION;
-        }
-        map['\\'] = Operation.DELETE_HORIZONTAL_SPACE;
-        map['_'] = Operation.YANK_LAST_ARG;
-        map['b'] = Operation.BACKWARD_WORD;
-        map['c'] = Operation.CAPITALIZE_WORD;
-        map['d'] = Operation.KILL_WORD;
-        map['f'] = Operation.FORWARD_WORD;
-        map['l'] = Operation.DOWNCASE_WORD;
-        map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY;
-        map['r'] = Operation.REVERT_LINE;
-        map['t'] = Operation.TRANSPOSE_WORDS;
-        map['u'] = Operation.UPCASE_WORD;
-        map['y'] = Operation.YANK_POP;
-        map['~'] = Operation.TILDE_EXPAND;
-        map[DELETE] = Operation.BACKWARD_KILL_WORD;
-        return new KeyMap(EMACS_META, map);
-    }
-
-    public static KeyMap viInsertion() {
-        Object[] map = new Object[KEYMAP_LENGTH];
-        Object[] ctrl = new Object[] {
-                        // Control keys.
-                        null,                               /* Control-@ */
-                        Operation.SELF_INSERT,              /* Control-A */
-                        Operation.SELF_INSERT,              /* Control-B */
-                        Operation.SELF_INSERT,              /* Control-C */
-                        Operation.VI_EOF_MAYBE,             /* Control-D */
-                        Operation.SELF_INSERT,              /* Control-E */
-                        Operation.SELF_INSERT,              /* Control-F */
-                        Operation.SELF_INSERT,              /* Control-G */
-                        Operation.BACKWARD_DELETE_CHAR,     /* Control-H */
-                        Operation.COMPLETE,                 /* Control-I */
-                        Operation.ACCEPT_LINE,              /* Control-J */
-                        Operation.SELF_INSERT,              /* Control-K */
-                        Operation.SELF_INSERT,              /* Control-L */
-                        Operation.ACCEPT_LINE,              /* Control-M */
-                        Operation.MENU_COMPLETE,            /* Control-N */
-                        Operation.SELF_INSERT,              /* Control-O */
-                        Operation.MENU_COMPLETE_BACKWARD,   /* Control-P */
-                        Operation.SELF_INSERT,              /* Control-Q */
-                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
-                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
-                        Operation.TRANSPOSE_CHARS,          /* Control-T */
-                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
-                        Operation.QUOTED_INSERT,            /* Control-V */
-                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
-                        Operation.SELF_INSERT,              /* Control-X */
-                        Operation.YANK,                     /* Control-Y */
-                        Operation.SELF_INSERT,              /* Control-Z */
-                        Operation.VI_MOVEMENT_MODE,         /* Control-[ */
-                        Operation.SELF_INSERT,              /* Control-\ */
-                        Operation.SELF_INSERT,              /* Control-] */
-                        Operation.SELF_INSERT,              /* Control-^ */
-                        Operation.UNDO,                     /* Control-_ */
-                };
-        System.arraycopy( ctrl, 0, map, 0, ctrl.length );
-        for (int i = 32; i < 256; i++) {
-            map[i] = Operation.SELF_INSERT;
-        }
-        map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
-        return new KeyMap(VI_INSERT, map);
-    }
-
-    public static KeyMap viMovement() {
-        Object[] map = new Object[KEYMAP_LENGTH];
-        Object[] low = new Object[] {
-                        // Control keys.
-                        null,                               /* Control-@ */
-                        null,                               /* Control-A */
-                        null,                               /* Control-B */
-                        Operation.INTERRUPT,                /* Control-C */
-                        /*
-                         * ^D is supposed to move down half a screen. In bash
-                         * appears to be ignored.
-                         */
-                        Operation.VI_EOF_MAYBE,             /* Control-D */
-                        Operation.EMACS_EDITING_MODE,       /* Control-E */
-                        null,                               /* Control-F */
-                        Operation.ABORT,                    /* Control-G */
-                        Operation.BACKWARD_CHAR,            /* Control-H */
-                        null,                               /* Control-I */
-                        Operation.VI_MOVE_ACCEPT_LINE,      /* Control-J */
-                        Operation.KILL_LINE,                /* Control-K */
-                        Operation.CLEAR_SCREEN,             /* Control-L */
-                        Operation.VI_MOVE_ACCEPT_LINE,      /* Control-M */
-                        Operation.VI_NEXT_HISTORY,          /* Control-N */
-                        null,                               /* Control-O */
-                        Operation.VI_PREVIOUS_HISTORY,      /* Control-P */
-                        /*
-                         * My testing with readline is the ^Q is ignored.
-                         * Maybe this should be null?
-                         */
-                        Operation.QUOTED_INSERT,            /* Control-Q */
-
-                        /*
-                         * TODO - Very broken.  While in forward/reverse
-                         * history search the VI keyset should go out the
-                         * window and we need to enter a very simple keymap.
-                         */
-                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
-                        /* TODO */
-                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
-                        Operation.TRANSPOSE_CHARS,          /* Control-T */
-                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
-                        /* TODO */
-                        Operation.QUOTED_INSERT,            /* Control-V */
-                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
-                        null,                               /* Control-X */
-                        /* TODO */
-                        Operation.YANK,                     /* Control-Y */
-                        null,                               /* Control-Z */
-                        emacsMeta(),                        /* Control-[ */
-                        null,                               /* Control-\ */
-                        /* TODO */
-                        Operation.CHARACTER_SEARCH,         /* Control-] */
-                        null,                               /* Control-^ */
-                        /* TODO */
-                        Operation.UNDO,                     /* Control-_ */
-                        Operation.FORWARD_CHAR,             /* SPACE */
-                        null,                               /* ! */
-                        null,                               /* " */
-                        Operation.VI_INSERT_COMMENT,        /* # */
-                        Operation.END_OF_LINE,              /* $ */
-                        Operation.VI_MATCH,                 /* % */
-                        Operation.VI_TILDE_EXPAND,          /* & */
-                        null,                               /* ' */
-                        null,                               /* ( */
-                        null,                               /* ) */
-                        /* TODO */
-                        Operation.VI_COMPLETE,              /* * */
-                        Operation.VI_NEXT_HISTORY,          /* + */
-                        Operation.VI_CHAR_SEARCH,           /* , */
-                        Operation.VI_PREVIOUS_HISTORY,      /* - */
-                        /* TODO */
-                        Operation.VI_REDO,                  /* . */
-                        Operation.VI_SEARCH,                /* / */
-                        Operation.VI_BEGINNING_OF_LINE_OR_ARG_DIGIT, /* 0 */
-                        Operation.VI_ARG_DIGIT,             /* 1 */
-                        Operation.VI_ARG_DIGIT,             /* 2 */
-                        Operation.VI_ARG_DIGIT,             /* 3 */
-                        Operation.VI_ARG_DIGIT,             /* 4 */
-                        Operation.VI_ARG_DIGIT,             /* 5 */
-                        Operation.VI_ARG_DIGIT,             /* 6 */
-                        Operation.VI_ARG_DIGIT,             /* 7 */
-                        Operation.VI_ARG_DIGIT,             /* 8 */
-                        Operation.VI_ARG_DIGIT,             /* 9 */
-                        null,                               /* : */
-                        Operation.VI_CHAR_SEARCH,           /* ; */
-                        null,                               /* < */
-                        Operation.VI_COMPLETE,              /* = */
-                        null,                               /* > */
-                        Operation.VI_SEARCH,                /* ? */
-                        null,                               /* @ */
-                        Operation.VI_APPEND_EOL,            /* A */
-                        Operation.VI_PREV_WORD,             /* B */
-                        Operation.VI_CHANGE_TO_EOL,         /* C */
-                        Operation.VI_DELETE_TO_EOL,         /* D */
-                        Operation.VI_END_WORD,              /* E */
-                        Operation.VI_CHAR_SEARCH,           /* F */
-                        /* I need to read up on what this does */
-                        Operation.VI_FETCH_HISTORY,         /* G */
-                        null,                               /* H */
-                        Operation.VI_INSERT_BEG,            /* I */
-                        null,                               /* J */
-                        null,                               /* K */
-                        null,                               /* L */
-                        null,                               /* M */
-                        Operation.VI_SEARCH_AGAIN,          /* N */
-                        null,                               /* O */
-                        Operation.VI_PUT,                   /* P */
-                        null,                               /* Q */
-                        /* TODO */
-                        Operation.VI_REPLACE,               /* R */
-                        Operation.VI_KILL_WHOLE_LINE,       /* S */
-                        Operation.VI_CHAR_SEARCH,           /* T */
-                        /* TODO */
-                        Operation.REVERT_LINE,              /* U */
-                        null,                               /* V */
-                        Operation.VI_NEXT_WORD,             /* W */
-                        Operation.VI_RUBOUT,                /* X */
-                        Operation.VI_YANK_TO,               /* Y */
-                        null,                               /* Z */
-                        null,                               /* [ */
-                        Operation.VI_COMPLETE,              /* \ */
-                        null,                               /* ] */
-                        Operation.VI_FIRST_PRINT,           /* ^ */
-                        Operation.VI_YANK_ARG,              /* _ */
-                        Operation.VI_GOTO_MARK,             /* ` */
-                        Operation.VI_APPEND_MODE,           /* a */
-                        Operation.VI_PREV_WORD,             /* b */
-                        Operation.VI_CHANGE_TO,             /* c */
-                        Operation.VI_DELETE_TO,             /* d */
-                        Operation.VI_END_WORD,              /* e */
-                        Operation.VI_CHAR_SEARCH,           /* f */
-                        null,                               /* g */
-                        Operation.BACKWARD_CHAR,            /* h */
-                        Operation.VI_INSERTION_MODE,        /* i */
-                        Operation.NEXT_HISTORY,             /* j */
-                        Operation.PREVIOUS_HISTORY,         /* k */
-                        Operation.FORWARD_CHAR,             /* l */
-                        Operation.VI_SET_MARK,              /* m */
-                        Operation.VI_SEARCH_AGAIN,          /* n */
-                        null,                               /* o */
-                        Operation.VI_PUT,                   /* p */
-                        null,                               /* q */
-                        Operation.VI_CHANGE_CHAR,           /* r */
-                        Operation.VI_SUBST,                 /* s */
-                        Operation.VI_CHAR_SEARCH,           /* t */
-                        Operation.UNDO,                     /* u */
-                        null,                               /* v */
-                        Operation.VI_NEXT_WORD,             /* w */
-                        Operation.VI_DELETE,                /* x */
-                        Operation.VI_YANK_TO,               /* y */
-                        null,                               /* z */
-                        null,                               /* { */
-                        Operation.VI_COLUMN,                /* | */
-                        null,                               /* } */
-                        Operation.VI_CHANGE_CASE,           /* ~ */
-                        Operation.VI_DELETE                 /* DEL */
-                };
-        System.arraycopy( low, 0, map, 0, low.length );
-        for (int i = 128; i < 256; i++) {
-            map[i] = null;
-        }
-        return new KeyMap(VI_MOVE, map);
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * The kill ring class keeps killed text in a fixed size ring. In this
- * class we also keep record of whether or not the last command was a
- * kill or a yank. Depending on this, the class may behave
- * different. For instance, two consecutive kill-word commands fill
- * the same slot such that the next yank will return the two
- * previously killed words instead that only the last one. Likewise
- * yank pop requires that the previous command was either a yank or a
- * yank-pop.
- */
-public final class KillRing {
-
-    /**
-     * Default size is 60, like in emacs.
-     */
-    private static final int DEFAULT_SIZE = 60;
-
-    private final String[] slots;
-    private int head = 0;
-    private boolean lastKill = false;
-    private boolean lastYank = false;
-
-    /**
-     * Creates a new kill ring of the given size.
-     */
-    public KillRing(int size) {
-        slots = new String[size];
-    }
-
-    /**
-     * Creates a new kill ring of the default size. See {@link #DEFAULT_SIZE}.
-     */
-    public KillRing() {
-        this(DEFAULT_SIZE);
-    }
-
-    /**
-     * Resets the last-yank state.
-     */
-    public void resetLastYank() {
-        lastYank = false;
-    }
-
-    /**
-     * Resets the last-kill state.
-     */
-    public void resetLastKill() {
-        lastKill = false;
-    }
-
-    /**
-     * Returns {@code true} if the last command was a yank.
-     */
-    public boolean lastYank() {
-        return lastYank;
-    }
-
-    /**
-     * Adds the string to the kill-ring. Also sets lastYank to false
-     * and lastKill to true.
-     */
-    public void add(String str) {
-        lastYank = false;
-
-        if (lastKill) {
-            if (slots[head] != null) {
-                slots[head] += str;
-                return;
-            }
-        }
-
-        lastKill = true;
-        next();
-        slots[head] = str;
-    }
-
-    /**
-     * Adds the string to the kill-ring product of killing
-     * backwards. If the previous command was a kill text one then
-     * adds the text at the beginning of the previous kill to avoid
-     * that two consecutive backwards kills followed by a yank leaves
-     * things reversed.
-     */
-    public void addBackwards(String str) {
-        lastYank = false;
-
-        if (lastKill) {
-            if (slots[head] != null) {
-                slots[head] = str + slots[head];
-                return;
-            }
-        }
-
-        lastKill = true;
-        next();
-        slots[head] = str;
-    }
-
-    /**
-     * Yanks a previously killed text. Returns {@code null} if the
-     * ring is empty.
-     */
-    public String yank() {
-        lastKill = false;
-        lastYank = true;
-        return slots[head];
-    }
-
-    /**
-     * Moves the pointer to the current slot back and returns the text
-     * in that position. If the previous command was not yank returns
-     * null.
-     */
-    public String yankPop() {
-        lastKill = false;
-        if (lastYank) {
-            prev();
-            return slots[head];
-        }
-        return null;
-    }
-
-    /**
-     * Moves the pointer to the current slot forward. If the end of
-     * the slots is reached then points back to the beginning.
-     */
-    private void next() {
-        if (head == 0 && slots[0] == null) {
-            return;
-        }
-        head++;
-        if (head == slots.length) {
-            head = 0;
-        }
-    }
-
-    /**
-     * Moves the pointer to the current slot backwards. If the
-     * beginning of the slots is reached then traverses the slot
-     * backwards until one with not null content is found.
-     */
-    private void prev() {
-        head--;
-        if (head == -1) {
-            int x = slots.length - 1;
-            for (; x >= 0; x--) {
-                if (slots[x] != null) {
-                    break;
-                }
-            }
-            head = x;
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * List of all operations.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.6
- */
-public enum Operation {
-
-    ABORT,
-    ACCEPT_LINE,
-    ARROW_KEY_PREFIX,
-    BACKWARD_BYTE,
-    BACKWARD_CHAR,
-    BACKWARD_DELETE_CHAR,
-    BACKWARD_KILL_LINE,
-    BACKWARD_KILL_WORD,
-    BACKWARD_WORD,
-    BEGINNING_OF_HISTORY,
-    BEGINNING_OF_LINE,
-    CALL_LAST_KBD_MACRO,
-    CAPITALIZE_WORD,
-    CHARACTER_SEARCH,
-    CHARACTER_SEARCH_BACKWARD,
-    CLEAR_SCREEN,
-    COMPLETE,
-    COPY_BACKWARD_WORD,
-    COPY_FORWARD_WORD,
-    COPY_REGION_AS_KILL,
-    DELETE_CHAR,
-    DELETE_CHAR_OR_LIST,
-    DELETE_HORIZONTAL_SPACE,
-    DIGIT_ARGUMENT,
-    DO_LOWERCASE_VERSION,
-    DOWNCASE_WORD,
-    DUMP_FUNCTIONS,
-    DUMP_MACROS,
-    DUMP_VARIABLES,
-    EMACS_EDITING_MODE,
-    END_KBD_MACRO,
-    END_OF_HISTORY,
-    END_OF_LINE,
-    EXCHANGE_POINT_AND_MARK,
-    EXIT_OR_DELETE_CHAR,
-    FORWARD_BACKWARD_DELETE_CHAR,
-    FORWARD_BYTE,
-    FORWARD_CHAR,
-    FORWARD_SEARCH_HISTORY,
-    FORWARD_WORD,
-    HISTORY_SEARCH_BACKWARD,
-    HISTORY_SEARCH_FORWARD,
-    INSERT_CLOSE_CURLY,
-    INSERT_CLOSE_PAREN,
-    INSERT_CLOSE_SQUARE,
-    INSERT_COMMENT,
-    INSERT_COMPLETIONS,
-    INTERRUPT,
-    KILL_WHOLE_LINE,
-    KILL_LINE,
-    KILL_REGION,
-    KILL_WORD,
-    MENU_COMPLETE,
-    MENU_COMPLETE_BACKWARD,
-    NEXT_HISTORY,
-    NON_INCREMENTAL_FORWARD_SEARCH_HISTORY,
-    NON_INCREMENTAL_REVERSE_SEARCH_HISTORY,
-    NON_INCREMENTAL_FORWARD_SEARCH_HISTORY_AGAIN,
-    NON_INCREMENTAL_REVERSE_SEARCH_HISTORY_AGAIN,
-    OLD_MENU_COMPLETE,
-    OVERWRITE_MODE,
-    PASTE_FROM_CLIPBOARD,
-    POSSIBLE_COMPLETIONS,
-    PREVIOUS_HISTORY,
-    QUOTED_INSERT,
-    QUIT,
-    RE_READ_INIT_FILE,
-    REDRAW_CURRENT_LINE,
-    REVERSE_SEARCH_HISTORY,
-    REVERT_LINE,
-    SELF_INSERT,
-    SET_MARK,
-    SKIP_CSI_SEQUENCE,
-    START_KBD_MACRO,
-    TAB_INSERT,
-    TILDE_EXPAND,
-    TRANSPOSE_CHARS,
-    TRANSPOSE_WORDS,
-    TTY_STATUS,
-    UNDO,
-    UNIVERSAL_ARGUMENT,
-    UNIX_FILENAME_RUBOUT,
-    UNIX_LINE_DISCARD,
-    UNIX_WORD_RUBOUT,
-    UPCASE_WORD,
-    YANK,
-    YANK_LAST_ARG,
-    YANK_NTH_ARG,
-    YANK_POP,
-    VI_APPEND_EOL,
-    VI_APPEND_MODE,
-    VI_ARG_DIGIT,
-    VI_BACK_TO_INDENT,
-    VI_BACKWARD_BIGWORD,
-    VI_BACKWARD_WORD,
-    VI_BWORD,
-    VI_CHANGE_CASE,
-    VI_CHANGE_CHAR,
-    VI_CHANGE_TO,
-    VI_CHANGE_TO_EOL,
-    VI_CHAR_SEARCH,
-    VI_COLUMN,
-    VI_COMPLETE,
-    VI_DELETE,
-    VI_DELETE_TO,
-    VI_DELETE_TO_EOL,
-    VI_EDITING_MODE,
-    VI_END_BIGWORD,
-    VI_END_WORD,
-    VI_EOF_MAYBE,
-    VI_EWORD,
-    VI_FWORD,
-    VI_FETCH_HISTORY,
-    VI_FIRST_PRINT,
-    VI_FORWARD_BIGWORD,
-    VI_FORWARD_WORD,
-    VI_GOTO_MARK,
-    VI_INSERT_BEG,
-    VI_INSERTION_MODE,
-    VI_KILL_WHOLE_LINE,
-    VI_MATCH,
-    VI_MOVEMENT_MODE,
-    VI_NEXT_WORD,
-    VI_OVERSTRIKE,
-    VI_OVERSTRIKE_DELETE,
-    VI_PREV_WORD,
-    VI_PUT,
-    VI_REDO,
-    VI_REPLACE,
-    VI_RUBOUT,
-    VI_SEARCH,
-    VI_SEARCH_AGAIN,
-    VI_SET_MARK,
-    VI_SUBST,
-    VI_TILDE_EXPAND,
-    VI_YANK_ARG,
-    VI_YANK_TO,
-    VI_MOVE_ACCEPT_LINE,
-    VI_NEXT_HISTORY,
-    VI_PREVIOUS_HISTORY,
-    VI_INSERT_COMMENT,
-    VI_BEGINNING_OF_LINE_OR_ARG_DIGIT,
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-/**
- * This exception is thrown by {@link ConsoleReader#readLine} when
- * user interrupt handling is enabled and the user types the
- * interrupt character (ctrl-C). The partially entered line is
- * available via the {@link #getPartialLine()} method.
- */
-public class UserInterruptException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 6172232572140736750L;
-
-    private final String partialLine;
-
-    public UserInterruptException(String partialLine)
-    {
-        this.partialLine = partialLine;
-    }
-
-    /**
-     * @return the partially entered line when ctrl-C was pressed
-     */
-    public String getPartialLine()
-    {
-        return partialLine;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/WCWidth.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console;
-
-public class WCWidth {
-
-    /* The following two functions define the column width of an ISO 10646
-     * character as follows:
-     *
-     *    - The null character (U+0000) has a column width of 0.
-     *
-     *    - Other C0/C1 control characters and DEL will lead to a return
-     *      value of -1.
-     *
-     *    - Non-spacing and enclosing combining characters (general
-     *      category code Mn or Me in the Unicode database) have a
-     *      column width of 0.
-     *
-     *    - SOFT HYPHEN (U+00AD) has a column width of 1.
-     *
-     *    - Other format characters (general category code Cf in the Unicode
-     *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
-     *
-     *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
-     *      have a column width of 0.
-     *
-     *    - Spacing characters in the East Asian Wide (W) or East Asian
-     *      Full-width (F) category as defined in Unicode Technical
-     *      Report #11 have a column width of 2.
-     *
-     *    - All remaining characters (including all printable
-     *      ISO 8859-1 and WGL4 characters, Unicode control characters,
-     *      etc.) have a column width of 1.
-     *
-     * This implementation assumes that wchar_t characters are encoded
-     * in ISO 10646.
-     */
-    public static int wcwidth(int ucs)
-    {
-
-        /* test for 8-bit control characters */
-        if (ucs == 0)
-            return 0;
-        if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
-            return -1;
-
-        /* binary search in table of non-spacing characters */
-        if (bisearch(ucs, combining, combining.length - 1))
-            return 0;
-
-        /* if we arrive here, ucs is not a combining or C0/C1 control character */
-        return 1 +
-                ((ucs >= 0x1100 &&
-                        (ucs <= 0x115f ||                           /* Hangul Jamo init. consonants */
-                                ucs == 0x2329 || ucs == 0x232a ||
-                                (ucs >= 0x2e80 && ucs <= 0xa4cf &&
-                                        ucs != 0x303f) ||           /* CJK ... Yi */
-                                (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
-                                (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
-                                (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
-                                (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
-                                (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
-                                (ucs >= 0xffe0 && ucs <= 0xffe6) ||
-                                (ucs >= 0x20000 && ucs <= 0x2fffd) ||
-                                (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0);
-    }
-
-    /* sorted list of non-overlapping intervals of non-spacing characters */
-    /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
-    static Interval[] combining = {
-            new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ),
-            new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ),
-            new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ),
-            new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ),
-            new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ),
-            new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ),
-            new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ),
-            new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ),
-            new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ),
-            new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ),
-            new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ),
-            new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ),
-            new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ),
-            new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ),
-            new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ),
-            new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ),
-            new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ),
-            new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ),
-            new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ),
-            new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ),
-            new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ),
-            new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ),
-            new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ),
-            new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ),
-            new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ),
-            new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ),
-            new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ),
-            new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ),
-            new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ),
-            new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ),
-            new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ),
-            new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ),
-            new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ),
-            new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ),
-            new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ),
-            new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ),
-            new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ),
-            new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ),
-            new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ),
-            new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ),
-            new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ),
-            new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ),
-            new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ),
-            new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ),
-            new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ),
-            new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ),
-            new Interval( 0x1D242, 0x1D244 ), new Interval( 0xE0001, 0xE0001 ), new Interval( 0xE0020, 0xE007F ),
-            new Interval( 0xE0100, 0xE01EF )
-    };
-
-    private static class Interval {
-        public final int first;
-        public final int last;
-
-        public Interval(int first, int last) {
-            this.first = first;
-            this.last = last;
-        }
-    }
-
-    /* auxiliary function for binary search in interval table */
-    private static boolean bisearch(int ucs, Interval[] table, int max) {
-        int min = 0;
-        int mid;
-
-        if (ucs < table[0].first || ucs > table[max].last)
-            return false;
-        while (max >= min) {
-            mid = (min + max) / 2;
-            if (ucs > table[mid].last)
-                min = mid + 1;
-            else if (ucs < table[mid].first)
-                max = mid - 1;
-            else
-                return true;
-        }
-
-        return false;
-    }
-
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer which contains multiple completers and aggregates them together.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class AggregateCompleter
-    implements Completer
-{
-    private final List<Completer> completers = new ArrayList<Completer>();
-
-    public AggregateCompleter() {
-        // empty
-    }
-
-    /**
-     * Construct an AggregateCompleter with the given collection of completers.
-     * The completers will be used in the iteration order of the collection.
-     *
-     * @param completers the collection of completers
-     */
-    public AggregateCompleter(final Collection<Completer> completers) {
-        checkNotNull(completers);
-        this.completers.addAll(completers);
-    }
-
-    /**
-     * Construct an AggregateCompleter with the given completers.
-     * The completers will be used in the order given.
-     *
-     * @param completers the completers
-     */
-    public AggregateCompleter(final Completer... completers) {
-        this(Arrays.asList(completers));
-    }
-
-    /**
-     * Retrieve the collection of completers currently being aggregated.
-     *
-     * @return the aggregated completers
-     */
-    public Collection<Completer> getCompleters() {
-        return completers;
-    }
-
-    /**
-     * Perform a completion operation across all aggregated completers.
-     *
-     * @see Completer#complete(String, int, java.util.List)
-     * @return the highest completion return value from all completers
-     */
-    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-        // buffer could be null
-        checkNotNull(candidates);
-
-        List<Completion> completions = new ArrayList<Completion>(completers.size());
-
-        // Run each completer, saving its completion results
-        int max = -1;
-        for (Completer completer : completers) {
-            Completion completion = new Completion(candidates);
-            completion.complete(completer, buffer, cursor);
-
-            // Compute the max cursor position
-            max = Math.max(max, completion.cursor);
-
-            completions.add(completion);
-        }
-
-        // Append candidates from completions which have the same cursor position as max
-        for (Completion completion : completions) {
-            if (completion.cursor == max) {
-                candidates.addAll(completion.candidates);
-            }
-        }
-
-        return max;
-    }
-
-    /**
-     * @return a string representing the aggregated completers
-     */
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "{" +
-            "completers=" + completers +
-            '}';
-    }
-
-    private class Completion
-    {
-        public final List<CharSequence> candidates;
-
-        public int cursor;
-
-        public Completion(final List<CharSequence> candidates) {
-            checkNotNull(candidates);
-            this.candidates = new LinkedList<CharSequence>(candidates);
-        }
-
-        public void complete(final Completer completer, final String buffer, final int cursor) {
-            checkNotNull(completer);
-            this.cursor = completer.complete(buffer, cursor, candidates);
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AnsiStringsCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import jdk.internal.jline.internal.Ansi;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer for a set of strings.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class AnsiStringsCompleter
-    implements Completer
-{
-    private final SortedMap<String, String> strings = new TreeMap<String, String>();
-
-    public AnsiStringsCompleter() {
-        // empty
-    }
-
-    public AnsiStringsCompleter(final Collection<String> strings) {
-        checkNotNull(strings);
-        for (String str : strings) {
-            this.strings.put(Ansi.stripAnsi(str), str);
-        }
-    }
-
-    public AnsiStringsCompleter(final String... strings) {
-        this(Arrays.asList(strings));
-    }
-
-    public Collection<String> getStrings() {
-        return strings.values();
-    }
-
-    public int complete(String buffer, final int cursor, final List<CharSequence> candidates) {
-        // buffer could be null
-        checkNotNull(candidates);
-
-        if (buffer == null) {
-            candidates.addAll(strings.values());
-        }
-        else {
-            buffer = Ansi.stripAnsi(buffer);
-            for (Map.Entry<String, String> match : strings.tailMap(buffer).entrySet()) {
-                if (!match.getKey().startsWith(buffer)) {
-                    break;
-                }
-
-                candidates.add(match.getValue());
-            }
-        }
-
-        return candidates.isEmpty() ? -1 : 0;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.internal.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A {@link Completer} implementation that invokes a child completer using the appropriate <i>separator</i> argument.
- * This can be used instead of the individual completers having to know about argument parsing semantics.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class ArgumentCompleter
-    implements Completer
-{
-    private final ArgumentDelimiter delimiter;
-
-    private final List<Completer> completers = new ArrayList<Completer>();
-
-    private boolean strict = true;
-
-    /**
-     * Create a new completer with the specified argument delimiter.
-     *
-     * @param delimiter     The delimiter for parsing arguments
-     * @param completers    The embedded completers
-     */
-    public ArgumentCompleter(final ArgumentDelimiter delimiter, final Collection<Completer> completers) {
-        this.delimiter = checkNotNull(delimiter);
-        checkNotNull(completers);
-        this.completers.addAll(completers);
-    }
-
-    /**
-     * Create a new completer with the specified argument delimiter.
-     *
-     * @param delimiter     The delimiter for parsing arguments
-     * @param completers    The embedded completers
-     */
-    public ArgumentCompleter(final ArgumentDelimiter delimiter, final Completer... completers) {
-        this(delimiter, Arrays.asList(completers));
-    }
-
-    /**
-     * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
-     *
-     * @param completers    The embedded completers
-     */
-    public ArgumentCompleter(final Completer... completers) {
-        this(new WhitespaceArgumentDelimiter(), completers);
-    }
-
-    /**
-     * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
-     *
-     * @param completers    The embedded completers
-     */
-    public ArgumentCompleter(final List<Completer> completers) {
-        this(new WhitespaceArgumentDelimiter(), completers);
-    }
-
-    /**
-     * If true, a completion at argument index N will only succeed
-     * if all the completions from 0-(N-1) also succeed.
-     */
-    public void setStrict(final boolean strict) {
-        this.strict = strict;
-    }
-
-    /**
-     * Returns whether a completion at argument index N will success
-     * if all the completions from arguments 0-(N-1) also succeed.
-     *
-     * @return  True if strict.
-     * @since 2.3
-     */
-    public boolean isStrict() {
-        return this.strict;
-    }
-
-    /**
-     * @since 2.3
-     */
-    public ArgumentDelimiter getDelimiter() {
-        return delimiter;
-    }
-
-    /**
-     * @since 2.3
-     */
-    public List<Completer> getCompleters() {
-        return completers;
-    }
-
-    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-        // buffer can be null
-        checkNotNull(candidates);
-
-        ArgumentDelimiter delim = getDelimiter();
-        ArgumentList list = delim.delimit(buffer, cursor);
-        int argpos = list.getArgumentPosition();
-        int argIndex = list.getCursorArgumentIndex();
-
-        if (argIndex < 0) {
-            return -1;
-        }
-
-        List<Completer> completers = getCompleters();
-        Completer completer;
-
-        // if we are beyond the end of the completers, just use the last one
-        if (argIndex >= completers.size()) {
-            completer = completers.get(completers.size() - 1);
-        }
-        else {
-            completer = completers.get(argIndex);
-        }
-
-        // ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
-        for (int i = 0; isStrict() && (i < argIndex); i++) {
-            Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i);
-            String[] args = list.getArguments();
-            String arg = (args == null || i >= args.length) ? "" : args[i];
-
-            List<CharSequence> subCandidates = new LinkedList<CharSequence>();
-
-            if (sub.complete(arg, arg.length(), subCandidates) == -1) {
-                return -1;
-            }
-
-            if (!subCandidates.contains(arg)) {
-                return -1;
-            }
-        }
-
-        int ret = completer.complete(list.getCursorArgument(), argpos, candidates);
-
-        if (ret == -1) {
-            return -1;
-        }
-
-        int pos = ret + list.getBufferPosition() - argpos;
-
-        // Special case: when completing in the middle of a line, and the area under the cursor is a delimiter,
-        // then trim any delimiters from the candidates, since we do not need to have an extra delimiter.
-        //
-        // E.g., if we have a completion for "foo", and we enter "f bar" into the buffer, and move to after the "f"
-        // and hit TAB, we want "foo bar" instead of "foo  bar".
-
-        if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
-            for (int i = 0; i < candidates.size(); i++) {
-                CharSequence val = candidates.get(i);
-
-                while (val.length() > 0 && delim.isDelimiter(val, val.length() - 1)) {
-                    val = val.subSequence(0, val.length() - 1);
-                }
-
-                candidates.set(i, val);
-            }
-        }
-
-        Log.trace("Completing ", buffer, " (pos=", cursor, ") with: ", candidates, ": offset=", pos);
-
-        return pos;
-    }
-
-    /**
-     * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom breaking up of a {@link String} into individual
-     * arguments in order to dispatch the arguments to the nested {@link Completer}.
-     *
-     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
-     */
-    public static interface ArgumentDelimiter
-    {
-        /**
-         * Break the specified buffer into individual tokens that can be completed on their own.
-         *
-         * @param buffer    The buffer to split
-         * @param pos       The current position of the cursor in the buffer
-         * @return          The tokens
-         */
-        ArgumentList delimit(CharSequence buffer, int pos);
-
-        /**
-         * Returns true if the specified character is a whitespace parameter.
-         *
-         * @param buffer    The complete command buffer
-         * @param pos       The index of the character in the buffer
-         * @return          True if the character should be a delimiter
-         */
-        boolean isDelimiter(CharSequence buffer, int pos);
-    }
-
-    /**
-     * Abstract implementation of a delimiter that uses the {@link #isDelimiter} method to determine if a particular
-     * character should be used as a delimiter.
-     *
-     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
-     */
-    public abstract static class AbstractArgumentDelimiter
-        implements ArgumentDelimiter
-    {
-        private char[] quoteChars = {'\'', '"'};
-
-        private char[] escapeChars = {'\\'};
-
-        public void setQuoteChars(final char[] chars) {
-            this.quoteChars = chars;
-        }
-
-        public char[] getQuoteChars() {
-            return this.quoteChars;
-        }
-
-        public void setEscapeChars(final char[] chars) {
-            this.escapeChars = chars;
-        }
-
-        public char[] getEscapeChars() {
-            return this.escapeChars;
-        }
-
-        public ArgumentList delimit(final CharSequence buffer, final int cursor) {
-            List<String> args = new LinkedList<String>();
-            StringBuilder arg = new StringBuilder();
-            int argpos = -1;
-            int bindex = -1;
-            int quoteStart = -1;
-
-            for (int i = 0; (buffer != null) && (i < buffer.length()); i++) {
-                // once we reach the cursor, set the
-                // position of the selected index
-                if (i == cursor) {
-                    bindex = args.size();
-                    // the position in the current argument is just the
-                    // length of the current argument
-                    argpos = arg.length();
-                }
-
-                if (quoteStart < 0 && isQuoteChar(buffer, i)) {
-                    // Start a quote block
-                    quoteStart = i;
-                } else if (quoteStart >= 0) {
-                    // In a quote block
-                    if (buffer.charAt(quoteStart) == buffer.charAt(i) && !isEscaped(buffer, i)) {
-                        // End the block; arg could be empty, but that's fine
-                        args.add(arg.toString());
-                        arg.setLength(0);
-                        quoteStart = -1;
-                    } else if (!isEscapeChar(buffer, i)) {
-                        // Take the next character
-                        arg.append(buffer.charAt(i));
-                    }
-                } else {
-                    // Not in a quote block
-                    if (isDelimiter(buffer, i)) {
-                        if (arg.length() > 0) {
-                            args.add(arg.toString());
-                            arg.setLength(0); // reset the arg
-                        }
-                    } else if (!isEscapeChar(buffer, i)) {
-                        arg.append(buffer.charAt(i));
-                    }
-                }
-            }
-
-            if (cursor == buffer.length()) {
-                bindex = args.size();
-                // the position in the current argument is just the
-                // length of the current argument
-                argpos = arg.length();
-            }
-            if (arg.length() > 0) {
-                args.add(arg.toString());
-            }
-
-            return new ArgumentList(args.toArray(new String[args.size()]), bindex, argpos, cursor);
-        }
-
-        /**
-         * Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not
-         * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and
-         * returns true from {@link #isDelimiterChar}.
-         *
-         * @param buffer    The complete command buffer
-         * @param pos       The index of the character in the buffer
-         * @return          True if the character should be a delimiter
-         */
-        public boolean isDelimiter(final CharSequence buffer, final int pos) {
-            return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
-        }
-
-        public boolean isQuoted(final CharSequence buffer, final int pos) {
-            return false;
-        }
-
-        public boolean isQuoteChar(final CharSequence buffer, final int pos) {
-            if (pos < 0) {
-                return false;
-            }
-
-            for (int i = 0; (quoteChars != null) && (i < quoteChars.length); i++) {
-                if (buffer.charAt(pos) == quoteChars[i]) {
-                    return !isEscaped(buffer, pos);
-                }
-            }
-
-            return false;
-        }
-
-        /**
-         * Check if this character is a valid escape char (i.e. one that has not been escaped)
-         */
-        public boolean isEscapeChar(final CharSequence buffer, final int pos) {
-            if (pos < 0) {
-                return false;
-            }
-
-            for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) {
-                if (buffer.charAt(pos) == escapeChars[i]) {
-                    return !isEscaped(buffer, pos); // escape escape
-                }
-            }
-
-            return false;
-        }
-
-        /**
-         * Check if a character is escaped (i.e. if the previous character is an escape)
-         *
-         * @param buffer
-         *          the buffer to check in
-         * @param pos
-         *          the position of the character to check
-         * @return true if the character at the specified position in the given buffer is an escape character and the character immediately preceding it is not an
-         *         escape character.
-         */
-        public boolean isEscaped(final CharSequence buffer, final int pos) {
-            if (pos <= 0) {
-                return false;
-            }
-
-            return isEscapeChar(buffer, pos - 1);
-        }
-
-        /**
-         * Returns true if the character at the specified position if a delimiter. This method will only be called if
-         * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the
-         * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
-         */
-        public abstract boolean isDelimiterChar(CharSequence buffer, int pos);
-    }
-
-    /**
-     * {@link ArgumentCompleter.ArgumentDelimiter} implementation that counts all whitespace (as reported by
-     * {@link Character#isWhitespace}) as being a delimiter.
-     *
-     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
-     */
-    public static class WhitespaceArgumentDelimiter
-        extends AbstractArgumentDelimiter
-    {
-        /**
-         * The character is a delimiter if it is whitespace, and the
-         * preceding character is not an escape character.
-         */
-        @Override
-        public boolean isDelimiterChar(final CharSequence buffer, final int pos) {
-            return Character.isWhitespace(buffer.charAt(pos));
-        }
-    }
-
-    /**
-     * The result of a delimited buffer.
-     *
-     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
-     */
-    public static class ArgumentList
-    {
-        private String[] arguments;
-
-        private int cursorArgumentIndex;
-
-        private int argumentPosition;
-
-        private int bufferPosition;
-
-        /**
-         * @param arguments             The array of tokens
-         * @param cursorArgumentIndex   The token index of the cursor
-         * @param argumentPosition      The position of the cursor in the current token
-         * @param bufferPosition        The position of the cursor in the whole buffer
-         */
-        public ArgumentList(final String[] arguments, final int cursorArgumentIndex, final int argumentPosition, final int bufferPosition) {
-            this.arguments = checkNotNull(arguments);
-            this.cursorArgumentIndex = cursorArgumentIndex;
-            this.argumentPosition = argumentPosition;
-            this.bufferPosition = bufferPosition;
-        }
-
-        public void setCursorArgumentIndex(final int i) {
-            this.cursorArgumentIndex = i;
-        }
-
-        public int getCursorArgumentIndex() {
-            return this.cursorArgumentIndex;
-        }
-
-        public String getCursorArgument() {
-            if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) {
-                return null;
-            }
-
-            return arguments[cursorArgumentIndex];
-        }
-
-        public void setArgumentPosition(final int pos) {
-            this.argumentPosition = pos;
-        }
-
-        public int getArgumentPosition() {
-            return this.argumentPosition;
-        }
-
-        public void setArguments(final String[] arguments) {
-            this.arguments = arguments;
-        }
-
-        public String[] getArguments() {
-            return this.arguments;
-        }
-
-        public void setBufferPosition(final int pos) {
-            this.bufferPosition = pos;
-        }
-
-        public int getBufferPosition() {
-            return this.bufferPosition;
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.CursorBuffer;
-import jdk.internal.jline.internal.Ansi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-/**
- * A {@link CompletionHandler} that deals with multiple distinct completions
- * by outputting the complete list of possibilities to the console. This
- * mimics the behavior of the
- * <a href="http://www.gnu.org/directory/readline.html">readline</a> library.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class CandidateListCompletionHandler
-    implements CompletionHandler
-{
-    private boolean printSpaceAfterFullCompletion = true;
-    private boolean stripAnsi;
-
-    public boolean getPrintSpaceAfterFullCompletion() {
-        return printSpaceAfterFullCompletion;
-    }
-
-    public void setPrintSpaceAfterFullCompletion(boolean printSpaceAfterFullCompletion) {
-        this.printSpaceAfterFullCompletion = printSpaceAfterFullCompletion;
-    }
-
-    public boolean isStripAnsi() {
-        return stripAnsi;
-    }
-
-    public void setStripAnsi(boolean stripAnsi) {
-        this.stripAnsi = stripAnsi;
-    }
-
-    // TODO: handle quotes and escaped quotes && enable automatic escaping of whitespace
-
-    public boolean complete(final ConsoleReader reader, final List<CharSequence> candidates, final int pos) throws
-        IOException
-    {
-        CursorBuffer buf = reader.getCursorBuffer();
-
-        // if there is only one completion, then fill in the buffer
-        if (candidates.size() == 1) {
-            String value = Ansi.stripAnsi(candidates.get(0).toString());
-
-            if (buf.cursor == buf.buffer.length()
-                    && printSpaceAfterFullCompletion
-                    && !value.endsWith(" ")) {
-                value += " ";
-            }
-
-            // fail if the only candidate is the same as the current buffer
-            if (value.equals(buf.toString())) {
-                return false;
-            }
-
-            setBuffer(reader, value, pos);
-
-            return true;
-        }
-        else if (candidates.size() > 1) {
-            String value = getUnambiguousCompletions(candidates);
-            setBuffer(reader, value, pos);
-        }
-
-        printCandidates(reader, candidates);
-
-        // redraw the current console buffer
-        reader.drawLine();
-
-        return true;
-    }
-
-    public static void setBuffer(final ConsoleReader reader, final CharSequence value, final int offset) throws
-        IOException
-    {
-        while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) {
-            // empty
-        }
-
-        reader.putString(value);
-        reader.setCursorPosition(offset + value.length());
-    }
-
-    /**
-     * Print out the candidates. If the size of the candidates is greater than the
-     * {@link ConsoleReader#getAutoprintThreshold}, they prompt with a warning.
-     *
-     * @param candidates the list of candidates to print
-     */
-    public static void printCandidates(final ConsoleReader reader, Collection<CharSequence> candidates) throws
-        IOException
-    {
-        Set<CharSequence> distinct = new HashSet<CharSequence>(candidates);
-
-        if (distinct.size() > reader.getAutoprintThreshold()) {
-            //noinspection StringConcatenation
-            reader.println();
-            reader.print(Messages.DISPLAY_CANDIDATES.format(distinct.size()));
-            reader.flush();
-
-            int c;
-
-            String noOpt = Messages.DISPLAY_CANDIDATES_NO.format();
-            String yesOpt = Messages.DISPLAY_CANDIDATES_YES.format();
-            char[] allowed = {yesOpt.charAt(0), noOpt.charAt(0)};
-
-            while ((c = reader.readCharacter(allowed)) != -1) {
-                String tmp = new String(new char[]{(char) c});
-
-                if (noOpt.startsWith(tmp)) {
-                    reader.println();
-                    return;
-                }
-                else if (yesOpt.startsWith(tmp)) {
-                    break;
-                }
-                else {
-                    reader.beep();
-                }
-            }
-        }
-
-        // copy the values and make them distinct, without otherwise affecting the ordering. Only do it if the sizes differ.
-        if (distinct.size() != candidates.size()) {
-            Collection<CharSequence> copy = new ArrayList<CharSequence>();
-
-            for (CharSequence next : candidates) {
-                if (!copy.contains(next)) {
-                    copy.add(next);
-                }
-            }
-
-            candidates = copy;
-        }
-
-        reader.println();
-        reader.printColumns(candidates);
-    }
-
-    /**
-     * Returns a root that matches all the {@link String} elements of the specified {@link List},
-     * or null if there are no commonalities. For example, if the list contains
-     * <i>foobar</i>, <i>foobaz</i>, <i>foobuz</i>, the method will return <i>foob</i>.
-     */
-    private String getUnambiguousCompletions(final List<CharSequence> candidates) {
-        if (candidates == null || candidates.isEmpty()) {
-            return null;
-        }
-
-        if (candidates.size() == 1) {
-            return candidates.get(0).toString();
-        }
-
-        // convert to an array for speed
-        String first = null;
-        String[] strings = new String[candidates.size() - 1];
-        for (int i = 0; i < candidates.size(); i++) {
-            String str = candidates.get(i).toString();
-            if (stripAnsi) {
-                str = Ansi.stripAnsi(str);
-            }
-            if (first == null) {
-                first = str;
-            } else {
-                strings[i - 1] = str;
-            }
-        }
-
-        StringBuilder candidate = new StringBuilder();
-
-        for (int i = 0; i < first.length(); i++) {
-            if (startsWith(first.substring(0, i + 1), strings)) {
-                candidate.append(first.charAt(i));
-            }
-            else {
-                break;
-            }
-        }
-
-        return candidate.toString();
-    }
-
-    /**
-     * @return true is all the elements of <i>candidates</i> start with <i>starts</i>
-     */
-    private static boolean startsWith(final String starts, final String[] candidates) {
-        for (String candidate : candidates) {
-            if (!candidate.toLowerCase().startsWith(starts.toLowerCase())) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private static enum Messages
-    {
-        DISPLAY_CANDIDATES,
-        DISPLAY_CANDIDATES_YES,
-        DISPLAY_CANDIDATES_NO,;
-
-        private static final
-        ResourceBundle
-            bundle =
-            ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
-
-        public String format(final Object... args) {
-            if (bundle == null)
-                return "";
-            else
-                return String.format(bundle.getString(name()), args);
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#
-# Copyright (c) 2002-2016, the original author or authors.
-#
-# This software is distributable under the BSD license. See the terms of the
-# BSD license in the documentation provided with this software.
-#
-# http://www.opensource.org/licenses/bsd-license.php
-#
-
-DISPLAY_CANDIDATES=Display all %d possibilities? (y or n)
-DISPLAY_CANDIDATES_YES=y
-DISPLAY_CANDIDATES_NO=n
-DISPLAY_MORE=--More--
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.List;
-
-/**
- * A completer is the mechanism by which tab-completion candidates will be resolved.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public interface Completer
-{
-    //
-    // FIXME: Check if we can use CharSequece for buffer?
-    //
-
-    /**
-     * Populates <i>candidates</i> with a list of possible completions for the <i>buffer</i>.
-     *
-     * The <i>candidates</i> list will not be sorted before being displayed to the user: thus, the
-     * complete method should sort the {@link List} before returning.
-     *
-     * @param buffer        The buffer
-     * @param cursor        The current position of the cursor in the <i>buffer</i>
-     * @param candidates    The {@link List} of candidates to populate
-     * @return              The index of the <i>buffer</i> for which the completion will be relative
-     */
-    int complete(String buffer, int cursor, List<CharSequence> candidates);
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.console.ConsoleReader;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Handler for dealing with candidates for tab-completion.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public interface CompletionHandler
-{
-    boolean complete(ConsoleReader reader, List<CharSequence> candidates, int position) throws IOException;
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * {@link Completer} for {@link Enum} names.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class EnumCompleter
-    extends StringsCompleter
-{
-    public EnumCompleter(Class<? extends Enum<?>> source) {
-        this(source, true);
-    }
-
-    public EnumCompleter(Class<? extends Enum<?>> source, boolean toLowerCase) {
-        checkNotNull(source);
-
-        for (Enum<?> n : source.getEnumConstants()) {
-            this.getStrings().add(toLowerCase ? n.name().toLowerCase() : n.name());
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import jdk.internal.jline.internal.Configuration;
-
-import java.io.File;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * A file name completer takes the buffer and issues a list of
- * potential completions.
- * <p/>
- * This completer tries to behave as similar as possible to
- * <i>bash</i>'s file name completion (using GNU readline)
- * with the following exceptions:
- * <p/>
- * <ul>
- * <li>Candidates that are directories will end with "/"</li>
- * <li>Wildcard regular expressions are not evaluated or replaced</li>
- * <li>The "~" character can be used to represent the user's home,
- * but it cannot complete to other users' homes, since java does
- * not provide any way of determining that easily</li>
- * </ul>
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class FileNameCompleter
-    implements Completer
-{
-    // TODO: Handle files with spaces in them
-
-    private static final boolean OS_IS_WINDOWS;
-
-    static {
-        String os = Configuration.getOsName();
-        OS_IS_WINDOWS = os.contains("windows");
-    }
-
-    public int complete(String buffer, final int cursor, final List<CharSequence> candidates) {
-        // buffer can be null
-        checkNotNull(candidates);
-
-        if (buffer == null) {
-            buffer = "";
-        }
-
-        if (OS_IS_WINDOWS) {
-            buffer = buffer.replace('/', '\\');
-        }
-
-        String translated = buffer;
-
-        File homeDir = getUserHome();
-
-        // Special character: ~ maps to the user's home directory
-        if (translated.startsWith("~" + separator())) {
-            translated = homeDir.getPath() + translated.substring(1);
-        }
-        else if (translated.startsWith("~")) {
-            translated = homeDir.getParentFile().getAbsolutePath();
-        }
-        else if (!(new File(translated).isAbsolute())) {
-            String cwd = getUserDir().getAbsolutePath();
-            translated = cwd + separator() + translated;
-        }
-
-        File file = new File(translated);
-        final File dir;
-
-        if (translated.endsWith(separator())) {
-            dir = file;
-        }
-        else {
-            dir = file.getParentFile();
-        }
-
-        File[] entries = dir == null ? new File[0] : dir.listFiles();
-
-        return matchFiles(buffer, translated, entries, candidates);
-    }
-
-    protected String separator() {
-        return File.separator;
-    }
-
-    protected File getUserHome() {
-        return Configuration.getUserHome();
-    }
-
-    protected File getUserDir() {
-        return new File(".");
-    }
-
-    protected int matchFiles(final String buffer, final String translated, final File[] files, final List<CharSequence> candidates) {
-        if (files == null) {
-            return -1;
-        }
-
-        int matches = 0;
-
-        // first pass: just count the matches
-        for (File file : files) {
-            if (file.getAbsolutePath().startsWith(translated)) {
-                matches++;
-            }
-        }
-        for (File file : files) {
-            if (file.getAbsolutePath().startsWith(translated)) {
-                CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " ");
-                candidates.add(render(file, name).toString());
-            }
-        }
-
-        final int index = buffer.lastIndexOf(separator());
-
-        return index + separator().length();
-    }
-
-    protected CharSequence render(final File file, final CharSequence name) {
-        return name;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.List;
-
-/**
- * Null completer.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public final class NullCompleter
-    implements Completer
-{
-    public static final NullCompleter INSTANCE = new NullCompleter();
-
-    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-        return -1;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Completer for a set of strings.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class StringsCompleter
-    implements Completer
-{
-    private final SortedSet<String> strings = new TreeSet<String>();
-
-    public StringsCompleter() {
-        // empty
-    }
-
-    public StringsCompleter(final Collection<String> strings) {
-        checkNotNull(strings);
-        getStrings().addAll(strings);
-    }
-
-    public StringsCompleter(final String... strings) {
-        this(Arrays.asList(strings));
-    }
-
-    public Collection<String> getStrings() {
-        return strings;
-    }
-
-    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-        // buffer could be null
-        checkNotNull(candidates);
-
-        if (buffer == null) {
-            candidates.addAll(strings);
-        }
-        else {
-            for (String match : strings.tailSet(buffer)) {
-                if (!match.startsWith(buffer)) {
-                    break;
-                }
-
-                candidates.add(match);
-            }
-        }
-
-        return candidates.isEmpty() ? -1 : 0;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * Console completer support.
- *
- * @since 2.3
- */
-package jdk.internal.jline.console.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.io.Reader;
-
-import jdk.internal.jline.internal.Log;
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * {@link History} using a file for persistent backing.
- * <p/>
- * Implementers should install shutdown hook to call {@link FileHistory#flush}
- * to save history to disk.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class FileHistory
-    extends MemoryHistory
-    implements PersistentHistory, Flushable
-{
-    private final File file;
-
-    /**
-     * Load a history file into memory, truncating to default max size.
-     */
-    public FileHistory(final File file) throws IOException {
-        this(file, true);
-    }
-
-    /**
-     * Create a FileHistory, but only initialize if doInit is true. This allows
-     * setting maxSize or other settings; call load() before using if doInit is
-     * false.
-     */
-    public FileHistory(final File file, final boolean doInit) throws IOException {
-        this.file = checkNotNull(file).getAbsoluteFile();
-        if (doInit) {
-            load();
-        }
-    }
-
-    /**
-     * Load history from file, e.g. if using delayed init.
-     */
-    public void load() throws IOException {
-        load(file);
-    }
-
-    public File getFile() {
-        return file;
-    }
-
-    public void load(final File file) throws IOException {
-        checkNotNull(file);
-        if (file.exists()) {
-            Log.trace("Loading history from: ", file);
-            FileReader reader = null;
-            try{
-                reader = new FileReader(file);
-                load(reader);
-            } finally{
-                if(reader != null){
-                    reader.close();
-                }
-            }
-        }
-    }
-
-    public void load(final InputStream input) throws IOException {
-        checkNotNull(input);
-        load(new InputStreamReader(input));
-    }
-
-    public void load(final Reader reader) throws IOException {
-        checkNotNull(reader);
-        BufferedReader input = new BufferedReader(reader);
-
-        String item;
-        while ((item = input.readLine()) != null) {
-            internalAdd(item);
-        }
-    }
-
-    public void flush() throws IOException {
-        Log.trace("Flushing history");
-
-        if (!file.exists()) {
-            File dir = file.getParentFile();
-            if (!dir.exists() && !dir.mkdirs()) {
-                Log.warn("Failed to create directory: ", dir);
-            }
-            if (!file.createNewFile()) {
-                Log.warn("Failed to create file: ", file);
-            }
-        }
-
-        PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
-        try {
-            for (Entry entry : this) {
-                out.println(entry.value());
-            }
-        }
-        finally {
-            out.close();
-        }
-    }
-
-    public void purge() throws IOException {
-        Log.trace("Purging history");
-
-        clear();
-
-        if (!file.delete()) {
-            Log.warn("Failed to delete history file: ", file);
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * Console history.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public interface History
-    extends Iterable<History.Entry>
-{
-    int size();
-
-    boolean isEmpty();
-
-    int index();
-
-    void clear();
-
-    CharSequence get(int index);
-
-    void add(CharSequence line);
-
-    /**
-     * Set the history item at the given index to the given CharSequence.
-     *
-     * @param index the index of the history offset
-     * @param item the new item
-     * @since 2.7
-     */
-    void set(int index, CharSequence item);
-
-    /**
-     * Remove the history element at the given index.
-     *
-     * @param i the index of the element to remove
-     * @return the removed element
-     * @since 2.7
-     */
-    CharSequence remove(int i);
-
-    /**
-     * Remove the first element from history.
-     *
-     * @return the removed element
-     * @since 2.7
-     */
-    CharSequence removeFirst();
-
-    /**
-     * Remove the last element from history
-     *
-     * @return the removed element
-     * @since 2.7
-     */
-    CharSequence removeLast();
-
-    void replace(CharSequence item);
-
-    //
-    // Entries
-    //
-
-    interface Entry
-    {
-        int index();
-
-        CharSequence value();
-    }
-
-    ListIterator<Entry> entries(int index);
-
-    ListIterator<Entry> entries();
-
-    Iterator<Entry> iterator();
-
-    //
-    // Navigation
-    //
-
-    CharSequence current();
-
-    boolean previous();
-
-    boolean next();
-
-    boolean moveToFirst();
-
-    boolean moveToLast();
-
-    boolean moveTo(int index);
-
-    void moveToEnd();
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Non-persistent {@link History}.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public class MemoryHistory
-    implements History
-{
-    public static final int DEFAULT_MAX_SIZE = 500;
-
-    private final LinkedList<CharSequence> items = new LinkedList<CharSequence>();
-
-    private int maxSize = DEFAULT_MAX_SIZE;
-
-    private boolean ignoreDuplicates = true;
-
-    private boolean autoTrim = false;
-
-    // NOTE: These are all ideas from looking at the Bash man page:
-
-    // TODO: Add ignore space? (lines starting with a space are ignored)
-
-    // TODO: Add ignore patterns?
-
-    // TODO: Add history timestamp?
-
-    // TODO: Add erase dups?
-
-    private int offset = 0;
-
-    private int index = 0;
-
-    public void setMaxSize(final int maxSize) {
-        this.maxSize = maxSize;
-        maybeResize();
-    }
-
-    public int getMaxSize() {
-        return maxSize;
-    }
-
-    public boolean isIgnoreDuplicates() {
-        return ignoreDuplicates;
-    }
-
-    public void setIgnoreDuplicates(final boolean flag) {
-        this.ignoreDuplicates = flag;
-    }
-
-    public boolean isAutoTrim() {
-        return autoTrim;
-    }
-
-    public void setAutoTrim(final boolean flag) {
-        this.autoTrim = flag;
-    }
-
-    public int size() {
-        return items.size();
-    }
-
-    public boolean isEmpty() {
-        return items.isEmpty();
-    }
-
-    public int index() {
-        return offset + index;
-    }
-
-    public void clear() {
-        items.clear();
-        offset = 0;
-        index = 0;
-    }
-
-    public CharSequence get(final int index) {
-        return items.get(index - offset);
-    }
-
-    public void set(int index, CharSequence item) {
-        items.set(index - offset, item);
-    }
-
-    public void add(CharSequence item) {
-        checkNotNull(item);
-
-        if (isAutoTrim()) {
-            item = String.valueOf(item).trim();
-        }
-
-        if (isIgnoreDuplicates()) {
-            if (!items.isEmpty() && item.equals(items.getLast())) {
-                return;
-            }
-        }
-
-        internalAdd(item);
-    }
-
-    public CharSequence remove(int i) {
-        return items.remove(i);
-    }
-
-    public CharSequence removeFirst() {
-        return items.removeFirst();
-    }
-
-    public CharSequence removeLast() {
-        return items.removeLast();
-    }
-
-    protected void internalAdd(CharSequence item) {
-        items.add(item);
-
-        maybeResize();
-    }
-
-    public void replace(final CharSequence item) {
-        items.removeLast();
-        add(item);
-    }
-
-    private void maybeResize() {
-        while (size() > getMaxSize()) {
-            items.removeFirst();
-            offset++;
-        }
-
-        index = size();
-    }
-
-    public ListIterator<Entry> entries(final int index) {
-        return new EntriesIterator(index - offset);
-    }
-
-    public ListIterator<Entry> entries() {
-        return entries(offset);
-    }
-
-    public Iterator<Entry> iterator() {
-        return entries();
-    }
-
-    private static class EntryImpl
-        implements Entry
-    {
-        private final int index;
-
-        private final CharSequence value;
-
-        public EntryImpl(int index, CharSequence value) {
-            this.index = index;
-            this.value = value;
-        }
-
-        public int index() {
-            return index;
-        }
-
-        public CharSequence value() {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return String.format("%d: %s", index, value);
-        }
-    }
-
-    private class EntriesIterator
-        implements ListIterator<Entry>
-    {
-        private final ListIterator<CharSequence> source;
-
-        private EntriesIterator(final int index) {
-            source = items.listIterator(index);
-        }
-
-        public Entry next() {
-            if (!source.hasNext()) {
-                throw new NoSuchElementException();
-            }
-            return new EntryImpl(offset + source.nextIndex(), source.next());
-        }
-
-        public Entry previous() {
-            if (!source.hasPrevious()) {
-                throw new NoSuchElementException();
-            }
-            return new EntryImpl(offset + source.previousIndex(), source.previous());
-        }
-
-        public int nextIndex() {
-            return offset + source.nextIndex();
-        }
-
-        public int previousIndex() {
-            return offset + source.previousIndex();
-        }
-
-        public boolean hasNext() {
-            return source.hasNext();
-        }
-
-        public boolean hasPrevious() {
-            return source.hasPrevious();
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        public void set(final Entry entry) {
-            throw new UnsupportedOperationException();
-        }
-
-        public void add(final Entry entry) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    //
-    // Navigation
-    //
-
-    /**
-     * This moves the history to the last entry. This entry is one position
-     * before the moveToEnd() position.
-     *
-     * @return Returns false if there were no history entries or the history
-     *         index was already at the last entry.
-     */
-    public boolean moveToLast() {
-        int lastEntry = size() - 1;
-        if (lastEntry >= 0 && lastEntry != index) {
-            index = size() - 1;
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Move to the specified index in the history
-     */
-    public boolean moveTo(int index) {
-        index -= offset;
-        if (index >= 0 && index < size() ) {
-            this.index = index;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Moves the history index to the first entry.
-     *
-     * @return Return false if there are no entries in the history or if the
-     *         history is already at the beginning.
-     */
-    public boolean moveToFirst() {
-        if (size() > 0 && index != 0) {
-            index = 0;
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Move to the end of the history buffer. This will be a blank entry, after
-     * all of the other entries.
-     */
-    public void moveToEnd() {
-        index = size();
-    }
-
-    /**
-     * Return the content of the current buffer.
-     */
-    public CharSequence current() {
-        if (index >= size()) {
-            return "";
-        }
-
-        return items.get(index);
-    }
-
-    /**
-     * Move the pointer to the previous element in the buffer.
-     *
-     * @return true if we successfully went to the previous element
-     */
-    public boolean previous() {
-        if (index <= 0) {
-            return false;
-        }
-
-        index--;
-
-        return true;
-    }
-
-    /**
-     * Move the pointer to the next element in the buffer.
-     *
-     * @return true if we successfully went to the next element
-     */
-    public boolean next() {
-        if (index >= size()) {
-            return false;
-        }
-
-        index++;
-
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        for (Entry e : this) {
-            sb.append(e.toString() + "\n");
-        }
-        return sb.toString();
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.history;
-
-import java.io.IOException;
-
-/**
- * Persistent {@link History}.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.3
- */
-public interface PersistentHistory
-    extends History
-{
-    /**
-     * Flush all items to persistent storage.
-     *
-     * @throws IOException  Flush failed
-     */
-    void flush() throws IOException;
-
-    /**
-     * Purge persistent storage and {@link #clear}.
-     *
-     * @throws IOException  Purge failed
-     */
-    void purge() throws IOException;
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * Console history support.
- *
- * @since 2.0
- */
-package jdk.internal.jline.console.history;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.internal;
-
-import jdk.internal.jline.console.ConsoleReader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
-import java.util.Enumeration;
-
-// FIXME: Clean up API and move to jline.console.runner package
-
-/**
- * An {@link InputStream} implementation that wraps a {@link ConsoleReader}.
- * It is useful for setting up the {@link System#in} for a generic console.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @since 2.7
- */
-class ConsoleReaderInputStream
-    extends SequenceInputStream
-{
-    private static InputStream systemIn = System.in;
-
-    public static void setIn() throws IOException {
-        setIn(new ConsoleReader());
-    }
-
-    public static void setIn(final ConsoleReader reader) {
-        System.setIn(new ConsoleReaderInputStream(reader));
-    }
-
-    /**
-     * Restore the original {@link System#in} input stream.
-     */
-    public static void restoreIn() {
-        System.setIn(systemIn);
-    }
-
-    public ConsoleReaderInputStream(final ConsoleReader reader) {
-        super(new ConsoleEnumeration(reader));
-    }
-
-    private static class ConsoleEnumeration
-        implements Enumeration<InputStream>
-    {
-        private final ConsoleReader reader;
-        private ConsoleLineInputStream next = null;
-        private ConsoleLineInputStream prev = null;
-
-        public ConsoleEnumeration(final ConsoleReader reader) {
-            this.reader = reader;
-        }
-
-        public InputStream nextElement() {
-            if (next != null) {
-                InputStream n = next;
-                prev = next;
-                next = null;
-
-                return n;
-            }
-
-            return new ConsoleLineInputStream(reader);
-        }
-
-        public boolean hasMoreElements() {
-            // the last line was null
-            if ((prev != null) && (prev.wasNull == true)) {
-                return false;
-            }
-
-            if (next == null) {
-                next = (ConsoleLineInputStream) nextElement();
-            }
-
-            return next != null;
-        }
-    }
-
-    private static class ConsoleLineInputStream
-        extends InputStream
-    {
-        private final ConsoleReader reader;
-        private String line = null;
-        private int index = 0;
-        private boolean eol = false;
-        protected boolean wasNull = false;
-
-        public ConsoleLineInputStream(final ConsoleReader reader) {
-            this.reader = reader;
-        }
-
-        public int read() throws IOException {
-            if (eol) {
-                return -1;
-            }
-
-            if (line == null) {
-                line = reader.readLine();
-            }
-
-            if (line == null) {
-                wasNull = true;
-                return -1;
-            }
-
-            if (index >= line.length()) {
-                eol = true;
-                return '\n'; // lines are ended with a newline
-            }
-
-            return line.charAt(index++);
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.console.internal;
-
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.completer.ArgumentCompleter;
-import jdk.internal.jline.console.completer.Completer;
-import jdk.internal.jline.console.history.FileHistory;
-import jdk.internal.jline.console.history.PersistentHistory;
-import jdk.internal.jline.internal.Configuration;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.StringTokenizer;
-
-// FIXME: Clean up API and move to jline.console.runner package
-
-/**
- * A pass-through application that sets the system input stream to a
- * {@link ConsoleReader} and invokes the specified main method.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @since 2.7
- */
-public class ConsoleRunner
-{
-    public static final String property = "jline.history";
-
-    // FIXME: This is really ugly... re-write this
-
-    public static void main(final String[] args) throws Exception {
-        List<String> argList = new ArrayList<String>(Arrays.asList(args));
-        if (argList.size() == 0) {
-            usage();
-            return;
-        }
-
-        String historyFileName = System.getProperty(ConsoleRunner.property, null);
-
-        String mainClass = argList.remove(0);
-        ConsoleReader reader = new ConsoleReader();
-
-        if (historyFileName != null) {
-            reader.setHistory(new FileHistory(new File(Configuration.getUserHome(),
-                String.format(".jline-%s.%s.history", mainClass, historyFileName))));
-        }
-        else {
-            reader.setHistory(new FileHistory(new File(Configuration.getUserHome(),
-                String.format(".jline-%s.history", mainClass))));
-        }
-
-        String completors = System.getProperty(ConsoleRunner.class.getName() + ".completers", "");
-        List<Completer> completorList = new ArrayList<Completer>();
-
-        for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) {
-            @SuppressWarnings("deprecation")
-            Object obj = Class.forName(tok.nextToken()).newInstance();
-            completorList.add((Completer) obj);
-        }
-
-        if (completorList.size() > 0) {
-            reader.addCompleter(new ArgumentCompleter(completorList));
-        }
-
-        ConsoleReaderInputStream.setIn(reader);
-
-        try {
-            Class<?> type = Class.forName(mainClass);
-            Method method = type.getMethod("main", String[].class);
-            String[] mainArgs = argList.toArray(new String[argList.size()]);
-            method.invoke(null, (Object) mainArgs);
-        }
-        finally {
-            // just in case this main method is called from another program
-            ConsoleReaderInputStream.restoreIn();
-            if (reader.getHistory() instanceof PersistentHistory) {
-                ((PersistentHistory) reader.getHistory()).flush();
-            }
-        }
-    }
-
-    private static void usage() {
-        System.out.println("Usage: \n   java " + "[-Djline.history='name'] "
-            + ConsoleRunner.class.getName()
-            + " <target class name> [args]"
-            + "\n\nThe -Djline.history option will avoid history"
-            + "\nmangling when running ConsoleRunner on the same application."
-            + "\n\nargs will be passed directly to the target class name.");
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * Console support.
- *
- * @since 2.0
- */
-package jdk.internal.jline.console;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/AnsiInterpretingOutputStream.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +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.  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 jdk.internal.jline.extra;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import jdk.internal.jline.internal.Ansi;
-
-/**A stream that interprets some escape code sequences, and ignores those it does not support.
- */
-public class AnsiInterpretingOutputStream extends OutputStream {
-    private final String encoding;
-    private final OutputStream out;
-    private final Performer performer;
-    private final Map<Character, AnsiCodeHandler> ESCAPE_CODE_ACTIONS = new HashMap<>();
-
-    private boolean inEscapeSequence;
-    private ByteArrayOutputStream escape = new ByteArrayOutputStream();
-
-    public AnsiInterpretingOutputStream(String encoding, OutputStream output, Performer performer) {
-        this.encoding = encoding;
-        this.out = output;
-        this.performer = performer;
-        ESCAPE_CODE_ACTIONS.put('A', code -> {
-            moveCursor(code, 0, -1);
-        });
-        ESCAPE_CODE_ACTIONS.put('B', code -> {
-            moveCursor(code, 0, +1);
-        });
-        ESCAPE_CODE_ACTIONS.put('C', code -> {
-            moveCursor(code, +1, 0);
-        });
-        ESCAPE_CODE_ACTIONS.put('D', code -> {
-            moveCursor(code, -1, 0);
-        });
-        ESCAPE_CODE_ACTIONS.put('K', code -> {
-            BufferState buffer = performer.getBufferState();
-            switch (parseOutIntValue(code, 0)) {
-                case 0:
-                    for (int i = buffer.cursorX; i < buffer.sizeX - 1; i++) {
-                        out.write(' ');
-                    }
-                    performer.setCursorPosition(buffer.cursorX, buffer.cursorY);
-                    break;
-                case 1:
-                    performer.setCursorPosition(0, buffer.cursorY);
-                    for (int i = 0; i < buffer.cursorX; i++) {
-                        out.write(' ');
-                    }
-                    break;
-                case 2:
-                    for (int i = 0; i < buffer.sizeX - 1; i++) {
-                        out.write(' ');
-                    }
-                    performer.setCursorPosition(buffer.cursorX, buffer.cursorY);
-                    break;
-            }
-            out.flush();
-        });
-    }
-
-    @Override
-    public void write(int d) throws IOException {
-        if (inEscapeSequence) {
-            escape.write(d);
-            String escapeCandidate = new String(escape.toByteArray(), encoding);
-            if (Ansi.ANSI_CODE_PATTERN.asPredicate().test(escapeCandidate)) {
-                //escape sequence:
-                char key = escapeCandidate.charAt(escapeCandidate.length() - 1);
-                AnsiCodeHandler handler =
-                        ESCAPE_CODE_ACTIONS.get(key);
-                if (handler != null) {
-                    handler.handle(escapeCandidate);
-                } else {
-                    //unknown escape sequence, ignore
-                }
-                inEscapeSequence = false;
-                escape = null;
-            }
-        } else if (d == '\033') {
-            inEscapeSequence = true;
-            escape = new ByteArrayOutputStream();
-            escape.write(d);
-        } else {
-            out.write(d);
-        }
-    }
-    @Override
-    public void flush() throws IOException {
-        out.flush();
-    }
-
-    private void moveCursor(String code, int dx, int dy) throws IOException {
-        int delta = parseOutIntValue(code, 1);
-        BufferState buffer = performer.getBufferState();
-        int tx = buffer.cursorX + dx * delta;
-        int ty = buffer.cursorY + dy * delta;
-
-        tx = Math.max(0, Math.min(buffer.sizeX - 1, tx));
-        ty = Math.max(0, Math.min(buffer.sizeY - 1, ty));
-
-        performer.setCursorPosition(tx, ty);
-    }
-
-    private int parseOutIntValue(String code, int def) {
-        try {
-            return Integer.parseInt(code.substring(code.indexOf('[') + 1, code.length() - 1));
-        } catch (NumberFormatException ex) {
-            return def;
-        }
-    }
-
-    interface AnsiCodeHandler {
-        public void handle(String code) throws IOException;
-    }
-
-    public interface Performer {
-        public BufferState getBufferState() throws IOException;
-        public void setCursorPosition(int cursorX, int cursorY) throws IOException;
-    }
-
-    public static class BufferState {
-        public final int cursorX;
-        public final int cursorY;
-        public final int sizeX;
-        public final int sizeY;
-
-        public BufferState(int cursorX, int cursorY, int sizeX, int sizeY) {
-            this.cursorX = cursorX;
-            this.cursorY = cursorY;
-            this.sizeX = sizeX;
-            this.sizeY = sizeY;
-        }
-
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,422 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 jdk.internal.jline.extra;
-
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.function.Supplier;
-
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.KeyMap;
-import jdk.internal.jline.console.history.History;
-import jdk.internal.jline.console.history.History.Entry;
-import jdk.internal.jline.console.history.MemoryHistory;
-
-/*Public for tests (HistoryTest).
- */
-public abstract class EditingHistory implements History {
-
-    private final History fullHistory;
-    private History currentDelegate;
-
-    protected EditingHistory(ConsoleReader in, Iterable<? extends String> originalHistory) {
-        MemoryHistory fullHistory = new MemoryHistory();
-        fullHistory.setIgnoreDuplicates(false);
-        this.fullHistory = fullHistory;
-        this.currentDelegate = fullHistory;
-        bind(in, CTRL_UP,
-             (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::previousSnippet));
-        bind(in, CTRL_DOWN,
-             (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::nextSnippet));
-        if (originalHistory != null) {
-            load(originalHistory);
-        }
-    }
-
-    private void moveHistoryToSnippet(ConsoleReader in, Supplier<Boolean> action) {
-        if (!action.get()) {
-            try {
-                in.beep();
-            } catch (IOException ex) {
-                throw new IllegalStateException(ex);
-            }
-        } else {
-            try {
-                //could use:
-                //in.resetPromptLine(in.getPrompt(), in.getHistory().current().toString(), -1);
-                //but that would mean more re-writing on the screen, (and prints an additional
-                //empty line), so using setBuffer directly:
-                Method setBuffer = ConsoleReader.class.getDeclaredMethod("setBuffer", String.class);
-
-                setBuffer.setAccessible(true);
-                setBuffer.invoke(in, in.getHistory().current().toString());
-                in.flush();
-            } catch (ReflectiveOperationException | IOException ex) {
-                throw new IllegalStateException(ex);
-            }
-        }
-    }
-
-    private void bind(ConsoleReader in, String shortcut, Object action) {
-        KeyMap km = in.getKeys();
-        for (int i = 0; i < shortcut.length(); i++) {
-            Object value = km.getBound(Character.toString(shortcut.charAt(i)));
-            if (value instanceof KeyMap) {
-                km = (KeyMap) value;
-            } else {
-                km.bind(shortcut.substring(i), action);
-            }
-        }
-    }
-
-    private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP
-    private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN
-
-    @Override
-    public int size() {
-        return currentDelegate.size();
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return currentDelegate.isEmpty();
-    }
-
-    @Override
-    public int index() {
-        return currentDelegate.index();
-    }
-
-    @Override
-    public void clear() {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        currentDelegate.clear();
-    }
-
-    @Override
-    public CharSequence get(int index) {
-        return currentDelegate.get(index);
-    }
-
-    @Override
-    public void add(CharSequence line) {
-        NarrowingHistoryLine currentLine = null;
-        int origIndex = fullHistory.index();
-        int fullSize;
-        try {
-            fullHistory.moveToEnd();
-            fullSize = fullHistory.index();
-            if (currentDelegate == fullHistory) {
-                if (origIndex < fullHistory.index()) {
-                    for (Entry entry : fullHistory) {
-                        if (!(entry.value() instanceof NarrowingHistoryLine))
-                            continue;
-                        int[] cluster = ((NarrowingHistoryLine) entry.value()).span;
-                        if (cluster[0] == origIndex && cluster[1] > cluster[0]) {
-                            currentDelegate = new MemoryHistory();
-                            for (int i = cluster[0]; i <= cluster[1]; i++) {
-                                currentDelegate.add(fullHistory.get(i));
-                            }
-                        }
-                    }
-                }
-            }
-            fullHistory.moveToEnd();
-            while (fullHistory.previous()) {
-                CharSequence c = fullHistory.current();
-                if (c instanceof NarrowingHistoryLine) {
-                    currentLine = (NarrowingHistoryLine) c;
-                    break;
-                }
-            }
-        } finally {
-            fullHistory.moveTo(origIndex);
-        }
-        if (currentLine == null || currentLine.span[1] != (-1)) {
-            line = currentLine = new NarrowingHistoryLine(line, fullSize);
-        }
-        StringBuilder complete = new StringBuilder();
-        for (int i = currentLine.span[0]; i < fullSize; i++) {
-            complete.append(fullHistory.get(i));
-        }
-        complete.append(line);
-        if (isComplete(complete)) {
-            currentLine.span[1] = fullSize; //TODO: +1?
-            currentDelegate = fullHistory;
-        }
-        fullHistory.add(line);
-    }
-
-    protected abstract boolean isComplete(CharSequence input);
-
-    @Override
-    public void set(int index, CharSequence item) {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        currentDelegate.set(index, item);
-    }
-
-    @Override
-    public CharSequence remove(int i) {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        return currentDelegate.remove(i);
-    }
-
-    @Override
-    public CharSequence removeFirst() {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        return currentDelegate.removeFirst();
-    }
-
-    @Override
-    public CharSequence removeLast() {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        return currentDelegate.removeLast();
-    }
-
-    @Override
-    public void replace(CharSequence item) {
-        if (currentDelegate != fullHistory)
-            throw new IllegalStateException("narrowed");
-        currentDelegate.replace(item);
-    }
-
-    @Override
-    public ListIterator<Entry> entries(int index) {
-        return currentDelegate.entries(index);
-    }
-
-    @Override
-    public ListIterator<Entry> entries() {
-        return currentDelegate.entries();
-    }
-
-    @Override
-    public Iterator<Entry> iterator() {
-        return currentDelegate.iterator();
-    }
-
-    @Override
-    public CharSequence current() {
-        return currentDelegate.current();
-    }
-
-    @Override
-    public boolean previous() {
-        return currentDelegate.previous();
-    }
-
-    @Override
-    public boolean next() {
-        return currentDelegate.next();
-    }
-
-    @Override
-    public boolean moveToFirst() {
-        return currentDelegate.moveToFirst();
-    }
-
-    @Override
-    public boolean moveToLast() {
-        return currentDelegate.moveToLast();
-    }
-
-    @Override
-    public boolean moveTo(int index) {
-        return currentDelegate.moveTo(index);
-    }
-
-    @Override
-    public void moveToEnd() {
-        currentDelegate.moveToEnd();
-    }
-
-    public boolean previousSnippet() {
-        while (previous()) {
-            if (current() instanceof NarrowingHistoryLine) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean nextSnippet() {
-        boolean success = false;
-
-        while (next()) {
-            success = true;
-
-            if (current() instanceof NarrowingHistoryLine) {
-                return true;
-            }
-        }
-
-        return success;
-    }
-
-    public final void load(Iterable<? extends String> originalHistory) {
-        NarrowingHistoryLine currentHistoryLine = null;
-        boolean start = true;
-        int currentLine = 0;
-        for (String historyItem : originalHistory) {
-            StringBuilder line = new StringBuilder(historyItem);
-            int trailingBackSlashes = countTrailintBackslashes(line);
-            boolean continuation = trailingBackSlashes % 2 != 0;
-            line.delete(line.length() - trailingBackSlashes / 2 - (continuation ? 1 : 0), line.length());
-            if (start) {
-                class PersistentNarrowingHistoryLine extends NarrowingHistoryLine implements PersistentEntryMarker {
-                    public PersistentNarrowingHistoryLine(CharSequence delegate, int start) {
-                        super(delegate, start);
-                    }
-                }
-                fullHistory.add(currentHistoryLine = new PersistentNarrowingHistoryLine(line, currentLine));
-            } else {
-                class PersistentLine implements CharSequence, PersistentEntryMarker {
-                    private final CharSequence delegate;
-                    public PersistentLine(CharSequence delegate) {
-                        this.delegate = delegate;
-                    }
-                    @Override public int length() {
-                        return delegate.length();
-                    }
-                    @Override public char charAt(int index) {
-                        return delegate.charAt(index);
-                    }
-                    @Override public CharSequence subSequence(int start, int end) {
-                        return delegate.subSequence(start, end);
-                    }
-                    @Override public String toString() {
-                        return delegate.toString();
-                    }
-                }
-                fullHistory.add(new PersistentLine(line));
-            }
-            start = !continuation;
-            currentHistoryLine.span[1] = currentLine;
-            currentLine++;
-        }
-    }
-
-    public Collection<? extends String> save() {
-        Collection<String> result = new ArrayList<>();
-        Iterator<Entry> entries = fullHistory.iterator();
-
-        if (entries.hasNext()) {
-            Entry entry = entries.next();
-            while (entry != null) {
-                StringBuilder historyLine = new StringBuilder(entry.value());
-                int trailingBackSlashes = countTrailintBackslashes(historyLine);
-                for (int i = 0; i < trailingBackSlashes; i++) {
-                    historyLine.append("\\");
-                }
-                entry = entries.hasNext() ? entries.next() : null;
-                if (entry != null && !(entry.value() instanceof NarrowingHistoryLine)) {
-                    historyLine.append("\\");
-                }
-                result.add(historyLine.toString());
-            }
-        }
-
-        return result;
-    }
-
-    private int countTrailintBackslashes(CharSequence text) {
-        int count = 0;
-
-        for (int i = text.length() - 1; i >= 0; i--) {
-            if (text.charAt(i) == '\\') {
-                count++;
-            } else {
-                break;
-            }
-        }
-
-        return count;
-    }
-
-    public List<String> entries(boolean currentSession) {
-        List<String> result = new ArrayList<>();
-
-        for (Entry e : fullHistory) {
-            if (!currentSession || !(e.value() instanceof PersistentEntryMarker)) {
-                result.add(e.value().toString());
-            }
-        }
-
-        return result;
-    }
-
-    public void fullHistoryReplace(String source) {
-        fullHistory.removeLast();
-        for (String line : source.split("\\R")) {
-            fullHistory.add(line);
-        }
-    }
-
-    private class NarrowingHistoryLine implements CharSequence {
-        private final CharSequence delegate;
-        private final int[] span;
-
-        public NarrowingHistoryLine(CharSequence delegate, int start) {
-            this.delegate = delegate;
-            this.span = new int[] {start, -1};
-        }
-
-        @Override
-        public int length() {
-            return delegate.length();
-        }
-
-        @Override
-        public char charAt(int index) {
-            return delegate.charAt(index);
-        }
-
-        @Override
-        public CharSequence subSequence(int start, int end) {
-            return delegate.subSequence(start, end);
-        }
-
-        @Override
-        public String toString() {
-            return delegate.toString();
-        }
-
-    }
-
-    private interface PersistentEntryMarker {}
-}
-
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Ansi.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.util.regex.Pattern;
-
-/**
- * Ansi support.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.13
- */
-public class Ansi {
-
-    public static String stripAnsi(String str) {
-        if (str == null) return "";
-        return ANSI_CODE_PATTERN.matcher(str).replaceAll("");
-        //was:
-//        try {
-//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-//            AnsiOutputStream aos = new AnsiOutputStream(baos);
-//            aos.write(str.getBytes());
-//            aos.close();
-//            return baos.toString();
-//        } catch (IOException e) {
-//            return str;
-//        }
-    }
-
-    public static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[\060-\077]*[\040-\057]*[\100-\176]");
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.FileNotFoundException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.util.Map;
-import java.util.Properties;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Provides access to configuration values.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.4
- */
-public class Configuration
-{
-    /**
-     * System property which can point to a file or URL containing configuration properties to load.
-     *
-     * @since 2.7
-     */
-    public static final String JLINE_CONFIGURATION = "jline.configuration";
-
-    /**
-     * Default configuration file name loaded from user's home directory.
-     */
-    public static final String JLINE_RC = ".jline.rc";
-
-    private static volatile Properties properties;
-
-    private static Properties initProperties() {
-        URL url = determineUrl();
-        Properties props = new Properties();
-        try {
-            loadProperties(url, props);
-        }
-        catch (FileNotFoundException e) {
-            // debug here and no stack trace, as this can happen normally if default jline.rc file is missing
-            Log.debug("Unable to read configuration: ", e.toString());
-        }
-        catch (IOException e) {
-            Log.warn("Unable to read configuration from: ", url, e);
-        }
-        return props;
-    }
-
-    private static void loadProperties(final URL url, final Properties props) throws IOException {
-        Log.debug("Loading properties from: ", url);
-        InputStream input = url.openStream();
-        try {
-            props.load(new BufferedInputStream(input));
-        }
-        finally {
-            try {
-                input.close();
-            }
-            catch (IOException e) {
-                // ignore
-            }
-        }
-
-        if (Log.DEBUG) {
-            Log.debug("Loaded properties:");
-            for (Map.Entry<Object,Object> entry : props.entrySet()) {
-                Log.debug("  ", entry.getKey(), "=", entry.getValue());
-            }
-        }
-    }
-
-    private static URL determineUrl() {
-        // See if user has customized the configuration location via sysprop
-        String tmp = System.getProperty(JLINE_CONFIGURATION);
-        if (tmp != null) {
-            return Urls.create(tmp);
-        }
-        else {
-            // Otherwise try the default
-            File file = new File(getUserHome(), JLINE_RC);
-            return Urls.create(file);
-        }
-    }
-
-    /**
-     * @since 2.7
-     */
-    public static void reset() {
-        Log.debug("Resetting");
-        properties = null;
-
-        // force new properties to load
-        getProperties();
-    }
-
-    /**
-     * @since 2.7
-     */
-    public static Properties getProperties() {
-        // Not sure its worth to guard this with any synchronization, volatile field probably sufficient
-        if (properties == null) {
-            properties = initProperties();
-        }
-        return properties;
-    }
-
-    public static String getString(final String name, final String defaultValue) {
-        checkNotNull(name);
-
-        String value;
-
-        // Check sysprops first, it always wins
-        value = System.getProperty(name);
-
-        if (value == null) {
-            // Next try userprops
-            value = getProperties().getProperty(name);
-
-            if (value == null) {
-                // else use the default
-                value = defaultValue;
-            }
-        }
-
-        return value;
-    }
-
-    public static String getString(final String name) {
-        return getString(name, null);
-    }
-
-    public static boolean getBoolean(final String name) {
-        return getBoolean(name, false);
-    }
-
-    public static boolean getBoolean(final String name, final boolean defaultValue) {
-        String value = getString(name);
-        if (value == null) {
-            return defaultValue;
-        }
-        return value.length() == 0
-            || value.equalsIgnoreCase("1")
-            || value.equalsIgnoreCase("on")
-            || value.equalsIgnoreCase("true");
-    }
-
-    /**
-     * @since 2.6
-     */
-    public static int getInteger(final String name, final int defaultValue) {
-        String str = getString(name);
-        if (str == null) {
-            return defaultValue;
-        }
-        return Integer.parseInt(str);
-    }
-
-    /**
-     * @since 2.6
-     */
-    public static long getLong(final String name, final long defaultValue) {
-        String str = getString(name);
-        if (str == null) {
-            return defaultValue;
-        }
-        return Long.parseLong(str);
-    }
-
-    //
-    // System property helpers
-    //
-
-    /**
-     * @since 2.7
-     */
-    public static String getLineSeparator() {
-        return System.getProperty("line.separator");
-    }
-
-    public static File getUserHome() {
-        return new File(System.getProperty("user.home"));
-    }
-
-    public static String getOsName() {
-        return System.getProperty("os.name").toLowerCase();
-    }
-
-    /**
-     * @since 2.7
-     */
-    public static boolean isWindows() {
-        return getOsName().startsWith("windows");
-    }
-
-    public static boolean isHpux() {
-        return getOsName().startsWith("hp");
-    }
-
-    // FIXME: Sort out use of property access of file.encoding in InputStreamReader, should consolidate configuration access here
-
-    public static String getFileEncoding() {
-        return System.getProperty("file.encoding");
-    }
-
-    /**
-     * Get the default encoding.  Will first look at the LC_ALL, LC_CTYPE, and LANG environment variables, then the input.encoding
-     * system property, then the default charset according to the JVM.
-     *
-     * @return The default encoding to use when none is specified.
-     */
-    public static String getEncoding() {
-        // Check for standard locale environment variables, in order of precedence, first.
-        // See http://www.gnu.org/s/libc/manual/html_node/Locale-Categories.html
-        for (String envOption : new String[]{"LC_ALL", "LC_CTYPE", "LANG"}) {
-            String envEncoding = extractEncodingFromCtype(System.getenv(envOption));
-            if (envEncoding != null) {
-                try {
-                    if (Charset.isSupported(envEncoding)) {
-                        return envEncoding;
-                    }
-                } catch (IllegalCharsetNameException e) {
-                    continue;
-                }
-            }
-        }
-        return getString("input.encoding", Charset.defaultCharset().name());
-    }
-
-    /**
-     * Parses the LC_CTYPE value to extract the encoding according to the POSIX standard, which says that the LC_CTYPE
-     * environment variable may be of the format <code>[language[_territory][.codeset][@modifier]]</code>
-     *
-     * @param ctype The ctype to parse, may be null
-     * @return The encoding, if one was present, otherwise null
-     */
-    static String extractEncodingFromCtype(String ctype) {
-        if (ctype != null && ctype.indexOf('.') > 0) {
-            String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1);
-            if (encodingAndModifier.indexOf('@') > 0) {
-                return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@'));
-            } else {
-                return encodingAndModifier;
-            }
-        }
-        return null;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Curses.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Stack;
-
-/**
- * Curses helper methods.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- */
-public class Curses {
-
-    private static Object[] sv = new Object[26];
-    private static Object[] dv = new Object[26];
-
-    private static final int IFTE_NONE = 0;
-    private static final int IFTE_IF = 1;
-    private static final int IFTE_THEN = 2;
-    private static final int IFTE_ELSE = 3;
-
-    /**
-     * Print the given terminal capabilities
-     *
-     * @param out the output stream
-     * @param str the capability to output
-     * @param params optional parameters
-     * @throws IOException if an error occurs
-     */
-    public static void tputs(Writer out, String str, Object... params) throws IOException {
-        int index = 0;
-        int length = str.length();
-        int ifte = IFTE_NONE;
-        boolean exec = true;
-        Stack<Object> stack = new Stack<Object>();
-        while (index < length) {
-            char ch = str.charAt(index++);
-            switch (ch) {
-                case '\\':
-                    ch = str.charAt(index++);
-                    if (ch >= '0' && ch <= '9') {
-                        throw new UnsupportedOperationException(); // todo
-                    } else {
-                        switch (ch) {
-                            case 'e':
-                            case 'E':
-                                if (exec) {
-                                    out.write(27); // escape
-                                }
-                                break;
-                            case 'n':
-                                out.write('\n');
-                                break;
-//                        case 'l':
-//                            rawPrint('\l');
-//                            break;
-                            case 'r':
-                                if (exec) {
-                                    out.write('\r');
-                                }
-                                break;
-                            case 't':
-                                if (exec) {
-                                    out.write('\t');
-                                }
-                                break;
-                            case 'b':
-                                if (exec) {
-                                    out.write('\b');
-                                }
-                                break;
-                            case 'f':
-                                if (exec) {
-                                    out.write('\f');
-                                }
-                                break;
-                            case 's':
-                                if (exec) {
-                                    out.write(' ');
-                                }
-                                break;
-                            case ':':
-                            case '^':
-                            case '\\':
-                                if (exec) {
-                                    out.write(ch);
-                                }
-                                break;
-                            default:
-                                throw new IllegalArgumentException();
-                        }
-                    }
-                    break;
-                case '^':
-                    ch = str.charAt(index++);
-                    if (exec) {
-                        out.write(ch - '@');
-                    }
-                    break;
-                case '%':
-                    ch = str.charAt(index++);
-                    switch (ch) {
-                        case '%':
-                            if (exec) {
-                                out.write('%');
-                            }
-                            break;
-                        case 'p':
-                            ch = str.charAt(index++);
-                            if (exec) {
-                                stack.push(params[ch - '1']);
-                            }
-                            break;
-                        case 'P':
-                            ch = str.charAt(index++);
-                            if (ch >= 'a' && ch <= 'z') {
-                                if (exec) {
-                                    dv[ch - 'a'] = stack.pop();
-                                }
-                            } else if (ch >= 'A' && ch <= 'Z') {
-                                if (exec) {
-                                    sv[ch - 'A'] = stack.pop();
-                                }
-                            } else {
-                                throw new IllegalArgumentException();
-                            }
-                            break;
-                        case 'g':
-                            ch = str.charAt(index++);
-                            if (ch >= 'a' && ch <= 'z') {
-                                if (exec) {
-                                    stack.push(dv[ch - 'a']);
-                                }
-                            } else if (ch >= 'A' && ch <= 'Z') {
-                                if (exec) {
-                                    stack.push(sv[ch - 'A']);
-                                }
-                            } else {
-                                throw new IllegalArgumentException();
-                            }
-                            break;
-                        case '\'':
-                            ch = str.charAt(index++);
-                            if (exec) {
-                                stack.push((int) ch);
-                            }
-                            ch = str.charAt(index++);
-                            if (ch != '\'') {
-                                throw new IllegalArgumentException();
-                            }
-                            break;
-                        case '{':
-                            int start = index;
-                            while (str.charAt(index++) != '}') ;
-                            if (exec) {
-                                int v = Integer.valueOf(str.substring(start, index - 1));
-                                stack.push(v);
-                            }
-                            break;
-                        case 'l':
-                            if (exec) {
-                                stack.push(stack.pop().toString().length());
-                            }
-                            break;
-                        case '+':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 + v2);
-                            }
-                            break;
-                        case '-':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 - v2);
-                            }
-                            break;
-                        case '*':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 * v2);
-                            }
-                            break;
-                        case '/':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 / v2);
-                            }
-                            break;
-                        case 'm':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 % v2);
-                            }
-                            break;
-                        case '&':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 & v2);
-                            }
-                            break;
-                        case '|':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 | v2);
-                            }
-                            break;
-                        case '^':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 ^ v2);
-                            }
-                            break;
-                        case '=':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 == v2);
-                            }
-                            break;
-                        case '>':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 > v2);
-                            }
-                            break;
-                        case '<':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 < v2);
-                            }
-                            break;
-                        case 'A':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 != 0 && v2 != 0);
-                            }
-                            break;
-                        case '!':
-                            if (exec) {
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 == 0);
-                            }
-                            break;
-                        case '~':
-                            if (exec) {
-                                int v1 = toInteger(stack.pop());
-                                stack.push(~v1);
-                            }
-                            break;
-                        case 'O':
-                            if (exec) {
-                                int v2 = toInteger(stack.pop());
-                                int v1 = toInteger(stack.pop());
-                                stack.push(v1 != 0 || v2 != 0);
-                            }
-                            break;
-                        case '?':
-                            if (ifte != IFTE_NONE) {
-                                throw new IllegalArgumentException();
-                            } else {
-                                ifte = IFTE_IF;
-                            }
-                            break;
-                        case 't':
-                            if (ifte != IFTE_IF && ifte != IFTE_ELSE) {
-                                throw new IllegalArgumentException();
-                            } else {
-                                ifte = IFTE_THEN;
-                            }
-                            exec = toInteger(stack.pop()) != 0;
-                            break;
-                        case 'e':
-                            if (ifte != IFTE_THEN) {
-                                throw new IllegalArgumentException();
-                            } else {
-                                ifte = IFTE_ELSE;
-                            }
-                            exec = !exec;
-                            break;
-                        case ';':
-                            if (ifte == IFTE_NONE || ifte == IFTE_IF) {
-                                throw new IllegalArgumentException();
-                            } else {
-                                ifte = IFTE_NONE;
-                            }
-                            exec = true;
-                            break;
-                        case 'i':
-                            if (params.length >= 1) {
-                                params[0] = toInteger(params[0]) + 1;
-                            }
-                            if (params.length >= 2) {
-                                params[1] = toInteger(params[1]) + 1;
-                            }
-                            break;
-                        case 'd':
-                            out.write(Integer.toString(toInteger(stack.pop())));
-                            break;
-                        default:
-                            throw new UnsupportedOperationException();
-                    }
-                    break;
-                default:
-                    if (exec) {
-                        out.write(ch);
-                    }
-                    break;
-            }
-        }
-    }
-
-    private static int toInteger(Object pop) {
-        if (pop instanceof Number) {
-            return ((Number) pop).intValue();
-        } else if (pop instanceof Boolean) {
-            return (Boolean) pop ? 1 : 0;
-        } else {
-            return Integer.valueOf(pop.toString());
-        }
-    }
-
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InfoCmp.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,591 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Infocmp helper methods.
- *
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- */
-public class InfoCmp {
-
-    private static final Map<String, String> CAPS = new HashMap<String, String>();
-
-    public static String getInfoCmp(
-            String terminal
-    ) throws IOException, InterruptedException {
-        String caps = CAPS.get(terminal);
-        if (caps == null) {
-            Process p = new ProcessBuilder("infocmp", terminal).start();
-            caps = TerminalLineSettings.waitAndCapture(p);
-            CAPS.put(terminal, caps);
-        }
-        return caps;
-    }
-
-    public static String getAnsiCaps() {
-        return ANSI_CAPS;
-    }
-
-    public static void parseInfoCmp(
-            String capabilities,
-            Set<String> bools,
-            Map<String, Integer> ints,
-            Map<String, String> strings
-    ) {
-        String[] lines = capabilities.split("\n");
-        for (int i = 2; i < lines.length; i++) {
-            Matcher m = Pattern.compile("\\s*(([^,]|\\\\,)+)\\s*[,$]").matcher(lines[i]);
-            while (m.find()) {
-                String cap = m.group(1);
-                if (cap.contains("#")) {
-                    int index = cap.indexOf('#');
-                    String key = cap.substring(0, index);
-                    String val = cap.substring(index + 1);
-                    int iVal;
-                    if (val.startsWith("0x")) {
-                        iVal = Integer.parseInt(val.substring(2), 16);
-                    } else {
-                        iVal = Integer.parseInt(val);
-                    }
-                    for (String name : getNames(key)) {
-                        ints.put(name, iVal);
-                    }
-                } else if (cap.contains("=")) {
-                    int index = cap.indexOf('=');
-                    String key = cap.substring(0, index);
-                    String val = cap.substring(index + 1);
-                    for (String name : getNames(key)) {
-                        strings.put(name, val);
-                    }
-                } else {
-                    for (String name : getNames(cap)) {
-                        bools.add(name);
-                    }
-                }
-            }
-        }
-    }
-
-    public static String[] getNames(String name) {
-        String[] names = NAMES.get(name);
-        return names != null ? names : new String[] { name };
-    }
-
-    private static final Map<String, String[]> NAMES;
-    static {
-        String[][] list = {
-                { "auto_left_margin", "bw", "bw" },
-                { "auto_right_margin", "am", "am" },
-                { "back_color_erase", "bce", "ut" },
-                { "can_change", "ccc", "cc" },
-                { "ceol_standout_glitch", "xhp", "xs" },
-                { "col_addr_glitch", "xhpa", "YA" },
-                { "cpi_changes_res", "cpix", "YF" },
-                { "cr_cancels_micro_mode", "crxm", "YB" },
-                { "dest_tabs_magic_smso", "xt", "xt" },
-                { "eat_newline_glitch", "xenl", "xn" },
-                { "erase_overstrike", "eo", "eo" },
-                { "generic_type", "gn", "gn" },
-                { "hard_copy", "hc", "hc" },
-                { "hard_cursor", "chts", "HC" },
-                { "has_meta_key", "km", "km" },
-                { "has_print_wheel", "daisy", "YC" },
-                { "has_status_line", "hs", "hs" },
-                { "hue_lightness_saturation", "hls", "hl" },
-                { "insert_null_glitch", "in", "in" },
-                { "lpi_changes_res", "lpix", "YG" },
-                { "memory_above", "da", "da" },
-                { "memory_below", "db", "db" },
-                { "move_insert_mode", "mir", "mi" },
-                { "move_standout_mode", "msgr", "ms" },
-                { "needs_xon_xoff", "nxon", "nx" },
-                { "no_esc_ctlc", "xsb", "xb" },
-                { "no_pad_char", "npc", "NP" },
-                { "non_dest_scroll_region", "ndscr", "ND" },
-                { "non_rev_rmcup", "nrrmc", "NR" },
-                { "over_strike", "os", "os" },
-                { "prtr_silent", "mc5i", "5i" },
-                { "row_addr_glitch", "xvpa", "YD" },
-                { "semi_auto_right_margin", "sam", "YE" },
-                { "status_line_esc_ok", "eslok", "es" },
-                { "tilde_glitch", "hz", "hz" },
-                { "transparent_underline", "ul", "ul" },
-                { "xon_xoff", "xon", "xo" },
-                { "columns", "cols", "co" },
-                { "init_tabs", "it", "it" },
-                { "label_height", "lh", "lh" },
-                { "label_width", "lw", "lw" },
-                { "lines", "lines", "li" },
-                { "lines_of_memory", "lm", "lm" },
-                { "magic_cookie_glitch", "xmc", "sg" },
-                { "max_attributes", "ma", "ma" },
-                { "max_colors", "colors", "Co" },
-                { "max_pairs", "pairs", "pa" },
-                { "maximum_windows", "wnum", "MW" },
-                { "no_color_video", "ncv", "NC" },
-                { "num_labels", "nlab", "Nl" },
-                { "padding_baud_rate", "pb", "pb" },
-                { "virtual_terminal", "vt", "vt" },
-                { "width_status_line", "wsl", "ws" },
-                { "bit_image_entwining", "bitwin", "Yo" },
-                { "bit_image_type", "bitype", "Yp" },
-                { "buffer_capacity", "bufsz", "Ya" },
-                { "buttons", "btns", "BT" },
-                { "dot_horz_spacing", "spinh", "Yc" },
-                { "dot_vert_spacing", "spinv", "Yb" },
-                { "max_micro_address", "maddr", "Yd" },
-                { "max_micro_jump", "mjump", "Ye" },
-                { "micro_col_size", "mcs", "Yf" },
-                { "micro_line_size", "mls", "Yg" },
-                { "number_of_pins", "npins", "Yh" },
-                { "output_res_char", "orc", "Yi" },
-                { "output_res_horz_inch", "orhi", "Yk" },
-                { "output_res_line", "orl", "Yj" },
-                { "output_res_vert_inch", "orvi", "Yl" },
-                { "print_rate", "cps", "Ym" },
-                { "wide_char_size", "widcs", "Yn" },
-                { "acs_chars", "acsc", "ac" },
-                { "back_tab", "cbt", "bt" },
-                { "bell", "bel", "bl" },
-                { "carriage_return", "cr", "cr" },
-                { "change_char_pitch", "cpi", "ZA" },
-                { "change_line_pitch", "lpi", "ZB" },
-                { "change_res_horz", "chr", "ZC" },
-                { "change_res_vert", "cvr", "ZD" },
-                { "change_scroll_region", "csr", "cs" },
-                { "char_padding", "rmp", "rP" },
-                { "clear_all_tabs", "tbc", "ct" },
-                { "clear_margins", "mgc", "MC" },
-                { "clear_screen", "clear", "cl" },
-                { "clr_bol", "el1", "cb" },
-                { "clr_eol", "el", "ce" },
-                { "clr_eos", "ed", "cd" },
-                { "column_address", "hpa", "ch" },
-                { "command_character", "cmdch", "CC" },
-                { "create_window", "cwin", "CW" },
-                { "cursor_address", "cup", "cm" },
-                { "cursor_down", "cud1", "do" },
-                { "cursor_home", "home", "ho" },
-                { "cursor_invisible", "civis", "vi" },
-                { "cursor_left", "cub1", "le" },
-                { "cursor_mem_address", "mrcup", "CM" },
-                { "cursor_normal", "cnorm", "ve" },
-                { "cursor_right", "cuf1", "nd" },
-                { "cursor_to_ll", "ll", "ll" },
-                { "cursor_up", "cuu1", "up" },
-                { "cursor_visible", "cvvis", "vs" },
-                { "define_char", "defc", "ZE" },
-                { "delete_character", "dch1", "dc" },
-                { "delete_line", "dl1", "dl" },
-                { "dial_phone", "dial", "DI" },
-                { "dis_status_line", "dsl", "ds" },
-                { "display_clock", "dclk", "DK" },
-                { "down_half_line", "hd", "hd" },
-                { "ena_acs", "enacs", "eA" },
-                { "enter_alt_charset_mode", "smacs", "as" },
-                { "enter_am_mode", "smam", "SA" },
-                { "enter_blink_mode", "blink", "mb" },
-                { "enter_bold_mode", "bold", "md" },
-                { "enter_ca_mode", "smcup", "ti" },
-                { "enter_delete_mode", "smdc", "dm" },
-                { "enter_dim_mode", "dim", "mh" },
-                { "enter_doublewide_mode", "swidm", "ZF" },
-                { "enter_draft_quality", "sdrfq", "ZG" },
-                { "enter_insert_mode", "smir", "im" },
-                { "enter_italics_mode", "sitm", "ZH" },
-                { "enter_leftward_mode", "slm", "ZI" },
-                { "enter_micro_mode", "smicm", "ZJ" },
-                { "enter_near_letter_quality", "snlq", "ZK" },
-                { "enter_normal_quality", "snrmq", "ZL" },
-                { "enter_protected_mode", "prot", "mp" },
-                { "enter_reverse_mode", "rev", "mr" },
-                { "enter_secure_mode", "invis", "mk" },
-                { "enter_shadow_mode", "sshm", "ZM" },
-                { "enter_standout_mode", "smso", "so" },
-                { "enter_subscript_mode", "ssubm", "ZN" },
-                { "enter_superscript_mode", "ssupm", "ZO" },
-                { "enter_underline_mode", "smul", "us" },
-                { "enter_upward_mode", "sum", "ZP" },
-                { "enter_xon_mode", "smxon", "SX" },
-                { "erase_chars", "ech", "ec" },
-                { "exit_alt_charset_mode", "rmacs", "ae" },
-                { "exit_am_mode", "rmam", "RA" },
-                { "exit_attribute_mode", "sgr0", "me" },
-                { "exit_ca_mode", "rmcup", "te" },
-                { "exit_delete_mode", "rmdc", "ed" },
-                { "exit_doublewide_mode", "rwidm", "ZQ" },
-                { "exit_insert_mode", "rmir", "ei" },
-                { "exit_italics_mode", "ritm", "ZR" },
-                { "exit_leftward_mode", "rlm", "ZS" },
-                { "exit_micro_mode", "rmicm", "ZT" },
-                { "exit_shadow_mode", "rshm", "ZU" },
-                { "exit_standout_mode", "rmso", "se" },
-                { "exit_subscript_mode", "rsubm", "ZV" },
-                { "exit_superscript_mode", "rsupm", "ZW" },
-                { "exit_underline_mode", "rmul", "ue" },
-                { "exit_upward_mode", "rum", "ZX" },
-                { "exit_xon_mode", "rmxon", "RX" },
-                { "fixed_pause", "pause", "PA" },
-                { "flash_hook", "hook", "fh" },
-                { "flash_screen", "flash", "vb" },
-                { "form_feed", "ff", "ff" },
-                { "from_status_line", "fsl", "fs" },
-                { "goto_window", "wingo", "WG" },
-                { "hangup", "hup", "HU" },
-                { "init_1string", "is1", "i1" },
-                { "init_2string", "is2", "is" },
-                { "init_3string", "is3", "i3" },
-                { "init_file", "if", "if" },
-                { "init_prog", "iprog", "iP" },
-                { "initialize_color", "initc", "Ic" },
-                { "initialize_pair", "initp", "Ip" },
-                { "insert_character", "ich1", "ic" },
-                { "insert_line", "il1", "al" },
-                { "insert_padding", "ip", "ip" },
-                { "key_a1", "ka1", "K1" },
-                { "key_a3", "ka3", "K3" },
-                { "key_b2", "kb2", "K2" },
-                { "key_backspace", "kbs", "kb" },
-                { "key_beg", "kbeg", "@1" },
-                { "key_btab", "kcbt", "kB" },
-                { "key_c1", "kc1", "K4" },
-                { "key_c3", "kc3", "K5" },
-                { "key_cancel", "kcan", "@2" },
-                { "key_catab", "ktbc", "ka" },
-                { "key_clear", "kclr", "kC" },
-                { "key_close", "kclo", "@3" },
-                { "key_command", "kcmd", "@4" },
-                { "key_copy", "kcpy", "@5" },
-                { "key_create", "kcrt", "@6" },
-                { "key_ctab", "kctab", "kt" },
-                { "key_dc", "kdch1", "kD" },
-                { "key_dl", "kdl1", "kL" },
-                { "key_down", "kcud1", "kd" },
-                { "key_eic", "krmir", "kM" },
-                { "key_end", "kend", "@7" },
-                { "key_enter", "kent", "@8" },
-                { "key_eol", "kel", "kE" },
-                { "key_eos", "ked", "kS" },
-                { "key_exit", "kext", "@9" },
-                { "key_f0", "kf0", "k0" },
-                { "key_f1", "kf1", "k1" },
-                { "key_f10", "kf10", "k;" },
-                { "key_f11", "kf11", "F1" },
-                { "key_f12", "kf12", "F2" },
-                { "key_f13", "kf13", "F3" },
-                { "key_f14", "kf14", "F4" },
-                { "key_f15", "kf15", "F5" },
-                { "key_f16", "kf16", "F6" },
-                { "key_f17", "kf17", "F7" },
-                { "key_f18", "kf18", "F8" },
-                { "key_f19", "kf19", "F9" },
-                { "key_f2", "kf2", "k2" },
-                { "key_f20", "kf20", "FA" },
-                { "key_f21", "kf21", "FB" },
-                { "key_f22", "kf22", "FC" },
-                { "key_f23", "kf23", "FD" },
-                { "key_f24", "kf24", "FE" },
-                { "key_f25", "kf25", "FF" },
-                { "key_f26", "kf26", "FG" },
-                { "key_f27", "kf27", "FH" },
-                { "key_f28", "kf28", "FI" },
-                { "key_f29", "kf29", "FJ" },
-                { "key_f3", "kf3", "k3" },
-                { "key_f30", "kf30", "FK" },
-                { "key_f31", "kf31", "FL" },
-                { "key_f32", "kf32", "FM" },
-                { "key_f33", "kf33", "FN" },
-                { "key_f34", "kf34", "FO" },
-                { "key_f35", "kf35", "FP" },
-                { "key_f36", "kf36", "FQ" },
-                { "key_f37", "kf37", "FR" },
-                { "key_f38", "kf38", "FS" },
-                { "key_f39", "kf39", "FT" },
-                { "key_f4", "kf4", "k4" },
-                { "key_f40", "kf40", "FU" },
-                { "key_f41", "kf41", "FV" },
-                { "key_f42", "kf42", "FW" },
-                { "key_f43", "kf43", "FX" },
-                { "key_f44", "kf44", "FY" },
-                { "key_f45", "kf45", "FZ" },
-                { "key_f46", "kf46", "Fa" },
-                { "key_f47", "kf47", "Fb" },
-                { "key_f48", "kf48", "Fc" },
-                { "key_f49", "kf49", "Fd" },
-                { "key_f5", "kf5", "k5" },
-                { "key_f50", "kf50", "Fe" },
-                { "key_f51", "kf51", "Ff" },
-                { "key_f52", "kf52", "Fg" },
-                { "key_f53", "kf53", "Fh" },
-                { "key_f54", "kf54", "Fi" },
-                { "key_f55", "kf55", "Fj" },
-                { "key_f56", "kf56", "Fk" },
-                { "key_f57", "kf57", "Fl" },
-                { "key_f58", "kf58", "Fm" },
-                { "key_f59", "kf59", "Fn" },
-                { "key_f6", "kf6", "k6" },
-                { "key_f60", "kf60", "Fo" },
-                { "key_f61", "kf61", "Fp" },
-                { "key_f62", "kf62", "Fq" },
-                { "key_f63", "kf63", "Fr" },
-                { "key_f7", "kf7", "k7" },
-                { "key_f8", "kf8", "k8" },
-                { "key_f9", "kf9", "k9" },
-                { "key_find", "kfnd", "@0" },
-                { "key_help", "khlp", "%1" },
-                { "key_home", "khome", "kh" },
-                { "key_ic", "kich1", "kI" },
-                { "key_il", "kil1", "kA" },
-                { "key_left", "kcub1", "kl" },
-                { "key_ll", "kll", "kH" },
-                { "key_mark", "kmrk", "%2" },
-                { "key_message", "kmsg", "%3" },
-                { "key_move", "kmov", "%4" },
-                { "key_next", "knxt", "%5" },
-                { "key_npage", "knp", "kN" },
-                { "key_open", "kopn", "%6" },
-                { "key_options", "kopt", "%7" },
-                { "key_ppage", "kpp", "kP" },
-                { "key_previous", "kprv", "%8" },
-                { "key_print", "kprt", "%9" },
-                { "key_redo", "krdo", "%0" },
-                { "key_reference", "kref", "&1" },
-                { "key_refresh", "krfr", "&2" },
-                { "key_replace", "krpl", "&3" },
-                { "key_restart", "krst", "&4" },
-                { "key_resume", "kres", "&5" },
-                { "key_right", "kcuf1", "kr" },
-                { "key_save", "ksav", "&6" },
-                { "key_sbeg", "kBEG", "&9" },
-                { "key_scancel", "kCAN", "&0" },
-                { "key_scommand", "kCMD", "*1" },
-                { "key_scopy", "kCPY", "*2" },
-                { "key_screate", "kCRT", "*3" },
-                { "key_sdc", "kDC", "*4" },
-                { "key_sdl", "kDL", "*5" },
-                { "key_select", "kslt", "*6" },
-                { "key_send", "kEND", "*7" },
-                { "key_seol", "kEOL", "*8" },
-                { "key_sexit", "kEXT", "*9" },
-                { "key_sf", "kind", "kF" },
-                { "key_sfind", "kFND", "*0" },
-                { "key_shelp", "kHLP", "#1" },
-                { "key_shome", "kHOM", "#2" },
-                { "key_sic", "kIC", "#3" },
-                { "key_sleft", "kLFT", "#4" },
-                { "key_smessage", "kMSG", "%a" },
-                { "key_smove", "kMOV", "%b" },
-                { "key_snext", "kNXT", "%c" },
-                { "key_soptions", "kOPT", "%d" },
-                { "key_sprevious", "kPRV", "%e" },
-                { "key_sprint", "kPRT", "%f" },
-                { "key_sr", "kri", "kR" },
-                { "key_sredo", "kRDO", "%g" },
-                { "key_sreplace", "kRPL", "%h" },
-                { "key_sright", "kRIT", "%i" },
-                { "key_srsume", "kRES", "%j" },
-                { "key_ssave", "kSAV", "!1" },
-                { "key_ssuspend", "kSPD", "!2" },
-                { "key_stab", "khts", "kT" },
-                { "key_sundo", "kUND", "!3" },
-                { "key_suspend", "kspd", "&7" },
-                { "key_undo", "kund", "&8" },
-                { "key_up", "kcuu1", "ku" },
-                { "keypad_local", "rmkx", "ke" },
-                { "keypad_xmit", "smkx", "ks" },
-                { "lab_f0", "lf0", "l0" },
-                { "lab_f1", "lf1", "l1" },
-                { "lab_f10", "lf10", "la" },
-                { "lab_f2", "lf2", "l2" },
-                { "lab_f3", "lf3", "l3" },
-                { "lab_f4", "lf4", "l4" },
-                { "lab_f5", "lf5", "l5" },
-                { "lab_f6", "lf6", "l6" },
-                { "lab_f7", "lf7", "l7" },
-                { "lab_f8", "lf8", "l8" },
-                { "lab_f9", "lf9", "l9" },
-                { "label_format", "fln", "Lf" },
-                { "label_off", "rmln", "LF" },
-                { "label_on", "smln", "LO" },
-                { "meta_off", "rmm", "mo" },
-                { "meta_on", "smm", "mm" },
-                { "micro_column_address", "mhpa", "ZY" },
-                { "micro_down", "mcud1", "ZZ" },
-                { "micro_left", "mcub1", "Za" },
-                { "micro_right", "mcuf1", "Zb" },
-                { "micro_row_address", "mvpa", "Zc" },
-                { "micro_up", "mcuu1", "Zd" },
-                { "newline", "nel", "nw" },
-                { "order_of_pins", "porder", "Ze" },
-                { "orig_colors", "oc", "oc" },
-                { "orig_pair", "op", "op" },
-                { "pad_char", "pad", "pc" },
-                { "parm_dch", "dch", "DC" },
-                { "parm_delete_line", "dl", "DL" },
-                { "parm_down_cursor", "cud", "DO" },
-                { "parm_down_micro", "mcud", "Zf" },
-                { "parm_ich", "ich", "IC" },
-                { "parm_index", "indn", "SF" },
-                { "parm_insert_line", "il", "AL" },
-                { "parm_left_cursor", "cub", "LE" },
-                { "parm_left_micro", "mcub", "Zg" },
-                { "parm_right_cursor", "cuf", "RI" },
-                { "parm_right_micro", "mcuf", "Zh" },
-                { "parm_rindex", "rin", "SR" },
-                { "parm_up_cursor", "cuu", "UP" },
-                { "parm_up_micro", "mcuu", "Zi" },
-                { "pkey_key", "pfkey", "pk" },
-                { "pkey_local", "pfloc", "pl" },
-                { "pkey_xmit", "pfx", "px" },
-                { "plab_norm", "pln", "pn" },
-                { "print_screen", "mc0", "ps" },
-                { "prtr_non", "mc5p", "pO" },
-                { "prtr_off", "mc4", "pf" },
-                { "prtr_on", "mc5", "po" },
-                { "pulse", "pulse", "PU" },
-                { "quick_dial", "qdial", "QD" },
-                { "remove_clock", "rmclk", "RC" },
-                { "repeat_char", "rep", "rp" },
-                { "req_for_input", "rfi", "RF" },
-                { "reset_1string", "rs1", "r1" },
-                { "reset_2string", "rs2", "r2" },
-                { "reset_3string", "rs3", "r3" },
-                { "reset_file", "rf", "rf" },
-                { "restore_cursor", "rc", "rc" },
-                { "row_address", "vpa", "cv" },
-                { "save_cursor", "sc", "sc" },
-                { "scroll_forward", "ind", "sf" },
-                { "scroll_reverse", "ri", "sr" },
-                { "select_char_set", "scs", "Zj" },
-                { "set_attributes", "sgr", "sa" },
-                { "set_background", "setb", "Sb" },
-                { "set_bottom_margin", "smgb", "Zk" },
-                { "set_bottom_margin_parm", "smgbp", "Zl" },
-                { "set_clock", "sclk", "SC" },
-                { "set_color_pair", "scp", "sp" },
-                { "set_foreground", "setf", "Sf" },
-                { "set_left_margin", "smgl", "ML" },
-                { "set_left_margin_parm", "smglp", "Zm" },
-                { "set_right_margin", "smgr", "MR" },
-                { "set_right_margin_parm", "smgrp", "Zn" },
-                { "set_tab", "hts", "st" },
-                { "set_top_margin", "smgt", "Zo" },
-                { "set_top_margin_parm", "smgtp", "Zp" },
-                { "set_window", "wind", "wi" },
-                { "start_bit_image", "sbim", "Zq" },
-                { "start_char_set_def", "scsd", "Zr" },
-                { "stop_bit_image", "rbim", "Zs" },
-                { "stop_char_set_def", "rcsd", "Zt" },
-                { "subscript_characters", "subcs", "Zu" },
-                { "superscript_characters", "supcs", "Zv" },
-                { "tab", "ht", "ta" },
-                { "these_cause_cr", "docr", "Zw" },
-                { "to_status_line", "tsl", "ts" },
-                { "tone", "tone", "TO" },
-                { "underline_char", "uc", "uc" },
-                { "up_half_line", "hu", "hu" },
-                { "user0", "u0", "u0" },
-                { "user1", "u1", "u1" },
-                { "user2", "u2", "u2" },
-                { "user3", "u3", "u3" },
-                { "user4", "u4", "u4" },
-                { "user5", "u5", "u5" },
-                { "user6", "u6", "u6" },
-                { "user7", "u7", "u7" },
-                { "user8", "u8", "u8" },
-                { "user9", "u9", "u9" },
-                { "wait_tone", "wait", "WA" },
-                { "xoff_character", "xoffc", "XF" },
-                { "xon_character", "xonc", "XN" },
-                { "zero_motion", "zerom", "Zx" },
-                { "alt_scancode_esc", "scesa", "S8" },
-                { "bit_image_carriage_return", "bicr", "Yv" },
-                { "bit_image_newline", "binel", "Zz" },
-                { "bit_image_repeat", "birep", "Xy" },
-                { "char_set_names", "csnm", "Zy" },
-                { "code_set_init", "csin", "ci" },
-                { "color_names", "colornm", "Yw" },
-                { "define_bit_image_region", "defbi", "Yx" },
-                { "device_type", "devt", "dv" },
-                { "display_pc_char", "dispc", "S1" },
-                { "end_bit_image_region", "endbi", "Yy" },
-                { "enter_pc_charset_mode", "smpch", "S2" },
-                { "enter_scancode_mode", "smsc", "S4" },
-                { "exit_pc_charset_mode", "rmpch", "S3" },
-                { "exit_scancode_mode", "rmsc", "S5" },
-                { "get_mouse", "getm", "Gm" },
-                { "key_mouse", "kmous", "Km" },
-                { "mouse_info", "minfo", "Mi" },
-                { "pc_term_options", "pctrm", "S6" },
-                { "pkey_plab", "pfxl", "xl" },
-                { "req_mouse_pos", "reqmp", "RQ" },
-                { "scancode_escape", "scesc", "S7" },
-                { "set0_des_seq", "s0ds", "s0" },
-                { "set1_des_seq", "s1ds", "s1" },
-                { "set2_des_seq", "s2ds", "s2" },
-                { "set3_des_seq", "s3ds", "s3" },
-                { "set_a_background", "setab", "AB" },
-                { "set_a_foreground", "setaf", "AF" },
-                { "set_color_band", "setcolor", "Yz" },
-                { "set_lr_margin", "smglr", "ML" },
-                { "set_page_length", "slines", "YZ" },
-                { "set_tb_margin", "smgtb", "MT" },
-                { "enter_horizontal_hl_mode", "ehhlm", "Xh" },
-                { "enter_left_hl_mode", "elhlm", "Xl" },
-                { "enter_low_hl_mode", "elohlm", "Xo" },
-                { "enter_right_hl_mode", "erhlm", "Xr" },
-                { "enter_top_hl_mode", "ethlm", "Xt" },
-                { "enter_vertical_hl_mode", "evhlm", "Xv" },
-                { "set_a_attributes", "sgr1", "sA" },
-                { "set_pglen_inch", "slength", "sL" }
-        };
-
-        Map<String, String[]> map = new HashMap<String, String[]>();
-        for (String[] names : list) {
-            for (String name : names) {
-                map.put(name, names);
-            }
-        }
-        NAMES = Collections.unmodifiableMap(map);
-    }
-
-    private static String ANSI_CAPS =
-            "#\tReconstructed via infocmp from file: /usr/share/terminfo/61/ansi\n" +
-            "ansi|ansi/pc-term compatible with color,\n" +
-            "\tam, mc5i, mir, msgr,\n" +
-            "\tcolors#8, cols#80, it#8, lines#24, ncv#3, pairs#64,\n" +
-            "\tacsc=+\\020\\,\\021-\\030.^Y0\\333`\\004a\\261f\\370g\\361h\\260j\\331k\\277l\\332m\\300n\\305o~p\\304q\\304r\\304s_t\\303u\\264v\\301w\\302x\\263y\\363z\\362{\\343|\\330}\\234~\\376,\n" +
-            "\tbel=^G, blink=\\E[5m, bold=\\E[1m, cbt=\\E[Z, clear=\\E[H\\E[J,\n" +
-            "\tcr=^M, cub=\\E[%p1%dD, cub1=\\E[D, cud=\\E[%p1%dB, cud1=\\E[B,\n" +
-            "\tcuf=\\E[%p1%dC, cuf1=\\E[C, cup=\\E[%i%p1%d;%p2%dH,\n" +
-            "\tcuu=\\E[%p1%dA, cuu1=\\E[A, dch=\\E[%p1%dP, dch1=\\E[P,\n" +
-            "\tdl=\\E[%p1%dM, dl1=\\E[M, ech=\\E[%p1%dX, ed=\\E[J, el=\\E[K,\n" +
-            "\tel1=\\E[1K, home=\\E[H, hpa=\\E[%i%p1%dG, ht=\\E[I, hts=\\EH,\n" +
-            "\tich=\\E[%p1%d@, il=\\E[%p1%dL, il1=\\E[L, ind=^J,\n" +
-            "\tindn=\\E[%p1%dS, invis=\\E[8m, kbs=^H, kcbt=\\E[Z, kcub1=\\E[D,\n" +
-            "\tkcud1=\\E[B, kcuf1=\\E[C, kcuu1=\\E[A, khome=\\E[H, kich1=\\E[L,\n" +
-            "\tmc4=\\E[4i, mc5=\\E[5i, nel=\\r\\E[S, op=\\E[39;49m,\n" +
-            "\trep=%p1%c\\E[%p2%{1}%-%db, rev=\\E[7m, rin=\\E[%p1%dT,\n" +
-            "\trmacs=\\E[10m, rmpch=\\E[10m, rmso=\\E[m, rmul=\\E[m,\n" +
-            "\ts0ds=\\E(B, s1ds=\\E)B, s2ds=\\E*B, s3ds=\\E+B,\n" +
-            "\tsetab=\\E[4%p1%dm, setaf=\\E[3%p1%dm,\n" +
-            "\tsgr=\\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,\n" +
-            "\tsgr0=\\E[0;10m, smacs=\\E[11m, smpch=\\E[11m, smso=\\E[7m,\n" +
-            "\tsmul=\\E[4m, tbc=\\E[2g, u6=\\E[%i%d;%dR, u7=\\E[6n,\n" +
-            "\tu8=\\E[?%[;0123456789]c, u9=\\E[c, vpa=\\E[%i%p1%dd,";
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.MalformedInputException;
-import java.nio.charset.UnmappableCharacterException;
-
-
-/**
- *
- * NOTE for JLine: the default InputStreamReader that comes from the JRE
- * usually read more bytes than needed from the input stream, which
- * is not usable in a character per character model used in the console.
- * We thus use the harmony code which only reads the minimal number of bytes,
- * with a modification to ensure we can read larger characters (UTF-16 has
- * up to 4 bytes, and UTF-32, rare as it is, may have up to 8).
- */
-/**
- * A class for turning a byte stream into a character stream. Data read from the
- * source input stream is converted into characters by either a default or a
- * provided character converter. The default encoding is taken from the
- * "file.encoding" system property. {@code InputStreamReader} contains a buffer
- * of bytes read from the source stream and converts these into characters as
- * needed. The buffer size is 8K.
- *
- * @see OutputStreamWriter
- */
-public class InputStreamReader extends Reader {
-    private InputStream in;
-
-    private static final int BUFFER_SIZE = 8192;
-
-    private boolean endOfInput = false;
-
-    CharsetDecoder decoder;
-
-    ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE);
-
-    /**
-     * Constructs a new {@code InputStreamReader} on the {@link InputStream}
-     * {@code in}. This constructor sets the character converter to the encoding
-     * specified in the "file.encoding" property and falls back to ISO 8859_1
-     * (ISO-Latin-1) if the property doesn't exist.
-     *
-     * @param in
-     *            the input stream from which to read characters.
-     */
-    public InputStreamReader(InputStream in) {
-        super(in);
-        this.in = in;
-        decoder = Charset.defaultCharset().newDecoder().onMalformedInput(
-                CodingErrorAction.REPLACE).onUnmappableCharacter(
-                CodingErrorAction.REPLACE);
-        bytes.limit(0);
-    }
-
-    /**
-     * Constructs a new InputStreamReader on the InputStream {@code in}. The
-     * character converter that is used to decode bytes into characters is
-     * identified by name by {@code enc}. If the encoding cannot be found, an
-     * UnsupportedEncodingException error is thrown.
-     *
-     * @param in
-     *            the InputStream from which to read characters.
-     * @param enc
-     *            identifies the character converter to use.
-     * @throws NullPointerException
-     *             if {@code enc} is {@code null}.
-     * @throws UnsupportedEncodingException
-     *             if the encoding specified by {@code enc} cannot be found.
-     */
-    public InputStreamReader(InputStream in, final String enc)
-            throws UnsupportedEncodingException {
-        super(in);
-        if (enc == null) {
-            throw new NullPointerException();
-        }
-        this.in = in;
-        try {
-            decoder = Charset.forName(enc).newDecoder().onMalformedInput(
-                    CodingErrorAction.REPLACE).onUnmappableCharacter(
-                    CodingErrorAction.REPLACE);
-        } catch (IllegalArgumentException e) {
-            throw (UnsupportedEncodingException)
-                    new UnsupportedEncodingException(enc).initCause(e);
-        }
-        bytes.limit(0);
-    }
-
-    /**
-     * Constructs a new InputStreamReader on the InputStream {@code in} and
-     * CharsetDecoder {@code dec}.
-     *
-     * @param in
-     *            the source InputStream from which to read characters.
-     * @param dec
-     *            the CharsetDecoder used by the character conversion.
-     */
-    public InputStreamReader(InputStream in, CharsetDecoder dec) {
-        super(in);
-        dec.averageCharsPerByte();
-        this.in = in;
-        decoder = dec;
-        bytes.limit(0);
-    }
-
-    /**
-     * Constructs a new InputStreamReader on the InputStream {@code in} and
-     * Charset {@code charset}.
-     *
-     * @param in
-     *            the source InputStream from which to read characters.
-     * @param charset
-     *            the Charset that defines the character converter
-     */
-    public InputStreamReader(InputStream in, Charset charset) {
-        super(in);
-        this.in = in;
-        decoder = charset.newDecoder().onMalformedInput(
-                CodingErrorAction.REPLACE).onUnmappableCharacter(
-                CodingErrorAction.REPLACE);
-        bytes.limit(0);
-    }
-
-    /**
-     * Closes this reader. This implementation closes the source InputStream and
-     * releases all local storage.
-     *
-     * @throws IOException
-     *             if an error occurs attempting to close this reader.
-     */
-    @Override
-    public void close() throws IOException {
-        synchronized (lock) {
-            decoder = null;
-            if (in != null) {
-                in.close();
-                in = null;
-            }
-        }
-    }
-
-    /**
-     * Returns the name of the encoding used to convert bytes into characters.
-     * The value {@code null} is returned if this reader has been closed.
-     *
-     * @return the name of the character converter or {@code null} if this
-     *         reader is closed.
-     */
-    public String getEncoding() {
-        if (!isOpen()) {
-            return null;
-        }
-        return decoder.charset().name();
-    }
-
-    /**
-     * Reads a single character from this reader and returns it as an integer
-     * with the two higher-order bytes set to 0. Returns -1 if the end of the
-     * reader has been reached. The byte value is either obtained from
-     * converting bytes in this reader's buffer or by first filling the buffer
-     * from the source InputStream and then reading from the buffer.
-     *
-     * @return the character read or -1 if the end of the reader has been
-     *         reached.
-     * @throws IOException
-     *             if this reader is closed or some other I/O error occurs.
-     */
-    @Override
-    public int read() throws IOException {
-        synchronized (lock) {
-            if (!isOpen()) {
-                throw new IOException("InputStreamReader is closed.");
-            }
-
-            char buf[] = new char[4];
-            return read(buf, 0, 4) != -1 ? Character.codePointAt(buf, 0) : -1;
-        }
-    }
-
-    /**
-     * Reads at most {@code length} characters from this reader and stores them
-     * at position {@code offset} in the character array {@code buf}. Returns
-     * the number of characters actually read or -1 if the end of the reader has
-     * been reached. The bytes are either obtained from converting bytes in this
-     * reader's buffer or by first filling the buffer from the source
-     * InputStream and then reading from the buffer.
-     *
-     * @param buf
-     *            the array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buf} to store the characters
-     *            read from this reader.
-     * @param length
-     *            the maximum number of characters to read.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code buf}.
-     * @throws IOException
-     *             if this reader is closed or some other I/O error occurs.
-     */
-    @Override
-    public int read(char[] buf, int offset, int length) throws IOException {
-        synchronized (lock) {
-            if (!isOpen()) {
-                throw new IOException("InputStreamReader is closed.");
-            }
-            if (offset < 0 || offset > buf.length - length || length < 0) {
-                throw new IndexOutOfBoundsException();
-            }
-            if (length == 0) {
-                return 0;
-            }
-
-            CharBuffer out = CharBuffer.wrap(buf, offset, length);
-            CoderResult result = CoderResult.UNDERFLOW;
-
-            // bytes.remaining() indicates number of bytes in buffer
-            // when 1-st time entered, it'll be equal to zero
-            boolean needInput = !bytes.hasRemaining();
-
-            while (out.hasRemaining()) {
-                // fill the buffer if needed
-                if (needInput) {
-                    try {
-                        if ((in.available() == 0)
-                            && (out.position() > offset)) {
-                            // we could return the result without blocking read
-                            break;
-                        }
-                    } catch (IOException e) {
-                        // available didn't work so just try the read
-                    }
-
-                    int to_read = bytes.capacity() - bytes.limit();
-                    int off = bytes.arrayOffset() + bytes.limit();
-                    int was_red = in.read(bytes.array(), off, to_read);
-
-                    if (was_red == -1) {
-                        endOfInput = true;
-                        break;
-                    } else if (was_red == 0) {
-                        break;
-                    }
-                    bytes.limit(bytes.limit() + was_red);
-                    needInput = false;
-                }
-
-                // decode bytes
-                result = decoder.decode(bytes, out, false);
-
-                if (result.isUnderflow()) {
-                    // compact the buffer if no space left
-                    if (bytes.limit() == bytes.capacity()) {
-                        bytes.compact();
-                        bytes.limit(bytes.position());
-                        bytes.position(0);
-                    }
-                    needInput = true;
-                } else {
-                    break;
-                }
-            }
-
-            if (result == CoderResult.UNDERFLOW && endOfInput) {
-                result = decoder.decode(bytes, out, true);
-                decoder.flush(out);
-                decoder.reset();
-            }
-            if (result.isMalformed()) {
-                throw new MalformedInputException(result.length());
-            } else if (result.isUnmappable()) {
-                throw new UnmappableCharacterException(result.length());
-            }
-
-            return out.position() - offset == 0 ? -1 : out.position() - offset;
-        }
-    }
-
-    /*
-     * Answer a boolean indicating whether or not this InputStreamReader is
-     * open.
-     */
-    private boolean isOpen() {
-        return in != null;
-    }
-
-    /**
-     * Indicates whether this reader is ready to be read without blocking. If
-     * the result is {@code true}, the next {@code read()} will not block. If
-     * the result is {@code false} then this reader may or may not block when
-     * {@code read()} is called. This implementation returns {@code true} if
-     * there are bytes available in the buffer or the source stream has bytes
-     * available.
-     *
-     * @return {@code true} if the receiver will not block when {@code read()}
-     *         is called, {@code false} if unknown or blocking will occur.
-     * @throws IOException
-     *             if this reader is closed or some other I/O error occurs.
-     */
-    @Override
-    public boolean ready() throws IOException {
-        synchronized (lock) {
-            if (in == null) {
-                throw new IOException("InputStreamReader is closed.");
-            }
-            try {
-                return bytes.hasRemaining() || in.available() > 0;
-            } catch (IOException e) {
-                return false;
-            }
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-//import java.util.logging.LogRecord;
-//import java.util.logging.Logger;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Internal logger.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.0
- */
-public final class Log
-{
-    ///CLOVER:OFF
-
-    public static enum Level
-    {
-        TRACE,
-        DEBUG,
-        INFO,
-        WARN,
-        ERROR
-    }
-
-    public static final boolean TRACE = Configuration.getBoolean(Log.class.getName() + ".trace");
-
-    public static final boolean DEBUG = TRACE || Configuration.getBoolean(Log.class.getName() + ".debug");
-
-    private static PrintStream output = System.err;
-
-    private static boolean useJul = Configuration.getBoolean("jline.log.jul");
-
-    public static PrintStream getOutput() {
-        return output;
-    }
-
-    public static void setOutput(final PrintStream out) {
-        output = checkNotNull(out);
-    }
-
-    /**
-     * Helper to support rendering messages.
-     */
-    @TestAccessible
-    static void render(final PrintStream out, final Object message) {
-        if (message.getClass().isArray()) {
-            Object[] array = (Object[]) message;
-
-            out.print("[");
-            for (int i = 0; i < array.length; i++) {
-                out.print(array[i]);
-                if (i + 1 < array.length) {
-                    out.print(",");
-                }
-            }
-            out.print("]");
-        }
-        else {
-            out.print(message);
-        }
-    }
-
-    @TestAccessible
-    static void log(final Level level, final Object... messages) {
-        if (useJul) {
-            logWithJul(level, messages);
-            return;
-        }
-        //noinspection SynchronizeOnNonFinalField
-        synchronized (output) {
-            output.format("[%s] ", level);
-
-            for (int i=0; i<messages.length; i++) {
-                // Special handling for the last message if its a throwable, render its stack on the next line
-                if (i + 1 == messages.length && messages[i] instanceof Throwable) {
-                    output.println();
-                    ((Throwable)messages[i]).printStackTrace(output);
-                }
-                else {
-                    render(output, messages[i]);
-                }
-            }
-
-            output.println();
-            output.flush();
-        }
-    }
-
-    static void logWithJul(Level level, Object... messages) {
-//        Logger logger = Logger.getLogger("jline");
-//        Throwable cause = null;
-//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-//        PrintStream ps = new PrintStream(baos);
-//        for (int i = 0; i < messages.length; i++) {
-//            // Special handling for the last message if its a throwable, render its stack on the next line
-//            if (i + 1 == messages.length && messages[i] instanceof Throwable) {
-//                cause = (Throwable) messages[i];
-//            }
-//            else {
-//                render(ps, messages[i]);
-//            }
-//        }
-//        ps.close();
-//        LogRecord r = new LogRecord(toJulLevel(level), baos.toString());
-//        r.setThrown(cause);
-//        logger.log(r);
-    }
-
-//    private static java.util.logging.Level toJulLevel(Level level) {
-//        switch (level) {
-//            case TRACE:
-//                return java.util.logging.Level.FINEST;
-//            case DEBUG:
-//                return java.util.logging.Level.FINE;
-//            case INFO:
-//                return java.util.logging.Level.INFO;
-//            case WARN:
-//                return java.util.logging.Level.WARNING;
-//            case ERROR:
-//                return java.util.logging.Level.SEVERE;
-//            default:
-//                throw new IllegalArgumentException();
-//        }
-//    }
-
-    public static void trace(final Object... messages) {
-        if (TRACE) {
-            log(Level.TRACE, messages);
-        }
-    }
-
-    public static void debug(final Object... messages) {
-        if (TRACE || DEBUG) {
-            log(Level.DEBUG, messages);
-        }
-    }
-
-    /**
-     * @since 2.7
-     */
-    public static void info(final Object... messages) {
-        log(Level.INFO, messages);
-    }
-
-    public static void warn(final Object... messages) {
-        log(Level.WARN, messages);
-    }
-
-    public static void error(final Object... messages) {
-        log(Level.ERROR, messages);
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/NonBlockingInputStream.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,311 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * This class wraps a regular input stream and allows it to appear as if it
- * is non-blocking; that is, reads can be performed against it that timeout
- * if no data is seen for a period of time.  This effect is achieved by having
- * a separate thread perform all non-blocking read requests and then
- * waiting on the thread to complete.
- *
- * <p>VERY IMPORTANT NOTES
- * <ul>
- *   <li> This class is not thread safe. It expects at most one reader.
- *   <li> The {@link #shutdown()} method must be called in order to shut down
- *          the thread that handles blocking I/O.
- * </ul>
- * @since 2.7
- * @author Scott C. Gray <scottgray1@gmail.com>
- */
-public class NonBlockingInputStream
-    extends InputStream
-    implements Runnable
-{
-    private InputStream in;               // The actual input stream
-    private int    ch   = -2;             // Recently read character
-
-    private boolean     threadIsReading      = false;
-    private boolean     isShutdown           = false;
-    private IOException exception            = null;
-    private boolean     nonBlockingEnabled;
-
-    /**
-     * Creates a <code>NonBlockingInputStream</code> out of a normal blocking
-     * stream. Note that this call also spawn a separate thread to perform the
-     * blocking I/O on behalf of the thread that is using this class. The
-     * {@link #shutdown()} method must be called in order to shut this thread down.
-     * @param in The input stream to wrap
-     * @param isNonBlockingEnabled If true, then the non-blocking methods
-     *   {@link #read(long)} and {@link #peek(long)} will be available and,
-     *   more importantly, the thread will be started to provide support for the
-     *   feature.  If false, then this class acts as a clean-passthru for the
-     *   underlying I/O stream and provides very little overhead.
-     */
-    public NonBlockingInputStream (InputStream in, boolean isNonBlockingEnabled) {
-        this.in                 = in;
-        this.nonBlockingEnabled = isNonBlockingEnabled;
-
-        if (isNonBlockingEnabled) {
-            Thread t = new Thread(this);
-            t.setName("NonBlockingInputStreamThread");
-            t.setDaemon(true);
-            t.start();
-        }
-    }
-
-    /**
-     * Shuts down the thread that is handling blocking I/O. Note that if the
-     * thread is currently blocked waiting for I/O it will not actually
-     * shut down until the I/O is received.  Shutting down the I/O thread
-     * does not prevent this class from being used, but causes the
-     * non-blocking methods to fail if called and causes {@link #isNonBlockingEnabled()}
-     * to return false.
-     */
-    public synchronized void shutdown() {
-        if (!isShutdown && nonBlockingEnabled) {
-            isShutdown = true;
-            notify();
-        }
-    }
-
-    /**
-     * Non-blocking is considered enabled if the feature is enabled and the
-     * I/O thread has not been shut down.
-     * @return true if non-blocking mode is enabled.
-     */
-    public boolean isNonBlockingEnabled() {
-        return nonBlockingEnabled && !isShutdown;
-    }
-
-    @Override
-    public void close() throws IOException {
-        /*
-         * The underlying input stream is closed first. This means that if the
-         * I/O thread was blocked waiting on input, it will be woken for us.
-         */
-        in.close();
-        shutdown();
-    }
-
-    @Override
-    public int read() throws IOException {
-        if (nonBlockingEnabled)
-            return read(0L, false);
-        return in.read ();
-    }
-
-    /**
-     * Peeks to see if there is a byte waiting in the input stream without
-     * actually consuming the byte.
-     *
-     * @param timeout The amount of time to wait, 0 == forever
-     * @return -1 on eof, -2 if the timeout expired with no available input
-     *   or the character that was read (without consuming it).
-     */
-    public int peek(long timeout) throws IOException {
-        if (!nonBlockingEnabled || isShutdown) {
-            throw new UnsupportedOperationException ("peek() "
-                + "cannot be called as non-blocking operation is disabled");
-        }
-        return read(timeout, true);
-    }
-
-    /**
-     * Attempts to read a character from the input stream for a specific
-     * period of time.
-     * @param timeout The amount of time to wait for the character
-     * @return The character read, -1 if EOF is reached, or -2 if the
-     *   read timed out.
-     */
-    public int read(long timeout) throws IOException {
-        if (!nonBlockingEnabled || isShutdown) {
-            throw new UnsupportedOperationException ("read() with timeout "
-                + "cannot be called as non-blocking operation is disabled");
-        }
-        return read(timeout, false);
-    }
-
-    /**
-     * Attempts to read a character from the input stream for a specific
-     * period of time.
-     * @param timeout The amount of time to wait for the character
-     * @return The character read, -1 if EOF is reached, or -2 if the
-     *   read timed out.
-     */
-    private synchronized int read(long timeout, boolean isPeek) throws IOException {
-        /*
-         * If the thread hit an IOException, we report it.
-         */
-        if (exception != null) {
-            assert ch == -2;
-            IOException toBeThrown = exception;
-            if (!isPeek)
-                exception = null;
-            throw toBeThrown;
-        }
-
-        /*
-         * If there was a pending character from the thread, then
-         * we send it. If the timeout is 0L or the thread was shut down
-         * then do a local read.
-         */
-        if (ch >= -1) {
-            assert exception == null;
-        }
-        else if ((timeout == 0L || isShutdown) && !threadIsReading) {
-            ch = in.read();
-        }
-        else {
-            /*
-             * If the thread isn't reading already, then ask it to do so.
-             */
-            if (!threadIsReading) {
-                threadIsReading = true;
-                notify();
-            }
-
-            boolean isInfinite = timeout <= 0L;
-
-            /*
-             * So the thread is currently doing the reading for us. So
-             * now we play the waiting game.
-             */
-            while (isInfinite || timeout > 0L)  {
-                long start = System.currentTimeMillis ();
-
-                try {
-                    wait(timeout);
-                }
-                catch (InterruptedException e) {
-                    /* IGNORED */
-                }
-
-                if (exception != null) {
-                    assert ch == -2;
-
-                    IOException toBeThrown = exception;
-                    if (!isPeek)
-                        exception = null;
-                    throw toBeThrown;
-                }
-
-                if (ch >= -1) {
-                    assert exception == null;
-                    break;
-                }
-
-                if (!isInfinite) {
-                    timeout -= System.currentTimeMillis() - start;
-                }
-            }
-        }
-
-        /*
-         * ch is the character that was just read. Either we set it because
-         * a local read was performed or the read thread set it (or failed to
-         * change it).  We will return it's value, but if this was a peek
-         * operation, then we leave it in place.
-         */
-        int ret = ch;
-        if (!isPeek) {
-            ch = -2;
-        }
-        return ret;
-    }
-
-    /**
-     * This version of read() is very specific to jline's purposes, it
-     * will always always return a single byte at a time, rather than filling
-     * the entire buffer.
-     */
-    @Override
-    public int read (byte[] b, int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return 0;
-        }
-
-        int c;
-        if (nonBlockingEnabled)
-            c = this.read(0L);
-        else
-            c = in.read();
-
-        if (c == -1) {
-            return -1;
-        }
-        b[off] = (byte)c;
-        return 1;
-    }
-
-    //@Override
-    public void run () {
-        Log.debug("NonBlockingInputStream start");
-        boolean needToShutdown = false;
-        boolean needToRead = false;
-
-        while (!needToShutdown) {
-
-            /*
-             * Synchronize to grab variables accessed by both this thread
-             * and the accessing thread.
-             */
-            synchronized (this) {
-                needToShutdown = this.isShutdown;
-                needToRead     = this.threadIsReading;
-
-                try {
-                    /*
-                     * Nothing to do? Then wait.
-                     */
-                    if (!needToShutdown && !needToRead) {
-                        wait(0);
-                    }
-                }
-                catch (InterruptedException e) {
-                    /* IGNORED */
-                }
-            }
-
-            /*
-             * We're not shutting down, but we need to read. This cannot
-             * happen while we are holding the lock (which we aren't now).
-             */
-            if (!needToShutdown && needToRead) {
-                int          charRead = -2;
-                IOException  failure = null;
-                try {
-                    charRead = in.read();
-                }
-                catch (IOException e) {
-                    failure = e;
-                }
-
-                /*
-                 * Re-grab the lock to update the state.
-                 */
-                synchronized (this) {
-                    exception       = failure;
-                    ch              = charRead;
-                    threadIsReading = false;
-                    notify();
-                }
-            }
-        }
-
-        Log.debug("NonBlockingInputStream shutdown");
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.lang.annotation.*;
-
-/**
- * Marker for reference which can be a null value.
- *
- * @since 2.7
- */
-@Documented
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
-public @interface Nullable
-{
-    String value() default "";
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-// Some bits lifted from Guava's ( http://code.google.com/p/guava-libraries/ ) Preconditions.
-
-/**
- * Preconditions.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.7
- */
-public class Preconditions
-{
-    public static <T> T checkNotNull(final T reference) {
-        if (reference == null) {
-            throw new NullPointerException();
-        }
-        return reference;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Manages the JLine shutdown-hook thread and tasks to execute on shutdown.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.7
- */
-public class ShutdownHooks
-{
-    public static final String JLINE_SHUTDOWNHOOK = "jline.shutdownhook";
-
-    private static final boolean enabled = Configuration.getBoolean(JLINE_SHUTDOWNHOOK, true);
-
-    private static final List<Task> tasks = new ArrayList<Task>();
-
-    private static Thread hook;
-
-    public static synchronized <T extends Task> T add(final T task) {
-        checkNotNull(task);
-
-        // If not enabled ignore
-        if (!enabled) {
-            Log.debug("Shutdown-hook is disabled; not installing: ", task);
-            return task;
-        }
-
-        // Install the hook thread if needed
-        if (hook == null) {
-            hook = addHook(new Thread("JLine Shutdown Hook")
-            {
-                @Override
-                public void run() {
-                    runTasks();
-                }
-            });
-        }
-
-        // Track the task
-        Log.debug("Adding shutdown-hook task: ", task);
-        tasks.add(task);
-
-        return task;
-    }
-
-    private static synchronized void runTasks() {
-        Log.debug("Running all shutdown-hook tasks");
-
-        // Iterate through copy of tasks list
-        for (Task task : tasks.toArray(new Task[tasks.size()])) {
-            Log.debug("Running task: ", task);
-            try {
-                task.run();
-            }
-            catch (Throwable e) {
-                Log.warn("Task failed", e);
-            }
-        }
-
-        tasks.clear();
-    }
-
-    private static Thread addHook(final Thread thread) {
-        Log.debug("Registering shutdown-hook: ", thread);
-        try {
-            Runtime.getRuntime().addShutdownHook(thread);
-        }
-        catch (AbstractMethodError e) {
-            // JDK 1.3+ only method. Bummer.
-            Log.debug("Failed to register shutdown-hook", e);
-        }
-        return thread;
-    }
-
-    public static synchronized void remove(final Task task) {
-        checkNotNull(task);
-
-        // ignore if not enabled or hook never installed
-        if (!enabled || hook == null) {
-            return;
-        }
-
-        // Drop the task
-        tasks.remove(task);
-
-        // If there are no more tasks, then remove the hook thread
-        if (tasks.isEmpty()) {
-            removeHook(hook);
-            hook = null;
-        }
-    }
-
-    private static void removeHook(final Thread thread) {
-        Log.debug("Removing shutdown-hook: ", thread);
-
-        try {
-            Runtime.getRuntime().removeShutdownHook(thread);
-        }
-        catch (AbstractMethodError e) {
-            // JDK 1.3+ only method. Bummer.
-            Log.debug("Failed to remove shutdown-hook", e);
-        }
-        catch (IllegalStateException e) {
-            // The VM is shutting down, not a big deal; ignore
-        }
-    }
-
-    /**
-     * Essentially a {@link Runnable} which allows running to throw an exception.
-     */
-    public static interface Task
-    {
-        void run() throws Exception;
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Method;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static jdk.internal.jline.internal.Preconditions.checkNotNull;
-
-/**
- * Provides access to terminal line settings via <tt>stty</tt>.
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:dwkemp@gmail.com">Dale Kemp</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:jbonofre@apache.org">Jean-Baptiste Onofr\u00E9</a>
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.0
- */
-public final class TerminalLineSettings
-{
-    public static final String JLINE_STTY = "jline.stty";
-
-    public static final String DEFAULT_STTY = "stty";
-
-    public static final String JLINE_SH = "jline.sh";
-
-    public static final String DEFAULT_SH = "sh";
-
-    private static final String UNDEFINED;
-
-    public static final String DEFAULT_TTY = "/dev/tty";
-
-    private static final boolean SUPPORTS_REDIRECT;
-
-    private static final Object REDIRECT_INHERIT;
-    private static final Method REDIRECT_INPUT_METHOD;
-
-    private static final Map<String, TerminalLineSettings> SETTINGS = new HashMap<String, TerminalLineSettings>();
-
-    static {
-        if (Configuration.isHpux()) {
-            UNDEFINED = "^-";
-        } else {
-            UNDEFINED = "undef";
-        }
-
-        boolean supportsRedirect;
-        Object redirectInherit = null;
-        Method redirectInputMethod = null;
-        try {
-            Class<?> redirect = Class.forName("java.lang.ProcessBuilder$Redirect");
-            redirectInherit = redirect.getField("INHERIT").get(null);
-            redirectInputMethod = ProcessBuilder.class.getMethod("redirectInput", redirect);
-            supportsRedirect = System.class.getMethod("console").invoke(null) != null;
-        } catch (Throwable t) {
-            supportsRedirect = false;
-        }
-        SUPPORTS_REDIRECT = supportsRedirect;
-        REDIRECT_INHERIT = redirectInherit;
-        REDIRECT_INPUT_METHOD = redirectInputMethod;
-    }
-
-    private String sttyCommand;
-
-    private String shCommand;
-
-    private String ttyDevice;
-
-    private String config;
-    private String initialConfig;
-
-    private long configLastFetched;
-
-    private boolean useRedirect;
-
-    @Deprecated
-    public TerminalLineSettings() throws IOException, InterruptedException {
-        this(DEFAULT_TTY);
-    }
-
-    @Deprecated
-    public TerminalLineSettings(String ttyDevice) throws IOException, InterruptedException {
-        this(ttyDevice, false);
-    }
-
-    private TerminalLineSettings(String ttyDevice, boolean unused) throws IOException, InterruptedException {
-        checkNotNull(ttyDevice);
-        this.sttyCommand = Configuration.getString(JLINE_STTY, DEFAULT_STTY);
-        this.shCommand = Configuration.getString(JLINE_SH, DEFAULT_SH);
-        this.ttyDevice = ttyDevice;
-        this.useRedirect = SUPPORTS_REDIRECT && DEFAULT_TTY.equals(ttyDevice);
-        this.initialConfig = get("-g").trim();
-        this.config = get("-a");
-        this.configLastFetched = System.currentTimeMillis();
-
-        Log.debug("Config: ", config);
-
-        // sanity check
-        if (config.length() == 0) {
-            throw new IOException(MessageFormat.format("Unrecognized stty code: {0}", config));
-        }
-    }
-
-    public static synchronized TerminalLineSettings getSettings(String device) throws IOException, InterruptedException {
-        TerminalLineSettings settings = SETTINGS.get(device);
-        if (settings == null) {
-            settings = new TerminalLineSettings(device, false);
-            SETTINGS.put(device, settings);
-        }
-        return settings;
-    }
-
-    public String getTtyDevice() {
-        return ttyDevice;
-    }
-
-    public String getConfig() {
-        return config;
-    }
-
-    public void restore() throws IOException, InterruptedException {
-        set(initialConfig);
-    }
-
-    public String get(final String args) throws IOException, InterruptedException {
-        checkNotNull(args);
-        return stty(args);
-    }
-
-    public void set(final String args) throws IOException, InterruptedException {
-        checkNotNull(args);
-        stty(args.split(" "));
-    }
-
-    public void set(final String... args) throws IOException, InterruptedException {
-        checkNotNull(args);
-        stty(args);
-    }
-
-    public void undef(final String name) throws IOException, InterruptedException {
-        checkNotNull(name);
-        stty(name, UNDEFINED);
-    }
-
-    /**
-     * <p>
-     * Get the value of a stty property, including the management of a cache.
-     * </p>
-     *
-     * @param name the stty property.
-     * @return the stty property value.
-     */
-    public int getProperty(String name) {
-        checkNotNull(name);
-        if (!fetchConfig(name)) {
-            return -1;
-        }
-        return getProperty(name, config);
-    }
-
-    public String getPropertyAsString(String name) {
-        checkNotNull(name);
-        if (!fetchConfig(name)) {
-            return null;
-        }
-        return getPropertyAsString(name, config);
-    }
-
-    private boolean fetchConfig(String name) {
-        long currentTime = System.currentTimeMillis();
-        try {
-            // tty properties are cached so we don't have to worry too much about getting term width/height
-            if (config == null || currentTime - configLastFetched > 1000) {
-                config = get("-a");
-            }
-        } catch (Exception e) {
-            if (e instanceof InterruptedException) {
-                Thread.currentThread().interrupt();
-            }
-            Log.debug("Failed to query stty ", name, "\n", e);
-            if (config == null) {
-                return false;
-            }
-        }
-
-        // always update the last fetched time and try to parse the output
-        if (currentTime - configLastFetched > 1000) {
-            configLastFetched = currentTime;
-        }
-        return true;
-    }
-
-    /**
-     * <p>
-     * Parses a stty output (provided by stty -a) and return the value of a given property.
-     * </p>
-     *
-     * @param name property name.
-     * @param stty string resulting of stty -a execution.
-     * @return value of the given property.
-     */
-    protected static String getPropertyAsString(String name, String stty) {
-        // try the first kind of regex
-        Pattern pattern = Pattern.compile(name + "\\s+=\\s+(.*?)[;\\n\\r]");
-        Matcher matcher = pattern.matcher(stty);
-        if (!matcher.find()) {
-            // try a second kind of regex
-            pattern = Pattern.compile(name + "\\s+([^;]*)[;\\n\\r]");
-            matcher = pattern.matcher(stty);
-            if (!matcher.find()) {
-                // try a second try of regex
-                pattern = Pattern.compile("(\\S*)\\s+" + name);
-                matcher = pattern.matcher(stty);
-                if (!matcher.find()) {
-                    return null;
-                }
-            }
-        }
-        return matcher.group(1);
-    }
-
-    protected static int getProperty(String name, String stty) {
-        String str = getPropertyAsString(name, stty);
-        return str != null ? parseControlChar(str) : -1;
-    }
-
-    private static int parseControlChar(String str) {
-        // under
-        if ("<undef>".equals(str)) {
-            return -1;
-        }
-        // octal
-        if (str.charAt(0) == '0') {
-            return Integer.parseInt(str, 8);
-        }
-        // decimal
-        if (str.charAt(0) >= '1' && str.charAt(0) <= '9') {
-            return Integer.parseInt(str, 10);
-        }
-        // control char
-        if (str.charAt(0) == '^') {
-            if (str.charAt(1) == '?') {
-                return 127;
-            } else {
-                return str.charAt(1) - 64;
-            }
-        } else if (str.charAt(0) == 'M' && str.charAt(1) == '-') {
-            if (str.charAt(2) == '^') {
-                if (str.charAt(3) == '?') {
-                    return 127 + 128;
-                } else {
-                    return str.charAt(3) - 64 + 128;
-                }
-            } else {
-                return str.charAt(2) + 128;
-            }
-        } else {
-            return str.charAt(0);
-        }
-    }
-
-    private String stty(final String... args) throws IOException, InterruptedException {
-        String[] s = new String[args.length + 1];
-        s[0] = sttyCommand;
-        System.arraycopy(args, 0, s, 1, args.length);
-        return exec(s);
-    }
-
-    private String exec(final String... cmd) throws IOException, InterruptedException {
-        checkNotNull(cmd);
-
-        Log.trace("Running: ", cmd);
-
-        Process p = null;
-        if (useRedirect) {
-            try {
-                p = inheritInput(new ProcessBuilder(cmd)).start();
-            } catch (Throwable t) {
-                useRedirect = false;
-            }
-        }
-        if (p == null) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < cmd.length; i++) {
-                if (i > 0) {
-                    sb.append(' ');
-                }
-                sb.append(cmd[i]);
-            }
-            sb.append(" < ");
-            sb.append(ttyDevice);
-            p = new ProcessBuilder(shCommand, "-c", sb.toString()).start();
-        }
-
-        String result = waitAndCapture(p);
-
-        Log.trace("Result: ", result);
-
-        return result;
-    }
-
-    private static ProcessBuilder inheritInput(ProcessBuilder pb) throws Exception {
-        REDIRECT_INPUT_METHOD.invoke(pb, REDIRECT_INHERIT);
-        return pb;
-    }
-
-    public static String waitAndCapture(Process p) throws IOException, InterruptedException {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        InputStream in = null;
-        InputStream err = null;
-        OutputStream out = null;
-        try {
-            int c;
-            in = p.getInputStream();
-            while ((c = in.read()) != -1) {
-                bout.write(c);
-            }
-            err = p.getErrorStream();
-            while ((c = err.read()) != -1) {
-                bout.write(c);
-            }
-            out = p.getOutputStream();
-            p.waitFor();
-        }
-        finally {
-            close(in, out, err);
-        }
-
-        return bout.toString();
-    }
-
-    private static void close(final Closeable... closeables) {
-        for (Closeable c : closeables) {
-            if (c != null) {
-                try {
-                    c.close();
-                } catch (Exception e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-}
-
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Marker annotation for members which are exposed for testing access.
- *
- * @since 2.7
- */
-@Retention(RUNTIME)
-@Target({TYPE, CONSTRUCTOR, METHOD, FIELD, PARAMETER})
-@Documented
-public @interface TestAccessible
-{
-    // empty
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-package jdk.internal.jline.internal;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * URL helpers.
- *
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
- * @since 2.7
- */
-public class Urls
-{
-    public static URL create(final String input) {
-        if (input == null) {
-            return null;
-        }
-        try {
-            return new URL(input);
-        }
-        catch (MalformedURLException e) {
-            return create(new File(input));
-        }
-    }
-
-    public static URL create(final File file) {
-        try {
-            return file != null ? file.toURI().toURL() : null;
-        }
-        catch (MalformedURLException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-}
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * Internal support.
- *
- * @since 2.0
- */
-package jdk.internal.jline.internal;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * http://www.opensource.org/licenses/bsd-license.php
- */
-/**
- * JLine 2.
- *
- * @since 2.0
- */
-package jdk.internal.jline;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.keymap;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+import jdk.internal.org.jline.reader.EndOfFileException;
+import jdk.internal.org.jline.utils.ClosedException;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+
+/**
+ * The BindingReader will transform incoming chars into
+ * key bindings
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class BindingReader {
+
+    protected final NonBlockingReader reader;
+    protected final StringBuilder opBuffer = new StringBuilder();
+    protected final Deque<Integer> pushBackChar = new ArrayDeque<>();
+    protected String lastBinding;
+
+    public BindingReader(NonBlockingReader reader) {
+        this.reader = reader;
+    }
+
+    /**
+     * Read from the input stream and decode an operation from the key map.
+     *
+     * The input stream will be read character by character until a matching
+     * binding can be found.  Characters that can't possibly be matched to
+     * any binding will be send with the {@link KeyMap#getNomatch()} binding.
+     * Unicode (&gt;= 128) characters will be matched to {@link KeyMap#getUnicode()}.
+     * If the current key sequence is ambiguous, i.e. the sequence is bound but
+     * it's also a prefix to other sequences, then the {@link KeyMap#getAmbiguousTimeout()}
+     * timeout will be used to wait for another incoming character.
+     * If a character comes, the disambiguation will be done.  If the timeout elapses
+     * and no character came in, or if the timeout is &lt;= 0, the current bound operation
+     * will be returned.
+     *
+     * @param keys the KeyMap to use for decoding the input stream
+     * @param <T> the type of bindings to be read
+     * @return the decoded binding or <code>null</code> if the end of
+     *         stream has been reached
+     */
+    public <T> T readBinding(KeyMap<T> keys) {
+        return readBinding(keys, null, true);
+    }
+
+    public <T> T readBinding(KeyMap<T> keys, KeyMap<T> local) {
+        return readBinding(keys, local, true);
+    }
+
+    public <T> T readBinding(KeyMap<T> keys, KeyMap<T> local, boolean block) {
+        lastBinding = null;
+        T o = null;
+        int[] remaining = new int[1];
+        boolean hasRead = false;
+        for (;;) {
+            if (local != null) {
+                o = local.getBound(opBuffer, remaining);
+            }
+            if (o == null && (local == null || remaining[0] >= 0)) {
+                o = keys.getBound(opBuffer, remaining);
+            }
+            // We have a binding and additional chars
+            if (o != null) {
+                if (remaining[0] >= 0) {
+                    runMacro(opBuffer.substring(opBuffer.length() - remaining[0]));
+                    opBuffer.setLength(opBuffer.length() - remaining[0]);
+                }
+                else {
+                    long ambiguousTimeout = keys.getAmbiguousTimeout();
+                    if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) {
+                        o = null;
+                    }
+                }
+                if (o != null) {
+                    lastBinding = opBuffer.toString();
+                    opBuffer.setLength(0);
+                    return o;
+                }
+                // We don't match anything
+            } else if (remaining[0] > 0) {
+                int cp = opBuffer.codePointAt(0);
+                String rem = opBuffer.substring(Character.charCount(cp));
+                lastBinding = opBuffer.substring(0, Character.charCount(cp));
+                // Unicode character
+                o = (cp >= KeyMap.KEYMAP_LENGTH) ? keys.getUnicode() : keys.getNomatch();
+                opBuffer.setLength(0);
+                opBuffer.append(rem);
+                if (o != null) {
+                    return o;
+                }
+            }
+
+            if (!block && hasRead) {
+                break;
+            }
+            int c = readCharacter();
+            if (c == -1) {
+                return null;
+            }
+            opBuffer.appendCodePoint(c);
+            hasRead = true;
+        }
+        return null;
+    }
+
+    /**
+     * Read a codepoint from the terminal.
+     *
+     * @return the character, or -1 if an EOF is received.
+     */
+    public int readCharacter() {
+        if (!pushBackChar.isEmpty()) {
+            return pushBackChar.pop();
+        }
+        try {
+            int c = NonBlockingReader.READ_EXPIRED;
+            int s = 0;
+            while (c == NonBlockingReader.READ_EXPIRED) {
+                c = reader.read(100L);
+                if (c >= 0 && Character.isHighSurrogate((char) c)) {
+                    s = c;
+                    c = NonBlockingReader.READ_EXPIRED;
+                }
+            }
+            return s != 0 ? Character.toCodePoint((char) s, (char) c) : c;
+        } catch (ClosedException e) {
+            throw new EndOfFileException(e);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public int peekCharacter(long timeout) {
+        if (!pushBackChar.isEmpty()) {
+            return pushBackChar.peek();
+        }
+        try {
+            return reader.peek(timeout);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public void runMacro(String macro) {
+        macro.codePoints().forEachOrdered(pushBackChar::addLast);
+    }
+
+    public String getCurrentBuffer() {
+        return opBuffer.toString();
+    }
+
+    public String getLastBinding() {
+        return lastBinding;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.keymap;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.Curses;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+
+/**
+ * The KeyMap class contains all bindings from keys to operations.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.6
+ */
+public class KeyMap<T> {
+
+    public static final int KEYMAP_LENGTH = 128;
+    public static final long DEFAULT_AMBIGUOUS_TIMEOUT = 1000L;
+
+    private Object[] mapping = new Object[KEYMAP_LENGTH];
+    private T anotherKey = null;
+    private T unicode;
+    private T nomatch;
+    private long ambiguousTimeout = DEFAULT_AMBIGUOUS_TIMEOUT;
+
+    public static String display(String key) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("\"");
+        for (int i = 0; i < key.length(); i++) {
+            char c = key.charAt(i);
+            if (c < 32) {
+                sb.append('^');
+                sb.append((char) (c + 'A' - 1));
+            } else if (c == 127) {
+                sb.append("^?");
+            } else if (c == '^' || c == '\\') {
+                sb.append('\\').append(c);
+            } else if (c >= 128) {
+                sb.append(String.format("\\u%04x", (int) c));
+            } else {
+                sb.append(c);
+            }
+        }
+        sb.append("\"");
+        return sb.toString();
+    }
+
+    public static String translate(String str) {
+        int i;
+        if (!str.isEmpty()) {
+            char c = str.charAt(0);
+            if ((c == '\'' || c == '"') && str.charAt(str.length() - 1) == c) {
+                str = str.substring(1, str.length() - 1);
+            }
+        }
+        StringBuilder keySeq = new StringBuilder();
+        for (i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c == '\\') {
+                if (++i >= str.length()) {
+                    break;
+                }
+                c = str.charAt(i);
+                switch (c) {
+                    case 'a':
+                        c = 0x07;
+                        break;
+                    case 'b':
+                        c = '\b';
+                        break;
+                    case 'd':
+                        c = 0x7f;
+                        break;
+                    case 'e':
+                    case 'E':
+                        c = 0x1b;
+                        break;
+                    case 'f':
+                        c = '\f';
+                        break;
+                    case 'n':
+                        c = '\n';
+                        break;
+                    case 'r':
+                        c = '\r';
+                        break;
+                    case 't':
+                        c = '\t';
+                        break;
+                    case 'v':
+                        c = 0x0b;
+                        break;
+                    case '\\':
+                        c = '\\';
+                        break;
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                        c = 0;
+                        for (int j = 0; j < 3; j++, i++) {
+                            if (i >= str.length()) {
+                                break;
+                            }
+                            int k = Character.digit(str.charAt(i), 8);
+                            if (k < 0) {
+                                break;
+                            }
+                            c = (char) (c * 8 + k);
+                        }
+                        i--;
+                        c &= 0xFF;
+                        break;
+                    case 'x':
+                        i++;
+                        c = 0;
+                        for (int j = 0; j < 2; j++, i++) {
+                            if (i >= str.length()) {
+                                break;
+                            }
+                            int k = Character.digit(str.charAt(i), 16);
+                            if (k < 0) {
+                                break;
+                            }
+                            c = (char) (c * 16 + k);
+                        }
+                        i--;
+                        c &= 0xFF;
+                        break;
+                    case 'u':
+                        i++;
+                        c = 0;
+                        for (int j = 0; j < 4; j++, i++) {
+                            if (i >= str.length()) {
+                                break;
+                            }
+                            int k = Character.digit(str.charAt(i), 16);
+                            if (k < 0) {
+                                break;
+                            }
+                            c = (char) (c * 16 + k);
+                        }
+                        break;
+                    case 'C':
+                        if (++i >= str.length()) {
+                            break;
+                        }
+                        c = str.charAt(i);
+                        if (c == '-') {
+                            if (++i >= str.length()) {
+                                break;
+                            }
+                            c = str.charAt(i);
+                        }
+                        c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f);
+                        break;
+                }
+            } else if (c == '^') {
+                if (++i >= str.length()) {
+                    break;
+                }
+                c = str.charAt(i);
+                if (c != '^') {
+                    c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f);
+                }
+            }
+            keySeq.append(c);
+        }
+        return keySeq.toString();
+    }
+
+    public static Collection<String> range(String range) {
+        String[] keys = range.split("-");
+        if (keys.length != 2) {
+            return null;
+        }
+        keys[0] = translate(keys[0]);
+        keys[1] = translate(keys[1]);
+        if (keys[0].length() != keys[1].length()) {
+            return null;
+        }
+        String pfx;
+        if (keys[0].length() > 1) {
+            pfx = keys[0].substring(0, keys[0].length() - 1);
+            if (!keys[1].startsWith(pfx)) {
+                return null;
+            }
+        } else {
+            pfx = "";
+        }
+        char c0 = keys[0].charAt(keys[0].length() - 1);
+        char c1 = keys[1].charAt(keys[1].length() - 1);
+        if (c0 > c1) {
+            return null;
+        }
+        Collection<String> seqs = new ArrayList<>();
+        for (char c = c0; c <= c1; c++) {
+            seqs.add(pfx + c);
+        }
+        return seqs;
+    }
+
+
+    public static String esc() {
+        return "\033";
+    }
+
+    public static String alt(char c) {
+        return "\033" + c;
+    }
+
+    public static String alt(String c) {
+        return "\033" + c;
+    }
+
+    public static String del() {
+        return "\177";
+    }
+
+    public static String ctrl(char key) {
+        return key == '?' ? del() : Character.toString((char) (Character.toUpperCase(key) & 0x1f));
+    }
+
+    public static String key(Terminal terminal, Capability capability) {
+        return Curses.tputs(terminal.getStringCapability(capability));
+    }
+
+    public static final Comparator<String> KEYSEQ_COMPARATOR = (s1, s2) -> {
+        int len1 = s1.length();
+        int len2 = s2.length();
+        int lim = Math.min(len1, len2);
+        int k = 0;
+        while (k < lim) {
+            char c1 = s1.charAt(k);
+            char c2 = s2.charAt(k);
+            if (c1 != c2) {
+                int l = len1 - len2;
+                return l != 0 ? l : c1 - c2;
+            }
+            k++;
+        }
+        return len1 - len2;
+    };
+
+    //
+    // Methods
+    //
+
+
+    public T getUnicode() {
+        return unicode;
+    }
+
+    public void setUnicode(T unicode) {
+        this.unicode = unicode;
+    }
+
+    public T getNomatch() {
+        return nomatch;
+    }
+
+    public void setNomatch(T nomatch) {
+        this.nomatch = nomatch;
+    }
+
+    public long getAmbiguousTimeout() {
+        return ambiguousTimeout;
+    }
+
+    public void setAmbiguousTimeout(long ambiguousTimeout) {
+        this.ambiguousTimeout = ambiguousTimeout;
+    }
+
+    public T getAnotherKey() {
+        return anotherKey;
+    }
+
+    public Map<String, T> getBoundKeys() {
+        Map<String, T> bound = new TreeMap<>(KEYSEQ_COMPARATOR);
+        doGetBoundKeys(this, "", bound);
+        return bound;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> void doGetBoundKeys(KeyMap<T> keyMap, String prefix, Map<String, T> bound) {
+        if (keyMap.anotherKey != null) {
+            bound.put(prefix, keyMap.anotherKey);
+        }
+        for (int c = 0; c < keyMap.mapping.length; c++) {
+            if (keyMap.mapping[c] instanceof KeyMap) {
+                doGetBoundKeys((KeyMap<T>) keyMap.mapping[c],
+                        prefix + (char) (c),
+                        bound);
+            } else if (keyMap.mapping[c] != null) {
+                bound.put(prefix + (char) (c), (T) keyMap.mapping[c]);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public T getBound(CharSequence keySeq, int[] remaining) {
+        remaining[0] = -1;
+        if (keySeq != null && keySeq.length() > 0) {
+            char c = keySeq.charAt(0);
+            if (c >= mapping.length) {
+                remaining[0] = Character.codePointCount(keySeq, 0, keySeq.length());
+                return null;
+            } else {
+                if (mapping[c] instanceof KeyMap) {
+                    CharSequence sub = keySeq.subSequence(1, keySeq.length());
+                    return ((KeyMap<T>) mapping[c]).getBound(sub, remaining);
+                } else if (mapping[c] != null) {
+                    remaining[0] = keySeq.length() - 1;
+                    return (T) mapping[c];
+                } else {
+                    remaining[0] = keySeq.length();
+                    return anotherKey;
+                }
+            }
+        } else {
+            return anotherKey;
+        }
+    }
+
+    public T getBound(CharSequence keySeq) {
+        int[] remaining = new int[1];
+        T res = getBound(keySeq, remaining);
+        return remaining[0] <= 0 ? res : null;
+    }
+
+    public void bindIfNotBound(T function, CharSequence keySeq) {
+        if (function != null && keySeq != null) {
+            bind(this, keySeq, function, true);
+        }
+    }
+
+    public void bind(T function, CharSequence... keySeqs) {
+        for (CharSequence keySeq : keySeqs) {
+            bind(function, keySeq);
+        }
+    }
+
+    public void bind(T function, Iterable<? extends CharSequence> keySeqs) {
+        for (CharSequence keySeq : keySeqs) {
+            bind(function, keySeq);
+        }
+    }
+
+    public void bind(T function, CharSequence keySeq) {
+        if (keySeq != null) {
+            if (function == null) {
+                unbind(keySeq);
+            } else {
+                bind(this, keySeq, function, false);
+            }
+        }
+    }
+
+    public void unbind(CharSequence... keySeqs) {
+        for (CharSequence keySeq : keySeqs) {
+            unbind(keySeq);
+        }
+    }
+
+    public void unbind(CharSequence keySeq) {
+        if (keySeq != null) {
+            unbind(this, keySeq);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T unbind(KeyMap<T> map, CharSequence keySeq) {
+        KeyMap<T> prev = null;
+        if (keySeq != null && keySeq.length() > 0) {
+            for (int i = 0; i < keySeq.length() - 1; i++) {
+                char c = keySeq.charAt(i);
+                if (c > map.mapping.length) {
+                    return null;
+                }
+                if (!(map.mapping[c] instanceof KeyMap)) {
+                    return null;
+                }
+                prev = map;
+                map = (KeyMap<T>) map.mapping[c];
+            }
+            char c = keySeq.charAt(keySeq.length() - 1);
+            if (c > map.mapping.length) {
+                return null;
+            }
+            if (map.mapping[c] instanceof KeyMap) {
+                KeyMap<?> sub = (KeyMap) map.mapping[c];
+                Object res = sub.anotherKey;
+                sub.anotherKey = null;
+                return (T) res;
+            } else {
+                Object res = map.mapping[c];
+                map.mapping[c] = null;
+                int nb = 0;
+                for (int i = 0; i < map.mapping.length; i++) {
+                    if (map.mapping[i] != null) {
+                        nb++;
+                    }
+                }
+                if (nb == 0 && prev != null) {
+                    prev.mapping[keySeq.charAt(keySeq.length() - 2)] = map.anotherKey;
+                }
+                return (T) res;
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> void bind(KeyMap<T> map, CharSequence keySeq, T function, boolean onlyIfNotBound) {
+        if (keySeq != null && keySeq.length() > 0) {
+            for (int i = 0; i < keySeq.length(); i++) {
+                char c = keySeq.charAt(i);
+                if (c >= map.mapping.length) {
+                    return;
+                }
+                if (i < keySeq.length() - 1) {
+                    if (!(map.mapping[c] instanceof KeyMap)) {
+                        KeyMap<T> m = new KeyMap<>();
+                        m.anotherKey = (T) map.mapping[c];
+                        map.mapping[c] = m;
+                    }
+                    map = (KeyMap) map.mapping[c];
+                } else {
+                    if (map.mapping[c] instanceof KeyMap) {
+                        ((KeyMap) map.mapping[c]).anotherKey = function;
+                    } else {
+                        Object op = map.mapping[c];
+                        if (!onlyIfNotBound || op == null) {
+                            map.mapping[c] = function;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * Marker interface for objects bound to key sequences.
+ *
+ * @see Macro
+ * @see Reference
+ * @see Widget
+ * @see org.jline.keymap.KeyMap
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public interface Binding {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+public interface Buffer {
+
+    /*
+     * Read access
+     */
+
+    int cursor();
+
+    int atChar(int i);
+
+    int length();
+
+    int currChar();
+
+    int prevChar();
+
+    int nextChar();
+
+    /*
+     * Movement
+     */
+
+    boolean cursor(int position);
+
+    int move(int num);
+
+    boolean up();
+
+    boolean down();
+
+    boolean moveXY(int dx, int dy);
+
+    /*
+     * Modification
+     */
+
+    boolean clear();
+
+    boolean currChar(int c);
+
+    void write(int c);
+
+    void write(int c, boolean overTyping);
+
+    void write(CharSequence str);
+
+    void write(CharSequence str, boolean overTyping);
+
+    boolean backspace();
+
+    int backspace(int num);
+
+    boolean delete();
+
+    int delete(int num);
+
+    /*
+     * String
+     */
+
+    String substring(int start);
+
+    String substring(int start, int end);
+
+    String upToCursor();
+
+    String toString();
+
+    /*
+     * Copy
+     */
+
+    Buffer copy();
+
+    void copyFrom(Buffer buffer);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.util.Objects;
+
+/**
+ * A completion candidate.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class Candidate implements Comparable<Candidate> {
+
+    private final String value;
+    private final String displ;
+    private final String group;
+    private final String descr;
+    private final String suffix;
+    private final String key;
+    private final boolean complete;
+
+    /**
+     * Simple constructor with only a single String as an argument.
+     *
+     * @param value the candidate
+     */
+    public Candidate(String value) {
+        this(value, value, null, null, null, null, true);
+    }
+
+    /**
+     * Constructs a new Candidate.
+     *
+     * @param value the value
+     * @param displ the display string
+     * @param group the group
+     * @param descr the description
+     * @param suffix the suffix
+     * @param key the key
+     * @param complete the complete flag
+     */
+    public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
+        Objects.requireNonNull(value);
+        this.value = value;
+        this.displ = displ;
+        this.group = group;
+        this.descr = descr;
+        this.suffix = suffix;
+        this.key = key;
+        this.complete = complete;
+    }
+
+    /**
+     * The value that will be used for the actual completion.
+     * This string should not contain ANSI sequences.
+     * @return the value
+     */
+    public String value() {
+        return value;
+    }
+
+    /**
+     * The string that will be displayed to the user.
+     * This string may contain ANSI sequences.
+     * @return the display string
+     */
+    public String displ() {
+        return displ;
+    }
+
+    /**
+     * The group name for this candidate.
+     * Candidates can be grouped together and this string is used
+     * as a key for the group and displayed to the user.
+     * @return the group
+     *
+     * @see LineReader.Option#GROUP
+     * @see LineReader.Option#AUTO_GROUP
+     */
+    public String group() {
+        return group;
+    }
+
+    /**
+     * Description of this candidate, usually a small help message
+     * to understand the meaning of this candidate.
+     * This string may contain ANSI sequences.
+     * @return the description
+     */
+    public String descr() {
+        return descr;
+    }
+
+    /**
+     * The suffix is added when this candidate is displayed.
+     * However, if the next character entered does not match,
+     * the suffix will be automatically removed.
+     * This string should not contain ANSI sequences.
+     * @return the suffix
+     *
+     * @see LineReader.Option#AUTO_REMOVE_SLASH
+     * @see LineReader#REMOVE_SUFFIX_CHARS
+     */
+    public String suffix() {
+        return suffix;
+    }
+
+    /**
+     * Candidates which have the same key will be merged together.
+     * For example, if a command has multiple aliases, they can be merged
+     * if they are using the same key.
+     * @return the key
+     */
+    public String key() {
+        return key;
+    }
+
+    /**
+     * Boolean indicating whether this candidate is complete or
+     * if the completer may further expand the candidate value
+     * after this candidate has been selected.
+     * This can be the case when completing folders for example.
+     * If the candidate is complete and is selected, a space
+     * separator will be added.
+     * @return the completion flag
+     */
+    public boolean complete() {
+        return complete;
+    }
+
+    @Override
+    public int compareTo(Candidate o) {
+        return value.compareTo(o.value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.util.List;
+
+/**
+ * A completer is the mechanism by which tab-completion candidates will be resolved.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.3
+ */
+public interface Completer
+{
+    /**
+     * Populates <i>candidates</i> with a list of possible completions for the <i>command line</i>.
+     *
+     * The list of candidates will be sorted and filtered by the LineReader, so that
+     * the list of candidates displayed to the user will usually be smaller than
+     * the list given by the completer.  Thus it is not necessary for the completer
+     * to do any matching based on the current buffer.  On the contrary, in order
+     * for the typo matcher to work, all possible candidates for the word being
+     * completed should be returned.
+     *
+     * @param reader        The line reader
+     * @param line          The parsed command line
+     * @param candidates    The {@link List} of candidates to populate
+     */
+    void complete(LineReader reader, ParsedLine line, List<Candidate> candidates);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules
+ * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate
+ * should be escaped/quoted.
+ *
+ * @author Eric Bottard
+ */
+public interface CompletingParsedLine extends ParsedLine {
+
+    CharSequence escape(CharSequence candidate, boolean complete);
+
+    int rawWordCursor();
+
+    int rawWordLength();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package jdk.internal.org.jline.reader;
+
+public class EOFError extends SyntaxError {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String missing;
+
+    public EOFError(int line, int column, String message) {
+        this(line, column, message, null);
+    }
+
+    public EOFError(int line, int column, String message, String missing) {
+        super(line, column, message);
+        this.missing = missing;
+    }
+
+    public String getMissing() {
+        return missing;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * This exception is thrown by {@link LineReader#readLine} when
+ * user the user types ctrl-D).
+ */
+public class EndOfFileException extends RuntimeException {
+
+    private static final long serialVersionUID = 528485360925144689L;
+
+    public EndOfFileException() {
+    }
+
+    public EndOfFileException(String message) {
+        super(message);
+    }
+
+    public EndOfFileException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public EndOfFileException(Throwable cause) {
+        super(cause);
+    }
+
+    public EndOfFileException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+public interface Expander {
+
+    String expandHistory(History history, String line);
+
+    String expandVar(String word);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import jdk.internal.org.jline.utils.AttributedString;
+
+public interface Highlighter {
+
+    AttributedString highlight(LineReader reader, String buffer);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Console history.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public interface History extends Iterable<History.Entry>
+{
+
+    /**
+     * Initialize the history for the given reader.
+     * @param reader the reader to attach to
+     */
+    void attach(LineReader reader);
+
+    /**
+     * Load history.
+     * @throws IOException if a problem occurs
+     */
+    void load() throws IOException;
+
+    /**
+     * Save history.
+     * @throws IOException if a problem occurs
+     */
+    void save() throws IOException;
+
+    /**
+     * Purge history.
+     * @throws IOException if a problem occurs
+     */
+    void purge() throws IOException;
+
+
+    int size();
+
+    default boolean isEmpty() {
+        return size() == 0;
+    }
+
+    int index();
+
+    int first();
+
+    int last();
+
+    String get(int index);
+
+    default void add(String line) {
+        add(Instant.now(), line);
+    }
+
+    void add(Instant time, String line);
+
+    /**
+     * Check if an entry should be persisted or not.
+     *
+     * @param entry the entry to check
+     * @return <code>true</code> if the given entry should be persisted, <code>false</code> otherwise
+     */
+    default boolean isPersistable(Entry entry) {
+        return true;
+    }
+
+    //
+    // Entries
+    //
+
+    interface Entry
+    {
+        int index();
+
+        Instant time();
+
+        String line();
+    }
+
+    ListIterator<Entry> iterator(int index);
+
+    default ListIterator<Entry> iterator() {
+        return iterator(first());
+    }
+
+    default Iterator<Entry> reverseIterator() {
+        return reverseIterator(last());
+    }
+
+    default Iterator<Entry> reverseIterator(int index) {
+        return new Iterator<Entry>() {
+            private final ListIterator<Entry> it = iterator(index + 1);
+            @Override
+            public boolean hasNext() {
+                return it.hasPrevious();
+            }
+            @Override
+            public Entry next() {
+                return it.previous();
+            }
+        };
+    }
+
+    //
+    // Navigation
+    //
+
+    /**
+     * Return the content of the current buffer.
+     *
+     * @return the content of the current buffer
+     */
+    String current();
+
+    /**
+     * Move the pointer to the previous element in the buffer.
+     *
+     * @return true if we successfully went to the previous element
+     */
+    boolean previous();
+
+    /**
+     * Move the pointer to the next element in the buffer.
+     *
+     * @return true if we successfully went to the next element
+     */
+    boolean next();
+
+    /**
+     * Moves the history index to the first entry.
+     *
+     * @return Return false if there are no iterator in the history or if the
+     * history is already at the beginning.
+     */
+    boolean moveToFirst();
+
+    /**
+     * This moves the history to the last entry. This entry is one position
+     * before the moveToEnd() position.
+     *
+     * @return Returns false if there were no history iterator or the history
+     * index was already at the last entry.
+     */
+    boolean moveToLast();
+
+    /**
+     * Move to the specified index in the history
+     *
+     * @param index The index to move to.
+     * @return      Returns true if the index was moved.
+     */
+    boolean moveTo(int index);
+
+    /**
+     * Move to the end of the history buffer. This will be a blank entry, after
+     * all of the other iterator.
+     */
+    void moveToEnd();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.io.InputStream;
+import java.util.Map;
+import java.util.function.IntConsumer;
+
+import jdk.internal.org.jline.keymap.KeyMap;
+import jdk.internal.org.jline.terminal.MouseEvent;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.AttributedString;
+
+/** Read lines from the console, with input editing.
+ *
+ * <h3>Thread safety</h3>
+ * The <code>LineReader</code> implementations are not thread safe,
+ * thus you should not attempt to use a single reader in several threads.
+ * Any attempt to call one of the <code>readLine</code> call while one is
+ * already executing in a different thread will immediately result in an
+ * <code>IllegalStateException</code> being thrown.  Other calls may lead to
+ * unknown behaviors. There is one exception though: users are allowed to call
+ * {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at
+ * any time to allow text to be printed above the current prompt.
+ *
+ * <h3>Prompt strings</h3>
+ * It is traditional for an interactive console-based program
+ * to print a short prompt string to signal that the user is expected
+ * to type a command.  JLine supports 3 kinds of prompt string:
+ * <ul>
+ * <li> The normal prompt at the start (left) of the initial line of a command.
+ * <li> An optional right prompt at the right border of the initial line.
+ * <li> A start (left) prompt for continuation lines.  I.e. the lines
+ * after the first line of a multi-line command.
+ * </ul>
+ * <p>
+ * All of these are specified with prompt templates,
+ * which are similar to {@code printf} format strings,
+ * using the character {@code '%'} to indicate special functionality.
+ * </p>
+ * The pattern may include ANSI escapes.
+ * It may include these template markers:
+ * <dl>
+ * <dt>{@code %N}</dt>
+ * <dd>A line number. This is the sum of {@code getLineNumber()}
+ *   and a counter starting with 1 for the first continuation line.
+ * </dd>
+ * <dt>{@code %M}</dt>
+ * <dd>A short word explaining what is "missing". This is supplied from
+ * the {@link EOFError#getMissing()} method, if provided.
+ * Defaults to an empty string.
+ * </dd>
+ * <dt>{@code %}<var>n</var>{@code P}<var>c</var></dt>
+ * <dd>Insert padding at this possion, repeating the following
+ *   character <var>c</var> as needed to bring the total prompt
+ *   column width as specified by the digits <var>n</var>.
+ * </dd>
+ * <dt>{@code %P}<var>c</var></dt>
+ * <dd>As before, but use width from the initial prompt.
+ * </dd>
+ * <dt>{@code %%}</dt>
+ * <dd>A literal {@code '%'}.
+ * </dd>
+ * <dt><code>%{</code></dt><dt><code>%}</code></dt>
+ * <dd>Text between a <code>%{</code>...<code>%}</code> pair is printed as
+ * part of a prompt, but not interpreted by JLine
+ * (except that {@code '%'}-escapes are processed).  The text is assumed
+ * to take zero columns (not move the cursor).  If it changes the style,
+ * you're responsible for changing it back.  Standard ANSI escape sequences
+ * do not need to be within a <code>%{</code>...<code>%}</code> pair
+ * (though can be) since JLine knows how to deal with them.  However,
+ * these delimiters are needed for unusual non-standard escape sequences.
+ * </dd>
+ * </dl>
+ */
+
+public interface LineReader {
+
+    /**
+     * System property that can be set to avoid a warning being logged
+     * when using a Parser which does not return {@link CompletingParsedLine} objects.
+     */
+    String PROP_SUPPORT_PARSEDLINE = "org.jline.reader.support.parsedline";
+
+    //
+    // Widget names
+    //
+    String CALLBACK_INIT = "callback-init";
+    String CALLBACK_FINISH = "callback-finish";
+    String CALLBACK_KEYMAP = "callback-keymap";
+
+    String ACCEPT_LINE = "accept-line";
+    String ARGUMENT_BASE = "argument-base";
+    String BACKWARD_CHAR = "backward-char";
+    String BACKWARD_DELETE_CHAR = "backward-delete-char";
+    String BACKWARD_DELETE_WORD = "backward-delete-word";
+    String BACKWARD_KILL_LINE = "backward-kill-line";
+    String BACKWARD_KILL_WORD = "backward-kill-word";
+    String BACKWARD_WORD = "backward-word";
+    String BEEP = "beep";
+    String BEGINNING_OF_BUFFER_OR_HISTORY = "beginning-of-buffer-or-history";
+    String BEGINNING_OF_HISTORY = "beginning-of-history";
+    String BEGINNING_OF_LINE = "beginning-of-line";
+    String BEGINNING_OF_LINE_HIST = "beginning-of-line-hist";
+    String CAPITALIZE_WORD = "capitalize-word";
+    String CHARACTER_SEARCH = "character-search";
+    String CHARACTER_SEARCH_BACKWARD = "character-search-backward";
+    String CLEAR = "clear";
+    String CLEAR_SCREEN = "clear-screen";
+    String COMPLETE_PREFIX = "complete-prefix";
+    String COMPLETE_WORD = "complete-word";
+    String COPY_PREV_WORD = "copy-prev-word";
+    String COPY_REGION_AS_KILL = "copy-region-as-kill";
+    String DELETE_CHAR = "delete-char";
+    String DELETE_CHAR_OR_LIST = "delete-char-or-list";
+    String DELETE_WORD = "delete-word";
+    String DIGIT_ARGUMENT = "digit-argument";
+    String DO_LOWERCASE_VERSION = "do-lowercase-version";
+    String DOWN_CASE_WORD = "down-case-word";
+    String DOWN_HISTORY = "down-history";
+    String DOWN_LINE = "down-line";
+    String DOWN_LINE_OR_HISTORY = "down-line-or-history";
+    String DOWN_LINE_OR_SEARCH = "down-line-or-search";
+    String EMACS_BACKWARD_WORD = "emacs-backward-word";
+    String EMACS_EDITING_MODE = "emacs-editing-mode";
+    String EMACS_FORWARD_WORD = "emacs-forward-word";
+    String END_OF_BUFFER_OR_HISTORY = "end-of-buffer-or-history";
+    String END_OF_HISTORY = "end-of-history";
+    String END_OF_LINE = "end-of-line";
+    String END_OF_LINE_HIST = "end-of-line-hist";
+    String EXCHANGE_POINT_AND_MARK = "exchange-point-and-mark";
+    String EXECUTE_NAMED_CMD = "execute-named-cmd";
+    String EXPAND_HISTORY = "expand-history";
+    String EXPAND_OR_COMPLETE = "expand-or-complete";
+    String EXPAND_OR_COMPLETE_PREFIX = "expand-or-complete-prefix";
+    String EXPAND_WORD = "expand-word";
+    String FRESH_LINE = "fresh-line";
+    String FORWARD_CHAR = "forward-char";
+    String FORWARD_WORD = "forward-word";
+    String HISTORY_BEGINNING_SEARCH_BACKWARD = "history-beginning-search-backward";
+    String HISTORY_BEGINNING_SEARCH_FORWARD = "history-beginning-search-forward";
+    String HISTORY_INCREMENTAL_PATTERN_SEARCH_BACKWARD = "history-incremental-pattern-search-backward";
+    String HISTORY_INCREMENTAL_PATTERN_SEARCH_FORWARD = "history-incremental-pattern-search-forward";
+    String HISTORY_INCREMENTAL_SEARCH_BACKWARD = "history-incremental-search-backward";
+    String HISTORY_INCREMENTAL_SEARCH_FORWARD = "history-incremental-search-forward";
+    String HISTORY_SEARCH_BACKWARD = "history-search-backward";
+    String HISTORY_SEARCH_FORWARD = "history-search-forward";
+    String INSERT_CLOSE_CURLY = "insert-close-curly";
+    String INSERT_CLOSE_PAREN = "insert-close-paren";
+    String INSERT_CLOSE_SQUARE = "insert-close-square";
+    String INFER_NEXT_HISTORY = "infer-next-history";
+    String INSERT_COMMENT = "insert-comment";
+    String INSERT_LAST_WORD = "insert-last-word";
+    String KILL_BUFFER = "kill-buffer";
+    String KILL_LINE = "kill-line";
+    String KILL_REGION = "kill-region";
+    String KILL_WHOLE_LINE = "kill-whole-line";
+    String KILL_WORD = "kill-word";
+    String LIST_CHOICES = "list-choices";
+    String LIST_EXPAND = "list-expand";
+    String MAGIC_SPACE = "magic-space";
+    String MENU_EXPAND_OR_COMPLETE = "menu-expand-or-complete";
+    String MENU_COMPLETE = "menu-complete";
+    String MENU_SELECT = "menu-select";
+    String NEG_ARGUMENT = "neg-argument";
+    String OVERWRITE_MODE = "overwrite-mode";
+    String PUT_REPLACE_SELECTION = "put-replace-selection";
+    String QUOTED_INSERT = "quoted-insert";
+    String READ_COMMAND = "read-command";
+    String RECURSIVE_EDIT = "recursive-edit";
+    String REDISPLAY = "redisplay";
+    String REDRAW_LINE = "redraw-line";
+    String REDO = "redo";
+    String REVERSE_MENU_COMPLETE = "reverse-menu-complete";
+    String SELF_INSERT = "self-insert";
+    String SELF_INSERT_UNMETA = "self-insert-unmeta";
+    String SEND_BREAK = "abort";
+    String SET_LOCAL_HISTORY = "set-local-history";
+    String SET_MARK_COMMAND = "set-mark-command";
+    String SPELL_WORD = "spell-word";
+    String SPLIT_UNDO = "split-undo";
+    String TRANSPOSE_CHARS = "transpose-chars";
+    String TRANSPOSE_WORDS = "transpose-words";
+    String UNDEFINED_KEY = "undefined-key";
+    String UNDO = "undo";
+    String UNIVERSAL_ARGUMENT = "universal-argument";
+    String UP_CASE_WORD = "up-case-word";
+    String UP_HISTORY = "up-history";
+    String UP_LINE = "up-line";
+    String UP_LINE_OR_HISTORY = "up-line-or-history";
+    String UP_LINE_OR_SEARCH = "up-line-or-search";
+    String VI_ADD_EOL = "vi-add-eol";
+    String VI_ADD_NEXT = "vi-add-next";
+    String VI_BACKWARD_BLANK_WORD = "vi-backward-blank-word";
+    String VI_BACKWARD_BLANK_WORD_END = "vi-backward-blank-word-end";
+    String VI_BACKWARD_CHAR = "vi-backward-char";
+    String VI_BACKWARD_DELETE_CHAR = "vi-backward-delete-char";
+    String VI_BACKWARD_KILL_WORD = "vi-backward-kill-word";
+    String VI_BACKWARD_WORD = "vi-backward-word";
+    String VI_BACKWARD_WORD_END = "vi-backward-word-end";
+    String VI_BEGINNING_OF_LINE = "vi-beginning-of-line";
+    String VI_CHANGE = "vi-change-to";
+    String VI_CHANGE_EOL = "vi-change-eol";
+    String VI_CHANGE_WHOLE_LINE = "vi-change-whole-line";
+    String VI_CMD_MODE = "vi-cmd-mode";
+    String VI_DELETE = "vi-delete";
+    String VI_DELETE_CHAR = "vi-delete-char";
+    String VI_DIGIT_OR_BEGINNING_OF_LINE = "vi-digit-or-beginning-of-line";
+    String VI_DOWN_LINE_OR_HISTORY = "vi-down-line-or-history";
+    String VI_END_OF_LINE = "vi-end-of-line";
+    String VI_FETCH_HISTORY = "vi-fetch-history";
+    String VI_FIND_NEXT_CHAR = "vi-find-next-char";
+    String VI_FIND_NEXT_CHAR_SKIP = "vi-find-next-char-skip";
+    String VI_FIND_PREV_CHAR = "vi-find-prev-char";
+    String VI_FIND_PREV_CHAR_SKIP = "vi-find-prev-char-skip";
+    String VI_FIRST_NON_BLANK = "vi-first-non-blank";
+    String VI_FORWARD_BLANK_WORD = "vi-forward-blank-word";
+    String VI_FORWARD_BLANK_WORD_END = "vi-forward-blank-word-end";
+    String VI_FORWARD_CHAR = "vi-forward-char";
+    String VI_FORWARD_WORD = "vi-forward-word";
+    String VI_FORWARD_WORD_END = "vi-forward-word-end";
+    String VI_GOTO_COLUMN = "vi-goto-column";
+    String VI_HISTORY_SEARCH_BACKWARD = "vi-history-search-backward";
+    String VI_HISTORY_SEARCH_FORWARD = "vi-history-search-forward";
+    String VI_INSERT = "vi-insert";
+    String VI_INSERT_BOL = "vi-insert-bol";
+    String VI_INSERT_COMMENT = "vi-insert-comment";
+    String VI_JOIN = "vi-join";
+    String VI_KILL_EOL = "vi-kill-eol";
+    String VI_KILL_LINE = "vi-kill-line";
+    String VI_MATCH_BRACKET = "vi-match-bracket";
+    String VI_OPEN_LINE_ABOVE = "vi-open-line-above";
+    String VI_OPEN_LINE_BELOW = "vi-open-line-below";
+    String VI_OPER_SWAP_CASE = "vi-oper-swap-case";
+    String VI_PUT_AFTER = "vi-put-after";
+    String VI_PUT_BEFORE = "vi-put-before";
+    String VI_QUOTED_INSERT = "vi-quoted-insert";
+    String VI_REPEAT_CHANGE = "vi-repeat-change";
+    String VI_REPEAT_FIND = "vi-repeat-find";
+    String VI_REPEAT_SEARCH = "vi-repeat-search";
+    String VI_REPLACE = "vi-replace";
+    String VI_REPLACE_CHARS = "vi-replace-chars";
+    String VI_REV_REPEAT_FIND = "vi-rev-repeat-find";
+    String VI_REV_REPEAT_SEARCH = "vi-rev-repeat-search";
+    String VI_SET_BUFFER = "vi-set-buffer";
+    String VI_SUBSTITUTE = "vi-substitute";
+    String VI_SWAP_CASE = "vi-swap-case";
+    String VI_UNDO_CHANGE = "vi-undo-change";
+    String VI_UP_LINE_OR_HISTORY = "vi-up-line-or-history";
+    String VI_YANK = "vi-yank";
+    String VI_YANK_EOL = "vi-yank-eol";
+    String VI_YANK_WHOLE_LINE = "vi-yank-whole-line";
+    String VISUAL_LINE_MODE = "visual-line-mode";
+    String VISUAL_MODE = "visual-mode";
+    String WHAT_CURSOR_POSITION = "what-cursor-position";
+    String YANK = "yank";
+    String YANK_POP = "yank-pop";
+    String MOUSE = "mouse";
+    String FOCUS_IN = "terminal-focus-in";
+    String FOCUS_OUT = "terminal-focus-out";
+
+    String BEGIN_PASTE = "begin-paste";
+
+    //
+    // KeyMap names
+    //
+
+    String VICMD = "vicmd";
+    String VIINS = "viins";
+    String VIOPP = "viopp";
+    String VISUAL = "visual";
+    String MAIN = "main";
+    String EMACS = "emacs";
+    String SAFE = ".safe";
+    String MENU = "menu";
+
+    //
+    // Variable names
+    //
+
+    String BIND_TTY_SPECIAL_CHARS = "bind-tty-special-chars";
+    String COMMENT_BEGIN = "comment-begin";
+    String BELL_STYLE = "bell-style";
+    String PREFER_VISIBLE_BELL = "prefer-visible-bell";
+    String LIST_MAX = "list-max";
+    String DISABLE_HISTORY = "disable-history";
+    String DISABLE_COMPLETION = "disable-completion";
+    String EDITING_MODE = "editing-mode";
+    String KEYMAP = "keymap";
+    String BLINK_MATCHING_PAREN = "blink-matching-paren";
+    String WORDCHARS = "WORDCHARS";
+    String REMOVE_SUFFIX_CHARS = "REMOVE_SUFFIX_CHARS";
+    String SEARCH_TERMINATORS = "search-terminators";
+    String ERRORS = "errors";
+    /** Property for the "others" group name */
+    String OTHERS_GROUP_NAME = "OTHERS_GROUP_NAME";
+    /** Property for the "original" group name */
+    String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME";
+    /** Completion style for displaying groups name */
+    String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP";
+    /** Completion style for displaying the current selected item */
+    String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION";
+    /** Completion style for displaying the candidate description */
+    String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION";
+    /** Completion style for displaying the matching part of candidates */
+    String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING";
+    /**
+     * Set the template for prompts for secondary (continuation) lines.
+     * This is a prompt template as described in the class header.
+     */
+    String SECONDARY_PROMPT_PATTERN = "secondary-prompt-pattern";
+    /**
+     * When in multiline edit mode, this variable can be used
+     * to offset the line number displayed.
+     */
+    String LINE_OFFSET = "line-offset";
+
+    /**
+     * Timeout for ambiguous key sequences.
+     * If the key sequence is ambiguous, i.e. there is a matching
+     * sequence but the sequence is also a prefix for other bindings,
+     * the next key press will be waited for a specified amount of
+     * time.  If the timeout elapses, the matched sequence will be
+     * used.
+     */
+    String AMBIGUOUS_BINDING = "ambiguous-binding";
+
+    /**
+     * Columns separated list of patterns that will not be saved in history.
+     */
+    String HISTORY_IGNORE = "history-ignore";
+
+    /**
+     * File system history path.
+     */
+    String HISTORY_FILE = "history-file";
+
+    /**
+     * Number of history items to keep in memory.
+     */
+    String HISTORY_SIZE = "history-size";
+
+    /**
+     * Number of history items to keep in the history file.
+     */
+    String HISTORY_FILE_SIZE = "history-file-size";
+
+    Map<String, KeyMap<Binding>> defaultKeyMaps();
+
+    enum Option {
+        COMPLETE_IN_WORD,
+        DISABLE_EVENT_EXPANSION,
+        HISTORY_VERIFY,
+        HISTORY_IGNORE_SPACE(true),
+        HISTORY_IGNORE_DUPS(true),
+        HISTORY_REDUCE_BLANKS(true),
+        HISTORY_BEEP(true),
+        HISTORY_INCREMENTAL(true),
+        HISTORY_TIMESTAMPED(true),
+        /** when displaying candidates, group them by {@link Candidate#group()} */
+        AUTO_GROUP(true),
+        AUTO_MENU(true),
+        AUTO_LIST(true),
+        RECOGNIZE_EXACT,
+        /** display group name before each group (else display all group names first) */
+        GROUP(true),
+        /** if completion is case insensitive or not */
+        CASE_INSENSITIVE,
+        LIST_AMBIGUOUS,
+        LIST_PACKED,
+        LIST_ROWS_FIRST,
+        GLOB_COMPLETE,
+        MENU_COMPLETE,
+        /** if set and not at start of line before prompt, move to new line */
+        AUTO_FRESH_LINE,
+
+        /** After writing into the rightmost column, do we immediately
+         * move to the next line (the default)? Or do we wait until
+         * the next character.
+         * If set, an input line that is exactly {@code N*columns} wide will
+         * use {@code N} screen lines; otherwise it will use {@code N+1} lines.
+         * When the cursor position is the right margin of the last line
+         * (i.e. after {@code N*columns} normal characters), if this option
+         * it set, the cursor will be remain on the last line (line {@code N-1},
+         * zero-origin); if unset the cursor will be on the empty next line.
+         * Regardless, for all except the last screen line if the cursor is at
+         * the right margin, it will be shown at the start of the next line.
+         */
+        DELAY_LINE_WRAP,
+        AUTO_PARAM_SLASH(true),
+        AUTO_REMOVE_SLASH(true),
+        /** When hitting the <code>&lt;tab&gt;</code> key at the beginning of the line, insert a tabulation
+         *  instead of completing.  This is mainly useful when {@link #BRACKETED_PASTE} is
+         *  disabled, so that copy/paste of indented text does not trigger completion.
+         */
+        INSERT_TAB,
+        MOUSE,
+        DISABLE_HIGHLIGHTER,
+        BRACKETED_PASTE(true),
+        /**
+         * Instead of printing a new line when the line is read, the entire line
+         * (including the prompt) will be erased, thereby leaving the screen as it
+         * was before the readLine call.
+         */
+        ERASE_LINE_ON_FINISH,
+
+        /** if history search is fully case insensitive */
+        CASE_INSENSITIVE_SEARCH,
+        ;
+
+        private final boolean def;
+
+        Option() {
+            this(false);
+        }
+
+        Option(boolean def) {
+            this.def = def;
+        }
+
+        public boolean isDef() {
+            return def;
+        }
+    }
+
+    enum RegionType {
+        NONE,
+        CHAR,
+        LINE,
+        PASTE
+    }
+
+    /**
+     * Read the next line and return the contents of the buffer.
+     *
+     * Equivalent to <code>readLine(null, null, null)</code>.
+     *
+     * @return the line read
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine() throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read the next line with the specified character mask. If null, then
+     * characters will be echoed. If 0, then no characters will be echoed.
+     *
+     * Equivalent to <code>readLine(null, mask, null)</code>
+     *
+     * @param mask      The mask character, <code>null</code> or <code>0</code>.
+     * @return          A line that is read from the terminal, can never be null.
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(Character mask) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read the next line with the specified prompt.
+     * If null, then the default prompt will be used.
+     *
+     * Equivalent to <code>readLine(prompt, null, null)</code>
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     * @return          A line that is read from the terminal, can never be null.
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(String prompt) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * Equivalent to <code>readLine(prompt, mask, null)</code>
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     * @param mask      The mask character, <code>null</code> or <code>0</code>.
+     * @return          A line that is read from the terminal, can never be null.
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(String prompt, Character mask) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * Equivalent to <code>readLine(prompt, null, mask, buffer)</code>
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     *   This is a template, with optional {@code '%'} escapes, as
+     *   described in the class header.
+     * @param mask      The character mask, may be null.
+     * @param buffer    The default value presented to the user to edit, may be null.
+     * @return          A line that is read from the terminal, can never be null.
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(String prompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt      The prompt to issue to the terminal, may be null.
+     *   This is a template, with optional {@code '%'} escapes, as
+     *   described in the class header.
+     * @param rightPrompt The right prompt
+     *   This is a template, with optional {@code '%'} escapes, as
+     *   described in the class header.
+     * @param mask        The character mask, may be null.
+     * @param buffer      The default value presented to the user to edit, may be null.
+     * @return            A line that is read from the terminal, can never be null.
+     *
+     * @throws UserInterruptException if readLine was interrupted (using Ctrl-C for example)
+     * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
+     * @throws java.io.IOError in case of other i/o errors
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt      The prompt to issue to the terminal, may be null.
+     *   This is a template, with optional {@code '%'} escapes, as
+     *   described in the class header.
+     * @param rightPrompt The right prompt
+     *   This is a template, with optional {@code '%'} escapes, as
+     *   described in the class header.
+     * @param maskingCallback  The {@link MaskingCallback} to use when displaying lines and adding them to the line {@link History}
+     * @param buffer      The default value presented to the user to edit, may be null.
+     * @return            A line that is read from the terminal, can never be null.
+     *
+     * @throws UserInterruptException if readLine was interrupted (using Ctrl-C for example)
+     * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
+     * @throws java.io.IOError in case of other i/o errors
+     * @throws UserInterruptException If the call was interrupted by the user.
+     * @throws EndOfFileException     If the end of the input stream was reached.
+     */
+    String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException;
+
+    /**
+     * Prints a line above the prompt and redraw everything.
+     * If the LineReader is not actually reading a line, the string will simply be printed to the terminal.
+     *
+     * @see #printAbove(AttributedString)
+     * @param str the string to print
+     */
+    void printAbove(String str);
+
+    /**
+     * Prints a string before the prompt and redraw everything.
+     * If the LineReader is not actually reading a line, the string will simply be printed to the terminal.
+     *
+     * @see #printAbove(String)
+     * @param str the string to print
+     */
+    void printAbove(AttributedString str);
+
+    /**
+     * Check if a thread is currently in a <code>readLine()</code> call.
+     *
+     * @return <code>true</code> if there is an ongoing <code>readLine()</code> call.
+     */
+    boolean isReading();
+
+    //
+    // Chainable setters
+    //
+
+    LineReader variable(String name, Object value);
+
+    LineReader option(Option option, boolean value);
+
+    void callWidget(String name);
+
+    Map<String, Object> getVariables();
+
+    Object getVariable(String name);
+
+    void setVariable(String name, Object value);
+
+    boolean isSet(Option option);
+
+    void setOpt(Option option);
+
+    void unsetOpt(Option option);
+
+    Terminal getTerminal();
+
+    Map<String, Widget> getWidgets();
+
+    Map<String, Widget> getBuiltinWidgets();
+
+    Buffer getBuffer();
+
+    String getAppName();
+
+    /**
+     * Push back a key sequence that will be later consumed by the line reader.
+     * This method can be used after reading the cursor position using
+     * {@link Terminal#getCursorPosition(IntConsumer)}.
+     *
+     * @param macro the key sequence to push back
+     * @see Terminal#getCursorPosition(IntConsumer)
+     * @see #readMouseEvent()
+     */
+    void runMacro(String macro);
+
+    /**
+     * Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence
+     * has just been read on the input stream.
+     * Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys
+     * that have been pushed back using {@link #runMacro(String)}.
+     *
+     * @return the mouse event
+     * @see #runMacro(String)
+     * @see Terminal#getCursorPosition(IntConsumer)
+     */
+    MouseEvent readMouseEvent();
+
+    History getHistory();
+
+    Parser getParser();
+
+    Highlighter getHighlighter();
+
+    Expander getExpander();
+
+    Map<String, KeyMap<Binding>> getKeyMaps();
+
+    String getKeyMap();
+
+    boolean setKeyMap(String name);
+
+    KeyMap<Binding> getKeys();
+
+    ParsedLine getParsedLine();
+
+    String getSearchTerm();
+
+    RegionType getRegionActive();
+
+    int getRegionMark();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import jdk.internal.org.jline.reader.impl.LineReaderImpl;
+import jdk.internal.org.jline.reader.impl.history.DefaultHistory;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.TerminalBuilder;
+import jdk.internal.org.jline.utils.Log;
+
+public final class LineReaderBuilder {
+
+    public static LineReaderBuilder builder() {
+        return new LineReaderBuilder();
+    }
+
+    Terminal terminal;
+    String appName;
+    Map<String, Object> variables = new HashMap<>();
+    Map<LineReader.Option, Boolean> options = new HashMap<>();
+    History history;
+    Completer completer;
+    History memoryHistory;
+    Highlighter highlighter;
+    Parser parser;
+    Expander expander;
+
+    private LineReaderBuilder() {
+    }
+
+    public LineReaderBuilder terminal(Terminal terminal) {
+        this.terminal = terminal;
+        return this;
+    }
+
+    public LineReaderBuilder appName(String appName) {
+        this.appName = appName;
+        return this;
+    }
+
+    public LineReaderBuilder variables(Map<String, Object> variables) {
+        Map<String, Object> old = this.variables;
+        this.variables = Objects.requireNonNull(variables);
+        this.variables.putAll(old);
+        return this;
+    }
+
+    public LineReaderBuilder variable(String name, Object value) {
+        this.variables.put(name, value);
+        return this;
+    }
+
+    public LineReaderBuilder option(LineReader.Option option, boolean value) {
+        this.options.put(option, value);
+        return this;
+    }
+
+    public LineReaderBuilder history(History history) {
+        this.history = history;
+        return this;
+    }
+
+    public LineReaderBuilder completer(Completer completer) {
+        this.completer = completer;
+        return this;
+    }
+
+    public LineReaderBuilder highlighter(Highlighter highlighter) {
+        this.highlighter = highlighter;
+        return this;
+    }
+
+    public LineReaderBuilder parser(Parser parser) {
+        if (parser != null) {
+            try {
+                if (!Boolean.parseBoolean(LineReader.PROP_SUPPORT_PARSEDLINE)
+                        && !(parser.parse("", 0) instanceof CompletingParsedLine)) {
+                    Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " +
+                            "Completion with escaped or quoted words won't work correctly.");
+                }
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+        this.parser = parser;
+        return this;
+    }
+
+    public LineReaderBuilder expander(Expander expander) {
+        this.expander = expander;
+        return this;
+    }
+
+    public LineReader build() {
+        Terminal terminal = this.terminal;
+        if (terminal == null) {
+            try {
+                terminal = TerminalBuilder.terminal();
+            } catch (IOException e) {
+                throw new IOError(e);
+            }
+        }
+        LineReaderImpl reader = new LineReaderImpl(terminal, appName, variables);
+        if (history != null) {
+            reader.setHistory(history);
+        } else {
+            if (memoryHistory == null) {
+                memoryHistory = new DefaultHistory();
+            }
+            reader.setHistory(memoryHistory);
+        }
+        if (completer != null) {
+            reader.setCompleter(completer);
+        }
+        if (highlighter != null) {
+            reader.setHighlighter(highlighter);
+        }
+        if (parser != null) {
+            reader.setParser(parser);
+        }
+        if (expander != null) {
+            reader.setExpander(expander);
+        }
+        for (Map.Entry<LineReader.Option, Boolean> e : options.entrySet()) {
+            reader.option(e.getKey(), e.getValue());
+        }
+        return reader;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+public class Macro implements Binding {
+
+    private final String sequence;
+
+    public Macro(String sequence) {
+        this.sequence = sequence;
+    }
+
+    public String getSequence() {
+        return sequence;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Macro macro = (Macro) o;
+        return sequence.equals(macro.sequence);
+    }
+
+    @Override
+    public int hashCode() {
+        return sequence.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "Macro[" +
+                sequence + ']';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * Callback used to mask parts of the line
+ */
+public interface MaskingCallback {
+
+    /**
+     * Transforms the line before it is displayed so that
+     * some parts can be hidden.
+     *
+     * @param line the current line being edited
+     * @return the modified line to display
+     */
+    String display(String line);
+
+    /**
+     * Transforms the line before storing in the history.
+     * If the return value is empty or null, it will not be saved
+     * in the history.
+     *
+     * @param line the line to be added to history
+     * @return the modified line
+     */
+    String history(String line);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+import java.util.List;
+
+/**
+ * <code>ParsedLine</code> objects are returned by the {@link Parser}
+ * during completion or when accepting the line.
+ *
+ * The instances should implement the {@link CompletingParsedLine}
+ * interface so that escape chars and quotes can be correctly handled.
+ *
+ * @see Parser
+ * @see CompletingParsedLine
+ */
+public interface ParsedLine {
+
+    /**
+     * The current word being completed.
+     * If the cursor is after the last word, an empty string is returned.
+     *
+     * @return the word being completed or an empty string
+     */
+    String word();
+
+    /**
+     * The cursor position within the current word.
+     *
+     * @return the cursor position within the current word
+     */
+    int wordCursor();
+
+    /**
+     * The index of the current word in the list of words.
+     *
+     * @return the index of the current word in the list of words
+     */
+    int wordIndex();
+
+    /**
+     * The list of words.
+     *
+     * @return the list of words
+     */
+    List<String> words();
+
+    /**
+     * The unparsed line.
+     *
+     * @return the unparsed line
+     */
+    String line();
+
+    /**
+     * The cursor position within the line.
+     *
+     * @return the cursor position within the line
+     */
+    int cursor();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+public interface Parser {
+
+    ParsedLine parse(String line, int cursor, ParseContext context) throws SyntaxError;
+
+    default ParsedLine parse(String line, int cursor) throws SyntaxError {
+        return parse(line, cursor, ParseContext.UNSPECIFIED);
+    }
+
+    enum ParseContext {
+        UNSPECIFIED,
+
+        /** Try a real "final" parse.
+         * May throw EOFError in which case we have incomplete input.
+         */
+        ACCEPT_LINE,
+
+        /** Parse to find completions (typically after a Tab).
+         * We should tolerate and ignore errors.
+         */
+        COMPLETE,
+
+        /** Called when we need to update the secondary prompts.
+         * Specifically, when we need the 'missing' field from EOFError,
+         * which is used by a "%M" in a prompt pattern.
+         */
+        SECONDARY_PROMPT
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * A reference to a {@link Widget}.
+ */
+public class Reference implements Binding {
+
+    private final String name;
+
+    public Reference(String name) {
+        this.name = name;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Reference func = (Reference) o;
+        return name.equals(func.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "Reference[" +
+                name + ']';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package jdk.internal.org.jline.reader;
+
+public class SyntaxError extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    private final int line;
+    private final int column;
+
+    public SyntaxError(int line, int column, String message) {
+        super(message);
+        this.line = line;
+        this.column = column;
+    }
+
+    public int column() {
+        return column;
+    }
+
+    public int line() {
+        return line;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ * This exception is thrown by {@link LineReader#readLine} when
+ * user interrupt handling is enabled and the user types the
+ * interrupt character (ctrl-C). The partially entered line is
+ * available via the {@link #getPartialLine()} method.
+ */
+public class UserInterruptException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = 6172232572140736750L;
+
+    private final String partialLine;
+
+    public UserInterruptException(String partialLine)
+    {
+        this.partialLine = partialLine;
+    }
+
+    /**
+     * @return the partially entered line when ctrl-C was pressed
+     */
+    public String getPartialLine()
+    {
+        return partialLine;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader;
+
+/**
+ *
+ */
+@FunctionalInterface
+public interface Widget extends Binding {
+
+    boolean apply();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import java.util.Objects;
+
+import jdk.internal.org.jline.reader.Buffer;
+
+/**
+ * A holder for a {@link StringBuilder} that also contains the current cursor position.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class BufferImpl implements Buffer
+{
+    private int cursor = 0;
+    private int cursorCol = -1;
+    private int[] buffer;
+    private int g0;
+    private int g1;
+
+    public BufferImpl() {
+        this(64);
+    }
+
+    public BufferImpl(int size) {
+        buffer = new int[size];
+        g0 = 0;
+        g1 = buffer.length;
+    }
+
+    private BufferImpl(BufferImpl buffer) {
+        this.cursor = buffer.cursor;
+        this.cursorCol = buffer.cursorCol;
+        this.buffer = buffer.buffer.clone();
+        this.g0 = buffer.g0;
+        this.g1 = buffer.g1;
+    }
+
+    public BufferImpl copy () {
+        return new BufferImpl(this);
+    }
+
+    public int cursor() {
+        return cursor;
+    }
+
+    public int length() {
+        return buffer.length - (g1 - g0);
+    }
+
+    public boolean currChar(int ch) {
+        if (cursor == length()) {
+            return false;
+        } else {
+            buffer[adjust(cursor)] = ch;
+            return true;
+        }
+    }
+
+    public int currChar() {
+        if (cursor == length()) {
+            return 0;
+        } else {
+            return atChar(cursor);
+        }
+    }
+
+    public int prevChar() {
+        if (cursor <= 0) {
+            return 0;
+        }
+        return atChar(cursor - 1);
+    }
+
+    public int nextChar() {
+        if (cursor >= length() - 1) {
+            return 0;
+        }
+        return atChar(cursor + 1);
+    }
+
+    public int atChar(int i) {
+        if (i < 0 || i >= length()) {
+            return 0;
+        }
+        return buffer[adjust(i)];
+    }
+
+    private int adjust(int i) {
+        return (i >= g0) ? i + g1 - g0 : i;
+    }
+
+    /**
+     * Write the specific character into the buffer, setting the cursor position
+     * ahead one.
+     *
+     * @param c the character to insert
+     */
+    public void write(int c) {
+        write(new int[] { c });
+    }
+
+    /**
+     * Write the specific character into the buffer, setting the cursor position
+     * ahead one. The text may overwrite or insert based on the current setting
+     * of {@code overTyping}.
+     *
+     * @param c the character to insert
+     */
+    public void write(int c, boolean overTyping) {
+        if (overTyping) {
+            delete(1);
+        }
+        write(new int[] { c });
+    }
+
+    /**
+     * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point.
+     */
+    public void write(CharSequence str) {
+        Objects.requireNonNull(str);
+        write(str.codePoints().toArray());
+    }
+
+    public void write(CharSequence str, boolean overTyping) {
+        Objects.requireNonNull(str);
+        int[] ucps = str.codePoints().toArray();
+        if (overTyping) {
+            delete(ucps.length);
+        }
+        write(ucps);
+    }
+
+    private void write(int[] ucps) {
+        moveGapToCursor();
+        int len = length() + ucps.length;
+        int sz = buffer.length;
+        if (sz < len) {
+            while (sz < len) {
+                sz *= 2;
+            }
+            int[] nb = new int[sz];
+            System.arraycopy(buffer, 0, nb, 0, g0);
+            System.arraycopy(buffer, g1, nb, g1 + sz - buffer.length, buffer.length - g1);
+            g1 += sz - buffer.length;
+            buffer = nb;
+        }
+        System.arraycopy(ucps, 0, buffer, cursor, ucps.length);
+        g0 += ucps.length;
+        cursor += ucps.length;
+        cursorCol = -1;
+    }
+
+    public boolean clear() {
+        if (length() == 0) {
+            return false;
+        }
+        g0 = 0;
+        g1 = buffer.length;
+        cursor = 0;
+        cursorCol = -1;
+        return true;
+    }
+
+    public String substring(int start) {
+        return substring(start, length());
+    }
+
+    public String substring(int start, int end) {
+        if (start >= end || start < 0 || end > length()) {
+            return "";
+        }
+        if (end <= g0) {
+            return new String(buffer, start, end - start);
+        } else if (start > g0) {
+            return new String(buffer, g1 - g0 + start, end - start);
+        } else {
+            int[] b = buffer.clone();
+            System.arraycopy(b, g1, b, g0, b.length - g1);
+            return new String(b, start, end - start);
+        }
+    }
+
+    public String upToCursor() {
+        return substring(0, cursor);
+    }
+
+    /**
+     * Move the cursor position to the specified absolute index.
+     */
+    public boolean cursor(int position) {
+        if (position == cursor) {
+            return true;
+        }
+        return move(position - cursor) != 0;
+    }
+
+    /**
+     * Move the cursor <i>where</i> characters.
+     *
+     * @param num   If less than 0, move abs(<i>where</i>) to the left, otherwise move <i>where</i> to the right.
+     * @return      The number of spaces we moved
+     */
+    public int move(final int num) {
+        int where = num;
+
+        if ((cursor == 0) && (where <= 0)) {
+            return 0;
+        }
+
+        if ((cursor == length()) && (where >= 0)) {
+            return 0;
+        }
+
+        if ((cursor + where) < 0) {
+            where = -cursor;
+        }
+        else if ((cursor + where) > length()) {
+            where = length() - cursor;
+        }
+
+        cursor += where;
+        cursorCol = -1;
+
+        return where;
+    }
+
+    public boolean up() {
+        int col = getCursorCol();
+        int pnl = cursor - 1;
+        while (pnl >= 0 && atChar(pnl) != '\n') {
+            pnl--;
+        }
+        if (pnl < 0) {
+            return false;
+        }
+        int ppnl = pnl - 1;
+        while (ppnl >= 0 && atChar(ppnl) != '\n') {
+            ppnl--;
+        }
+        cursor = Math.min(ppnl + col + 1, pnl);
+        return true;
+    }
+
+    public boolean down() {
+        int col = getCursorCol();
+        int nnl = cursor;
+        while (nnl < length() && atChar(nnl) != '\n') {
+            nnl++;
+        }
+        if (nnl >= length()) {
+            return false;
+        }
+        int nnnl = nnl + 1;
+        while (nnnl < length() && atChar(nnnl) != '\n') {
+            nnnl++;
+        }
+        cursor = Math.min(nnl + col + 1, nnnl);
+        return true;
+    }
+
+    public boolean moveXY(int dx, int dy) {
+        int col = 0;
+        while (prevChar() != '\n' && move(-1) == -1) {
+            col++;
+        }
+        cursorCol = 0;
+        while (dy < 0) {
+            up();
+            dy++;
+        }
+        while (dy > 0) {
+            down();
+            dy--;
+        }
+        col = Math.max(col + dx, 0);
+        for (int i = 0; i < col; i++) {
+            if (move(1) != 1 || currChar() == '\n') {
+                break;
+            }
+        }
+        cursorCol = col;
+        return true;
+    }
+
+    private int getCursorCol() {
+        if (cursorCol < 0) {
+            cursorCol = 0;
+            int pnl = cursor - 1;
+            while (pnl >= 0 && atChar(pnl) != '\n') {
+                pnl--;
+            }
+            cursorCol = cursor - pnl - 1;
+        }
+        return cursorCol;
+    }
+
+    /**
+     * Issue <em>num</em> backspaces.
+     *
+     * @return the number of characters backed up
+     */
+    public int backspace(final int num) {
+        int count = Math.max(Math.min(cursor, num), 0);
+        moveGapToCursor();
+        cursor -= count;
+        g0 -= count;
+        cursorCol = -1;
+        return count;
+    }
+
+    /**
+     * Issue a backspace.
+     *
+     * @return true if successful
+     */
+    public boolean backspace() {
+        return backspace(1) == 1;
+    }
+
+    public int delete(int num) {
+        int count = Math.max(Math.min(length() - cursor, num), 0);
+        moveGapToCursor();
+        g1 += count;
+        cursorCol = -1;
+        return count;
+    }
+
+    public boolean delete() {
+        return delete(1) == 1;
+    }
+
+    @Override
+    public String toString() {
+        return substring(0, length());
+    }
+
+    public void copyFrom(Buffer buf) {
+        if (!(buf instanceof BufferImpl)) {
+            throw new IllegalStateException();
+        }
+        BufferImpl that = (BufferImpl) buf;
+        this.g0 = that.g0;
+        this.g1 = that.g1;
+        this.buffer = that.buffer.clone();
+        this.cursor = that.cursor;
+        this.cursorCol = that.cursorCol;
+    }
+
+    private void moveGapToCursor() {
+        if (cursor < g0) {
+            int l = g0 - cursor;
+            System.arraycopy(buffer, cursor, buffer, g1 - l, l);
+            g0 -= l;
+            g1 -= l;
+        } else if (cursor > g0) {
+            int l = cursor - g0;
+            System.arraycopy(buffer, g1, buffer, g0, l);
+            g0 += l;
+            g1 += l;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import java.util.ListIterator;
+
+import jdk.internal.org.jline.reader.Expander;
+import jdk.internal.org.jline.reader.History;
+import jdk.internal.org.jline.reader.History.Entry;
+
+public class DefaultExpander implements Expander {
+
+    /**
+     * Expand event designator such as !!, !#, !3, etc...
+     * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
+     */
+    @SuppressWarnings("fallthrough")
+    @Override
+    public String expandHistory(History history, String line) {
+        boolean inQuote = false;
+        StringBuilder sb = new StringBuilder();
+        boolean escaped = false;
+        int unicode = 0;
+        for (int i = 0; i < line.length(); i++) {
+            char c = line.charAt(i);
+            if (unicode > 0) {
+                escaped = (--unicode >= 0);
+                sb.append(c);
+            }
+            else if (escaped) {
+                if (c == 'u') {
+                    unicode = 4;
+                } else {
+                    escaped = false;
+                }
+                sb.append(c);
+            }
+            else if (c == '\'') {
+                inQuote = !inQuote;
+                sb.append(c);
+            }
+            else if (inQuote) {
+                sb.append(c);
+            }
+            else {
+                switch (c) {
+                    case '\\':
+                        // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
+                        // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
+                        // otherwise, add the escape
+                        escaped = true;
+                        sb.append(c);
+                        break;
+                    case '!':
+                        if (i + 1 < line.length()) {
+                            c = line.charAt(++i);
+                            boolean neg = false;
+                            String rep = null;
+                            int i1, idx;
+                            switch (c) {
+                                case '!':
+                                    if (history.size() == 0) {
+                                        throw new IllegalArgumentException("!!: event not found");
+                                    }
+                                    rep = history.get(history.index() - 1);
+                                    break;
+                                case '#':
+                                    sb.append(sb.toString());
+                                    break;
+                                case '?':
+                                    i1 = line.indexOf('?', i + 1);
+                                    if (i1 < 0) {
+                                        i1 = line.length();
+                                    }
+                                    String sc = line.substring(i + 1, i1);
+                                    i = i1;
+                                    idx = searchBackwards(history, sc, history.index(), false);
+                                    if (idx < 0) {
+                                        throw new IllegalArgumentException("!?" + sc + ": event not found");
+                                    } else {
+                                        rep = history.get(idx);
+                                    }
+                                    break;
+                                case '$':
+                                    if (history.size() == 0) {
+                                        throw new IllegalArgumentException("!$: event not found");
+                                    }
+                                    String previous = history.get(history.index() - 1).trim();
+                                    int lastSpace = previous.lastIndexOf(' ');
+                                    if (lastSpace != -1) {
+                                        rep = previous.substring(lastSpace + 1);
+                                    } else {
+                                        rep = previous;
+                                    }
+                                    break;
+                                case ' ':
+                                case '\t':
+                                    sb.append('!');
+                                    sb.append(c);
+                                    break;
+                                case '-':
+                                    neg = true;
+                                    i++;
+                                    // fall through
+                                case '0':
+                                case '1':
+                                case '2':
+                                case '3':
+                                case '4':
+                                case '5':
+                                case '6':
+                                case '7':
+                                case '8':
+                                case '9':
+                                    i1 = i;
+                                    for (; i < line.length(); i++) {
+                                        c = line.charAt(i);
+                                        if (c < '0' || c > '9') {
+                                            break;
+                                        }
+                                    }
+                                    try {
+                                        idx = Integer.parseInt(line.substring(i1, i));
+                                    } catch (NumberFormatException e) {
+                                        throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
+                                    }
+                                    if (neg && idx > 0 && idx <= history.size()) {
+                                        rep = history.get(history.index() - idx);
+                                    } else if (!neg && idx > history.index() - history.size() && idx <= history.index()) {
+                                        rep = history.get(idx - 1);
+                                    } else {
+                                        throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
+                                    }
+                                    break;
+                                default:
+                                    String ss = line.substring(i);
+                                    i = line.length();
+                                    idx = searchBackwards(history, ss, history.index(), true);
+                                    if (idx < 0) {
+                                        throw new IllegalArgumentException("!" + ss + ": event not found");
+                                    } else {
+                                        rep = history.get(idx);
+                                    }
+                                    break;
+                            }
+                            if (rep != null) {
+                                sb.append(rep);
+                            }
+                        } else {
+                            sb.append(c);
+                        }
+                        break;
+                    case '^':
+                        if (i == 0) {
+                            int i1 = line.indexOf('^', i + 1);
+                            int i2 = line.indexOf('^', i1 + 1);
+                            if (i2 < 0) {
+                                i2 = line.length();
+                            }
+                            if (i1 > 0 && i2 > 0) {
+                                String s1 = line.substring(i + 1, i1);
+                                String s2 = line.substring(i1 + 1, i2);
+                                String s = history.get(history.index() - 1).replace(s1, s2);
+                                sb.append(s);
+                                i = i2 + 1;
+                                break;
+                            }
+                        }
+                        sb.append(c);
+                        break;
+                    default:
+                        sb.append(c);
+                        break;
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String expandVar(String word) {
+        return word;
+    }
+
+    protected int searchBackwards(History history, String searchTerm, int startIndex, boolean startsWith) {
+        ListIterator<Entry> it = history.iterator(startIndex);
+        while (it.hasPrevious()) {
+            History.Entry e = it.previous();
+            if (startsWith) {
+                if (e.line().startsWith(searchTerm)) {
+                    return e.index();
+                }
+            } else {
+                if (e.line().contains(searchTerm)) {
+                    return e.index();
+                }
+            }
+        }
+        return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.LineReader.RegionType;
+import jdk.internal.org.jline.reader.Highlighter;
+import jdk.internal.org.jline.utils.AttributedString;
+import jdk.internal.org.jline.utils.AttributedStringBuilder;
+import jdk.internal.org.jline.utils.AttributedStyle;
+import jdk.internal.org.jline.utils.WCWidth;
+
+public class DefaultHighlighter implements Highlighter {
+
+    @Override
+    public AttributedString highlight(LineReader reader, String buffer) {
+        int underlineStart = -1;
+        int underlineEnd = -1;
+        int negativeStart = -1;
+        int negativeEnd = -1;
+        String search = reader.getSearchTerm();
+        if (search != null && search.length() > 0) {
+            underlineStart = buffer.indexOf(search);
+            if (underlineStart >= 0) {
+                underlineEnd = underlineStart + search.length() - 1;
+            }
+        }
+        if (reader.getRegionActive() != RegionType.NONE) {
+            negativeStart = reader.getRegionMark();
+            negativeEnd = reader.getBuffer().cursor();
+            if (negativeStart > negativeEnd) {
+                int x = negativeEnd;
+                negativeEnd = negativeStart;
+                negativeStart = x;
+            }
+            if (reader.getRegionActive() == RegionType.LINE) {
+                while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') {
+                    negativeStart--;
+                }
+                while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') {
+                    negativeEnd++;
+                }
+            }
+        }
+
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        for (int i = 0; i < buffer.length(); i++) {
+            if (i == underlineStart) {
+                sb.style(AttributedStyle::underline);
+            }
+            if (i == negativeStart) {
+                sb.style(AttributedStyle::inverse);
+            }
+            char c = buffer.charAt(i);
+            if (c == '\t' || c == '\n') {
+                sb.append(c);
+            } else if (c < 32) {
+                sb.style(AttributedStyle::inverseNeg)
+                        .append('^')
+                        .append((char) (c + '@'))
+                        .style(AttributedStyle::inverseNeg);
+            } else {
+                int w = WCWidth.wcwidth(c);
+                if (w > 0) {
+                    sb.append(c);
+                }
+            }
+            if (i == underlineEnd) {
+                sb.style(AttributedStyle::underlineOff);
+            }
+            if (i == negativeEnd) {
+                sb.style(AttributedStyle::inverseOff);
+            }
+        }
+        return sb.toAttributedString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import java.util.*;
+import java.util.function.Predicate;
+
+import jdk.internal.org.jline.reader.CompletingParsedLine;
+import jdk.internal.org.jline.reader.EOFError;
+import jdk.internal.org.jline.reader.ParsedLine;
+import jdk.internal.org.jline.reader.Parser;
+
+public class DefaultParser implements Parser {
+
+    private char[] quoteChars = {'\'', '"'};
+
+    private char[] escapeChars = {'\\'};
+
+    private boolean eofOnUnclosedQuote;
+
+    private boolean eofOnEscapedNewLine;
+
+    //
+    // Chainable setters
+    //
+
+    public DefaultParser quoteChars(final char[] chars) {
+        this.quoteChars = chars;
+        return this;
+    }
+
+    public DefaultParser escapeChars(final char[] chars) {
+        this.escapeChars = chars;
+        return this;
+    }
+
+    public DefaultParser eofOnUnclosedQuote(boolean eofOnUnclosedQuote) {
+        this.eofOnUnclosedQuote = eofOnUnclosedQuote;
+        return this;
+    }
+
+    public DefaultParser eofOnEscapedNewLine(boolean eofOnEscapedNewLine) {
+        this.eofOnEscapedNewLine = eofOnEscapedNewLine;
+        return this;
+    }
+
+    //
+    // Java bean getters and setters
+    //
+
+    public void setQuoteChars(final char[] chars) {
+        this.quoteChars = chars;
+    }
+
+    public char[] getQuoteChars() {
+        return this.quoteChars;
+    }
+
+    public void setEscapeChars(final char[] chars) {
+        this.escapeChars = chars;
+    }
+
+    public char[] getEscapeChars() {
+        return this.escapeChars;
+    }
+
+    public void setEofOnUnclosedQuote(boolean eofOnUnclosedQuote) {
+        this.eofOnUnclosedQuote = eofOnUnclosedQuote;
+    }
+
+    public boolean isEofOnUnclosedQuote() {
+        return eofOnUnclosedQuote;
+    }
+
+    public void setEofOnEscapedNewLine(boolean eofOnEscapedNewLine) {
+        this.eofOnEscapedNewLine = eofOnEscapedNewLine;
+    }
+
+    public boolean isEofOnEscapedNewLine() {
+        return eofOnEscapedNewLine;
+    }
+
+    public ParsedLine parse(final String line, final int cursor, ParseContext context) {
+        List<String> words = new LinkedList<>();
+        StringBuilder current = new StringBuilder();
+        int wordCursor = -1;
+        int wordIndex = -1;
+        int quoteStart = -1;
+        int rawWordCursor = -1;
+        int rawWordLength = -1;
+        int rawWordStart = 0;
+
+        for (int i = 0; (line != null) && (i < line.length()); i++) {
+            // once we reach the cursor, set the
+            // position of the selected index
+            if (i == cursor) {
+                wordIndex = words.size();
+                // the position in the current argument is just the
+                // length of the current argument
+                wordCursor = current.length();
+                rawWordCursor = i - rawWordStart;
+            }
+
+            if (quoteStart < 0 && isQuoteChar(line, i)) {
+                // Start a quote block
+                quoteStart = i;
+            } else if (quoteStart >= 0) {
+                // In a quote block
+                if (line.charAt(quoteStart) == line.charAt(i) && !isEscaped(line, i)) {
+                    // End the block; arg could be empty, but that's fine
+                    words.add(current.toString());
+                    current.setLength(0);
+                    quoteStart = -1;
+                    if (rawWordCursor >= 0 && rawWordLength < 0) {
+                        rawWordLength = i - rawWordStart + 1;
+                    }
+                } else {
+                    if (!isEscapeChar(line, i)) {
+                        // Take the next character
+                        current.append(line.charAt(i));
+                    }
+                }
+            } else {
+                // Not in a quote block
+                if (isDelimiter(line, i)) {
+                    if (current.length() > 0) {
+                        words.add(current.toString());
+                        current.setLength(0); // reset the arg
+                        if (rawWordCursor >= 0 && rawWordLength < 0) {
+                            rawWordLength = i - rawWordStart;
+                        }
+                    }
+                    rawWordStart = i + 1;
+                } else {
+                    if (!isEscapeChar(line, i)) {
+                        current.append(line.charAt(i));
+                    }
+                }
+            }
+        }
+
+        if (current.length() > 0 || cursor == line.length()) {
+            words.add(current.toString());
+            if (rawWordCursor >= 0 && rawWordLength < 0) {
+                rawWordLength = line.length() - rawWordStart;
+            }
+        }
+
+        if (cursor == line.length()) {
+            wordIndex = words.size() - 1;
+            wordCursor = words.get(words.size() - 1).length();
+            rawWordCursor = cursor - rawWordStart;
+            rawWordLength = rawWordCursor;
+        }
+
+        if (eofOnEscapedNewLine && isEscapeChar(line, line.length() - 1)) {
+            throw new EOFError(-1, -1, "Escaped new line", "newline");
+        }
+        if (eofOnUnclosedQuote && quoteStart >= 0 && context != ParseContext.COMPLETE) {
+            throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\''
+                    ? "quote" : "dquote");
+        }
+
+        String openingQuote = quoteStart >= 0 ? line.substring(quoteStart, quoteStart + 1) : null;
+        return new ArgumentList(line, words, wordIndex, wordCursor, cursor, openingQuote, rawWordCursor, rawWordLength);
+    }
+
+    /**
+     * Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not
+     * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and
+     * returns true from {@link #isDelimiterChar}.
+     *
+     * @param buffer    The complete command buffer
+     * @param pos       The index of the character in the buffer
+     * @return          True if the character should be a delimiter
+     */
+    public boolean isDelimiter(final CharSequence buffer, final int pos) {
+        return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
+    }
+
+    public boolean isQuoted(final CharSequence buffer, final int pos) {
+        return false;
+    }
+
+    public boolean isQuoteChar(final CharSequence buffer, final int pos) {
+        if (pos < 0) {
+            return false;
+        }
+        if (quoteChars != null) {
+            for (char e : quoteChars) {
+                if (e == buffer.charAt(pos)) {
+                    return !isEscaped(buffer, pos);
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if this character is a valid escape char (i.e. one that has not been escaped)
+     *
+     * @param buffer
+     *          the buffer to check in
+     * @param pos
+     *          the position of the character to check
+     * @return true if the character at the specified position in the given buffer is an escape
+     *         character and the character immediately preceding it is not an escape character.
+     */
+    public boolean isEscapeChar(final CharSequence buffer, final int pos) {
+        if (pos < 0) {
+            return false;
+        }
+        if (escapeChars != null) {
+            for (char e : escapeChars) {
+                if (e == buffer.charAt(pos)) {
+                    return !isEscaped(buffer, pos);
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if a character is escaped (i.e. if the previous character is an escape)
+     *
+     * @param buffer
+     *          the buffer to check in
+     * @param pos
+     *          the position of the character to check
+     * @return true if the character at the specified position in the given buffer is an escape
+     *         character and the character immediately preceding it is an escape character.
+     */
+    public boolean isEscaped(final CharSequence buffer, final int pos) {
+        if (pos <= 0) {
+            return false;
+        }
+        return isEscapeChar(buffer, pos - 1);
+    }
+
+    /**
+     * Returns true if the character at the specified position if a delimiter. This method will only be called if
+     * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the
+     * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
+     *
+     * @param buffer
+     *          the buffer to check in
+     * @param pos
+     *          the position of the character to check
+     * @return true if the character at the specified position in the given buffer is a delimiter.
+     */
+    public boolean isDelimiterChar(CharSequence buffer, int pos) {
+        return Character.isWhitespace(buffer.charAt(pos));
+    }
+
+    private boolean isRawEscapeChar(char key) {
+        if (escapeChars != null) {
+            for (char e : escapeChars) {
+                if (e == key) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean isRawQuoteChar(char key) {
+        if (quoteChars != null) {
+            for (char e : quoteChars) {
+                if (e == key) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * The result of a delimited buffer.
+     *
+     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+     */
+    public class ArgumentList implements ParsedLine, CompletingParsedLine
+    {
+        private final String line;
+
+        private final List<String> words;
+
+        private final int wordIndex;
+
+        private final int wordCursor;
+
+        private final int cursor;
+
+        private final String openingQuote;
+
+        private final int rawWordCursor;
+
+        private final int rawWordLength;
+
+        @Deprecated
+        public ArgumentList(final String line, final List<String> words,
+                            final int wordIndex, final int wordCursor,
+                            final int cursor) {
+            this(line, words, wordIndex, wordCursor, cursor,
+                    null, wordCursor, words.get(wordIndex).length());
+        }
+
+        /**
+         *
+         * @param line the command line being edited
+         * @param words the list of words
+         * @param wordIndex the index of the current word in the list of words
+         * @param wordCursor the cursor position within the current word
+         * @param cursor the cursor position within the line
+         * @param openingQuote the opening quote (usually '\"' or '\'') or null
+         * @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters)
+         * @param rawWordLength the raw word length, including quotes and escape characters
+         */
+        public ArgumentList(final String line, final List<String> words,
+                            final int wordIndex, final int wordCursor,
+                            final int cursor, final String openingQuote,
+                            final int rawWordCursor, final int rawWordLength) {
+            this.line = line;
+            this.words = Collections.unmodifiableList(Objects.requireNonNull(words));
+            this.wordIndex = wordIndex;
+            this.wordCursor = wordCursor;
+            this.cursor = cursor;
+            this.openingQuote = openingQuote;
+            this.rawWordCursor = rawWordCursor;
+            this.rawWordLength = rawWordLength;
+        }
+
+        public int wordIndex() {
+            return this.wordIndex;
+        }
+
+        public String word() {
+            // TODO: word() should always be contained in words()
+            if ((wordIndex < 0) || (wordIndex >= words.size())) {
+                return "";
+            }
+            return words.get(wordIndex);
+        }
+
+        public int wordCursor() {
+            return this.wordCursor;
+        }
+
+        public List<String> words() {
+            return this.words;
+        }
+
+        public int cursor() {
+            return this.cursor;
+        }
+
+        public String line() {
+            return line;
+        }
+
+        public CharSequence escape(CharSequence candidate, boolean complete) {
+            StringBuilder sb = new StringBuilder(candidate);
+            Predicate<Integer> needToBeEscaped;
+            // Completion is protected by an opening quote:
+            // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does.
+            // Also, close the quote at the end
+            if (openingQuote != null) {
+                needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote);
+            }
+            // No quote protection, need to escape everything: delimiter chars (spaces), quote chars
+            // and escapes themselves
+            else {
+                needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i));
+            }
+            for (int i = 0; i < sb.length(); i++) {
+                if (needToBeEscaped.test(i)) {
+                    sb.insert(i++, escapeChars[0]);
+                }
+            }
+            if (openingQuote != null) {
+                sb.insert(0, openingQuote);
+                if (complete) {
+                    sb.append(openingQuote);
+                }
+            }
+            return sb;
+        }
+
+        @Override
+        public int rawWordCursor() {
+            return rawWordCursor;
+        }
+
+        @Override
+        public int rawWordLength() {
+            return rawWordLength;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+/**
+ * The kill ring class keeps killed text in a fixed size ring. In this
+ * class we also keep record of whether or not the last command was a
+ * kill or a yank. Depending on this, the class may behave
+ * different. For instance, two consecutive kill-word commands fill
+ * the same slot such that the next yank will return the two
+ * previously killed words instead that only the last one. Likewise
+ * yank pop requires that the previous command was either a yank or a
+ * yank-pop.
+ */
+public final class KillRing {
+
+    /**
+     * Default size is 60, like in emacs.
+     */
+    private static final int DEFAULT_SIZE = 60;
+
+    private final String[] slots;
+    private int head = 0;
+    private boolean lastKill = false;
+    private boolean lastYank = false;
+
+    /**
+     * Creates a new kill ring of the given size.
+     *
+     * @param size the size of the ring
+     */
+    public KillRing(int size) {
+        slots = new String[size];
+    }
+
+    /**
+     * Creates a new kill ring of the default size. See {@link #DEFAULT_SIZE}.
+     */
+    public KillRing() {
+        this(DEFAULT_SIZE);
+    }
+
+    /**
+     * Resets the last-yank state.
+     */
+    public void resetLastYank() {
+        lastYank = false;
+    }
+
+    /**
+     * Resets the last-kill state.
+     */
+    public void resetLastKill() {
+        lastKill = false;
+    }
+
+    /**
+     * Returns {@code true} if the last command was a yank.
+     * @return {@code true} if the last command was a yank
+     */
+    public boolean lastYank() {
+        return lastYank;
+    }
+
+    /**
+     * Adds the string to the kill-ring. Also sets lastYank to false
+     * and lastKill to true.
+     * @param str the string to add
+     */
+    public void add(String str) {
+        lastYank = false;
+
+        if (lastKill) {
+            if (slots[head] != null) {
+                slots[head] += str;
+                return;
+            }
+        }
+
+        lastKill = true;
+        next();
+        slots[head] = str;
+    }
+
+    /**
+     * Adds the string to the kill-ring product of killing
+     * backwards. If the previous command was a kill text one then
+     * adds the text at the beginning of the previous kill to avoid
+     * that two consecutive backwards kills followed by a yank leaves
+     * things reversed.
+     * @param str the string to add
+     */
+    public void addBackwards(String str) {
+        lastYank = false;
+
+        if (lastKill) {
+            if (slots[head] != null) {
+                slots[head] = str + slots[head];
+                return;
+            }
+        }
+
+        lastKill = true;
+        next();
+        slots[head] = str;
+    }
+
+    /**
+     * Yanks a previously killed text. Returns {@code null} if the
+     * ring is empty.
+     * @return the text in the current position
+     */
+    public String yank() {
+        lastKill = false;
+        lastYank = true;
+        return slots[head];
+    }
+
+    /**
+     * Moves the pointer to the current slot back and returns the text
+     * in that position. If the previous command was not yank returns
+     * null.
+     * @return the text in the previous position
+     */
+    public String yankPop() {
+        lastKill = false;
+        if (lastYank) {
+            prev();
+            return slots[head];
+        }
+        return null;
+    }
+
+    /**
+     * Moves the pointer to the current slot forward. If the end of
+     * the slots is reached then points back to the beginning.
+     */
+    private void next() {
+        if (head == 0 && slots[0] == null) {
+            return;
+        }
+        head++;
+        if (head == slots.length) {
+            head = 0;
+        }
+    }
+
+    /**
+     * Moves the pointer to the current slot backwards. If the
+     * beginning of the slots is reached then traverses the slot
+     * backwards until one with not null content is found.
+     */
+    private void prev() {
+        head--;
+        if (head == -1) {
+            int x = (slots.length - 1);
+            for (; x >= 0; x--) {
+                if (slots[x] != null) {
+                    break;
+                }
+            }
+            head = x;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,5683 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import java.io.Flushable;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.time.Instant;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import jdk.internal.org.jline.keymap.BindingReader;
+import jdk.internal.org.jline.keymap.KeyMap;
+import jdk.internal.org.jline.reader.*;
+import jdk.internal.org.jline.reader.Parser.ParseContext;
+import jdk.internal.org.jline.reader.impl.history.DefaultHistory;
+import jdk.internal.org.jline.terminal.*;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Terminal.Signal;
+import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
+import jdk.internal.org.jline.utils.AttributedString;
+import jdk.internal.org.jline.utils.AttributedStringBuilder;
+import jdk.internal.org.jline.utils.AttributedStyle;
+import jdk.internal.org.jline.utils.Curses;
+import jdk.internal.org.jline.utils.Display;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+import jdk.internal.org.jline.utils.Levenshtein;
+import jdk.internal.org.jline.utils.Log;
+import jdk.internal.org.jline.utils.Status;
+import jdk.internal.org.jline.utils.WCWidth;
+
+import static jdk.internal.org.jline.keymap.KeyMap.alt;
+import static jdk.internal.org.jline.keymap.KeyMap.ctrl;
+import static jdk.internal.org.jline.keymap.KeyMap.del;
+import static jdk.internal.org.jline.keymap.KeyMap.esc;
+import static jdk.internal.org.jline.keymap.KeyMap.range;
+import static jdk.internal.org.jline.keymap.KeyMap.translate;
+
+/**
+ * A reader for terminal applications. It supports custom tab-completion,
+ * saveable command history, and command line editing.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+@SuppressWarnings("StatementWithEmptyBody")
+public class LineReaderImpl implements LineReader, Flushable
+{
+    public static final char NULL_MASK = 0;
+
+    public static final int TAB_WIDTH = 4;
+
+
+    public static final String DEFAULT_WORDCHARS = "*?_-.[]~=/&;!#$%^(){}<>";
+    public static final String DEFAULT_REMOVE_SUFFIX_CHARS = " \t\n;&|";
+    public static final String DEFAULT_COMMENT_BEGIN = "#";
+    public static final String DEFAULT_SEARCH_TERMINATORS = "\033\012";
+    public static final String DEFAULT_BELL_STYLE = "";
+    public static final int    DEFAULT_LIST_MAX = 100;
+    public static final int    DEFAULT_ERRORS = 2;
+    public static final long   DEFAULT_BLINK_MATCHING_PAREN = 500L;
+    public static final long   DEFAULT_AMBIGUOUS_BINDING = 1000L;
+    public static final String DEFAULT_SECONDARY_PROMPT_PATTERN = "%M> ";
+    public static final String DEFAULT_OTHERS_GROUP_NAME = "others";
+    public static final String DEFAULT_ORIGINAL_GROUP_NAME = "original";
+    public static final String DEFAULT_COMPLETION_STYLE_STARTING = "36";    // cyan
+    public static final String DEFAULT_COMPLETION_STYLE_DESCRIPTION = "90"; // dark gray
+    public static final String DEFAULT_COMPLETION_STYLE_GROUP = "35;1";     // magenta
+    public static final String DEFAULT_COMPLETION_STYLE_SELECTION = "7";    // inverted
+
+    private static final int MIN_ROWS = 3;
+
+    public static final String BRACKETED_PASTE_ON = "\033[?2004h";
+    public static final String BRACKETED_PASTE_OFF = "\033[?2004l";
+    public static final String BRACKETED_PASTE_BEGIN = "\033[200~";
+    public static final String BRACKETED_PASTE_END = "\033[201~";
+
+    public static final String FOCUS_IN_SEQ = "\033[I";
+    public static final String FOCUS_OUT_SEQ = "\033[O";
+
+    /**
+     * Possible states in which the current readline operation may be in.
+     */
+    protected enum State {
+        /**
+         * The user is just typing away
+         */
+        NORMAL,
+        /**
+         * readLine should exit and return the buffer content
+         */
+        DONE,
+        /**
+         * readLine should exit and throw an EOFException
+         */
+        EOF,
+        /**
+         * readLine should exit and throw an UserInterruptException
+         */
+        INTERRUPT
+    }
+
+    protected enum ViMoveMode {
+        NORMAL,
+        YANK,
+        DELETE,
+        CHANGE
+    }
+
+    protected enum BellType {
+        NONE,
+        AUDIBLE,
+        VISIBLE
+    }
+
+    //
+    // Constructor variables
+    //
+
+    /** The terminal to use */
+    protected final Terminal terminal;
+    /** The application name */
+    protected final String appName;
+    /** The terminal keys mapping */
+    protected final Map<String, KeyMap<Binding>> keyMaps;
+
+    //
+    // Configuration
+    //
+    protected final Map<String, Object> variables;
+    protected History history = new DefaultHistory();
+    protected Completer completer = null;
+    protected Highlighter highlighter = new DefaultHighlighter();
+    protected Parser parser = new DefaultParser();
+    protected Expander expander = new DefaultExpander();
+
+    //
+    // State variables
+    //
+
+    protected final Map<Option, Boolean> options = new HashMap<>();
+
+    protected final Buffer buf = new BufferImpl();
+
+    protected final Size size = new Size();
+
+    protected AttributedString prompt;
+    protected AttributedString rightPrompt;
+
+    protected MaskingCallback maskingCallback;
+
+    protected Map<Integer, String> modifiedHistory = new HashMap<>();
+    protected Buffer historyBuffer = null;
+    protected CharSequence searchBuffer;
+    protected StringBuffer searchTerm = null;
+    protected boolean searchFailing;
+    protected boolean searchBackward;
+    protected int searchIndex = -1;
+
+
+    // Reading buffers
+    protected final BindingReader bindingReader;
+
+
+    /**
+     * VI character find
+     */
+    protected int findChar;
+    protected int findDir;
+    protected int findTailAdd;
+    /**
+     * VI history string search
+     */
+    private int searchDir;
+    private String searchString;
+
+    /**
+     * Region state
+     */
+    protected int regionMark;
+    protected RegionType regionActive;
+
+    private boolean forceChar;
+    private boolean forceLine;
+
+    /**
+     * The vi yank buffer
+     */
+    protected String yankBuffer = "";
+
+    protected ViMoveMode viMoveMode = ViMoveMode.NORMAL;
+
+    protected KillRing killRing = new KillRing();
+
+    protected UndoTree<Buffer> undo = new UndoTree<>(this::setBuffer);
+    protected boolean isUndo;
+
+    /*
+     * Current internal state of the line reader
+     */
+    protected State   state = State.DONE;
+    protected final AtomicBoolean startedReading = new AtomicBoolean();
+    protected boolean reading;
+
+    protected Supplier<AttributedString> post;
+
+    protected Map<String, Widget> builtinWidgets;
+    protected Map<String, Widget> widgets;
+
+    protected int count;
+    protected int mult;
+    protected int universal = 4;
+    protected int repeatCount;
+    protected boolean isArgDigit;
+
+    protected ParsedLine parsedLine;
+
+    protected boolean skipRedisplay;
+    protected Display display;
+
+    protected boolean overTyping = false;
+
+    protected String keyMap;
+
+    protected int smallTerminalOffset = 0;
+
+
+
+    public LineReaderImpl(Terminal terminal) throws IOException {
+        this(terminal, null, null);
+    }
+
+    public LineReaderImpl(Terminal terminal, String appName) throws IOException {
+        this(terminal, appName, null);
+    }
+
+    public LineReaderImpl(Terminal terminal, String appName, Map<String, Object> variables) {
+        Objects.requireNonNull(terminal, "terminal can not be null");
+        this.terminal = terminal;
+        if (appName == null) {
+            appName = "JLine";
+        }
+        this.appName = appName;
+        if (variables != null) {
+            this.variables = variables;
+        } else {
+            this.variables = new HashMap<>();
+        }
+        this.keyMaps = defaultKeyMaps();
+
+        builtinWidgets = builtinWidgets();
+        widgets = new HashMap<>(builtinWidgets);
+        bindingReader = new BindingReader(terminal.reader());
+    }
+
+    public Terminal getTerminal() {
+        return terminal;
+    }
+
+    public String getAppName() {
+        return appName;
+    }
+
+    public Map<String, KeyMap<Binding>> getKeyMaps() {
+        return keyMaps;
+    }
+
+    public KeyMap<Binding> getKeys() {
+        return keyMaps.get(keyMap);
+    }
+
+    @Override
+    public Map<String, Widget> getWidgets() {
+        return widgets;
+    }
+
+    @Override
+    public Map<String, Widget> getBuiltinWidgets() {
+        return Collections.unmodifiableMap(builtinWidgets);
+    }
+
+    @Override
+    public Buffer getBuffer() {
+        return buf;
+    }
+
+    @Override
+    public void runMacro(String macro) {
+        bindingReader.runMacro(macro);
+    }
+
+    @Override
+    public MouseEvent readMouseEvent() {
+        return terminal.readMouseEvent(bindingReader::readCharacter);
+    }
+
+    /**
+     * Set the completer.
+     *
+     * @param completer the completer to use
+     */
+    public void setCompleter(Completer completer) {
+        this.completer = completer;
+    }
+
+    /**
+     * Returns the completer.
+     *
+     * @return the completer
+     */
+    public Completer getCompleter() {
+        return completer;
+    }
+
+    //
+    // History
+    //
+
+    public void setHistory(final History history) {
+        Objects.requireNonNull(history);
+        this.history = history;
+    }
+
+    public History getHistory() {
+        return history;
+    }
+
+    //
+    // Highlighter
+    //
+
+    public void setHighlighter(Highlighter highlighter) {
+        this.highlighter = highlighter;
+    }
+
+    public Highlighter getHighlighter() {
+        return highlighter;
+    }
+
+    public Parser getParser() {
+        return parser;
+    }
+
+    public void setParser(Parser parser) {
+        this.parser = parser;
+    }
+
+    @Override
+    public Expander getExpander() {
+        return expander;
+    }
+
+    public void setExpander(Expander expander) {
+        this.expander = expander;
+    }
+
+    //
+    // Line Reading
+    //
+
+    /**
+     * Read the next line and return the contents of the buffer.
+     *
+     * @return          A line that is read from the terminal, can never be null.
+     */
+    public String readLine() throws UserInterruptException, EndOfFileException {
+        return readLine(null, null, (MaskingCallback) null, null);
+    }
+
+    /**
+     * Read the next line with the specified character mask. If null, then
+     * characters will be echoed. If 0, then no characters will be echoed.
+     *
+     * @param mask      The mask character, <code>null</code> or <code>0</code>.
+     * @return          A line that is read from the terminal, can never be null.
+     */
+    public String readLine(Character mask) throws UserInterruptException, EndOfFileException {
+        return readLine(null, null, mask, null);
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     * @return          A line that is read from the terminal, can never be null.
+     */
+    public String readLine(String prompt) throws UserInterruptException, EndOfFileException {
+        return readLine(prompt, null, (MaskingCallback) null, null);
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     * @param mask      The mask character, <code>null</code> or <code>0</code>.
+     * @return          A line that is read from the terminal, can never be null.
+     */
+    public String readLine(String prompt, Character mask) throws UserInterruptException, EndOfFileException {
+        return readLine(prompt, null, mask, null);
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt    The prompt to issue to the terminal, may be null.
+     * @param mask      The mask character, <code>null</code> or <code>0</code>.
+     * @param buffer    A string that will be set for editing.
+     * @return          A line that is read from the terminal, can never be null.
+     */
+    public String readLine(String prompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException {
+        return readLine(prompt, null, mask, buffer);
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt      The prompt to issue to the terminal, may be null.
+     * @param rightPrompt The prompt to issue to the right of the terminal, may be null.
+     * @param mask        The mask character, <code>null</code> or <code>0</code>.
+     * @param buffer      A string that will be set for editing.
+     * @return            A line that is read from the terminal, can never be null.
+     */
+    public String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException {
+        return readLine(prompt, rightPrompt, mask != null ? new SimpleMaskingCallback(mask) : null, buffer);
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt          The prompt to issue to the terminal, may be null.
+     * @param rightPrompt     The prompt to issue to the right of the terminal, may be null.
+     * @param maskingCallback The callback used to mask parts of the edited line.
+     * @param buffer          A string that will be set for editing.
+     * @return                A line that is read from the terminal, can never be null.
+     */
+    public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException {
+        // prompt may be null
+        // maskingCallback may be null
+        // buffer may be null
+
+        if (!startedReading.compareAndSet(false, true)) {
+            throw new IllegalStateException();
+        }
+
+        Thread readLineThread = Thread.currentThread();
+        SignalHandler previousIntrHandler = null;
+        SignalHandler previousWinchHandler = null;
+        SignalHandler previousContHandler = null;
+        Attributes originalAttributes = null;
+        boolean dumb = Terminal.TYPE_DUMB.equals(terminal.getType())
+                    || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType());
+        try {
+
+            this.maskingCallback = maskingCallback;
+
+            /*
+             * This is the accumulator for VI-mode repeat count. That is, while in
+             * move mode, if you type 30x it will delete 30 characters. This is
+             * where the "30" is accumulated until the command is struck.
+             */
+            repeatCount = 0;
+            mult = 1;
+            regionActive = RegionType.NONE;
+            regionMark = -1;
+
+            smallTerminalOffset = 0;
+
+            state = State.NORMAL;
+
+            modifiedHistory.clear();
+
+            setPrompt(prompt);
+            setRightPrompt(rightPrompt);
+            buf.clear();
+            if (buffer != null) {
+                buf.write(buffer);
+            }
+            undo.clear();
+            parsedLine = null;
+            keyMap = MAIN;
+
+            if (history != null) {
+                history.attach(this);
+            }
+
+            synchronized (this) {
+                this.reading = true;
+
+                previousIntrHandler = terminal.handle(Signal.INT, signal -> readLineThread.interrupt());
+                previousWinchHandler = terminal.handle(Signal.WINCH, this::handleSignal);
+                previousContHandler = terminal.handle(Signal.CONT, this::handleSignal);
+                originalAttributes = terminal.enterRawMode();
+
+                // Cache terminal size for the duration of the call to readLine()
+                // It will eventually be updated with WINCH signals
+                size.copy(terminal.getSize());
+
+                display = new Display(terminal, false);
+                if (size.getRows() == 0 || size.getColumns() == 0) {
+                    display.resize(1, Integer.MAX_VALUE);
+                } else {
+                    display.resize(size.getRows(), size.getColumns());
+                }
+                if (isSet(Option.DELAY_LINE_WRAP))
+                    display.setDelayLineWrap(true);
+
+                // Move into application mode
+                if (!dumb) {
+                    terminal.puts(Capability.keypad_xmit);
+                    if (isSet(Option.AUTO_FRESH_LINE))
+                        callWidget(FRESH_LINE);
+                    if (isSet(Option.MOUSE))
+                        terminal.trackMouse(Terminal.MouseTracking.Normal);
+                    if (isSet(Option.BRACKETED_PASTE))
+                        terminal.writer().write(BRACKETED_PASTE_ON);
+                } else {
+                    // For dumb terminals, we need to make sure that CR are ignored
+                    Attributes attr = new Attributes(originalAttributes);
+                    attr.setInputFlag(Attributes.InputFlag.IGNCR, true);
+                    terminal.setAttributes(attr);
+                }
+
+                callWidget(CALLBACK_INIT);
+
+                undo.newState(buf.copy());
+
+                // Draw initial prompt
+                redrawLine();
+                redisplay();
+            }
+
+            while (true) {
+
+                KeyMap<Binding> local = null;
+                if (isInViCmdMode() && regionActive != RegionType.NONE) {
+                    local = keyMaps.get(VISUAL);
+                }
+                Binding o = readBinding(getKeys(), local);
+                if (o == null) {
+                    throw new EndOfFileException();
+                }
+                Log.trace("Binding: ", o);
+                if (buf.length() == 0 && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) {
+                    throw new EndOfFileException();
+                }
+
+                // If this is still false after handling the binding, then
+                // we reset our repeatCount to 0.
+                isArgDigit = false;
+                // Every command that can be repeated a specified number
+                // of times, needs to know how many times to repeat, so
+                // we figure that out here.
+                count = ((repeatCount == 0) ? 1 : repeatCount) * mult;
+                // Reset undo/redo flag
+                isUndo = false;
+                // Reset region after a paste
+                if (regionActive == RegionType.PASTE) {
+                    regionActive = RegionType.NONE;
+                }
+
+                synchronized (this) {
+                    // Get executable widget
+                    Buffer copy = buf.copy();
+                    Widget w = getWidget(o);
+                    if (!w.apply()) {
+                        beep();
+                    }
+                    if (!isUndo && !copy.toString().equals(buf.toString())) {
+                        undo.newState(buf.copy());
+                    }
+
+                    switch (state) {
+                        case DONE:
+                            return finishBuffer();
+                        case EOF:
+                            throw new EndOfFileException();
+                        case INTERRUPT:
+                            throw new UserInterruptException(buf.toString());
+                    }
+
+                    if (!isArgDigit) {
+                        /*
+                         * If the operation performed wasn't a vi argument
+                         * digit, then clear out the current repeatCount;
+                         */
+                        repeatCount = 0;
+                        mult = 1;
+                    }
+
+                    if (!dumb) {
+                        redisplay();
+                    }
+                }
+            }
+        } catch (IOError e) {
+            if (e.getCause() instanceof InterruptedIOException) {
+                throw new UserInterruptException(buf.toString());
+            } else {
+                throw e;
+            }
+        }
+        finally {
+            synchronized (this) {
+                this.reading = false;
+
+                cleanup();
+                if (originalAttributes != null) {
+                    terminal.setAttributes(originalAttributes);
+                }
+                if (previousIntrHandler != null) {
+                    terminal.handle(Signal.INT, previousIntrHandler);
+                }
+                if (previousWinchHandler != null) {
+                    terminal.handle(Signal.WINCH, previousWinchHandler);
+                }
+                if (previousContHandler != null) {
+                    terminal.handle(Signal.CONT, previousContHandler);
+                }
+            }
+            startedReading.set(false);
+        }
+    }
+
+    @Override
+    public synchronized void printAbove(String str) {
+        boolean reading = this.reading;
+        if (reading) {
+            display.update(Collections.emptyList(), 0);
+        }
+        if (str.endsWith("\n")) {
+            terminal.writer().print(str);
+        } else {
+            terminal.writer().println(str);
+        }
+        if (reading) {
+            redisplay(false);
+        }
+        terminal.flush();
+    }
+
+    @Override
+    public void printAbove(AttributedString str) {
+        printAbove(str.toAnsi(terminal));
+    }
+
+    @Override
+    public synchronized boolean isReading() {
+        return reading;
+    }
+
+    /* Make sure we position the cursor on column 0 */
+    protected boolean freshLine() {
+        boolean wrapAtEol = terminal.getBooleanCapability(Capability.auto_right_margin);
+        boolean delayedWrapAtEol = wrapAtEol && terminal.getBooleanCapability(Capability.eat_newline_glitch);
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        sb.style(AttributedStyle.DEFAULT.foreground(AttributedStyle.BLACK + AttributedStyle.BRIGHT));
+        sb.append("~");
+        sb.style(AttributedStyle.DEFAULT);
+        if (!wrapAtEol || delayedWrapAtEol) {
+            for (int i = 0; i < size.getColumns() - 1; i++) {
+                sb.append(" ");
+            }
+            sb.append(KeyMap.key(terminal, Capability.carriage_return));
+            sb.append(" ");
+            sb.append(KeyMap.key(terminal, Capability.carriage_return));
+        } else {
+            // Given the terminal will wrap automatically,
+            // we need to print one less than needed.
+            // This means that the last character will not
+            // be overwritten, and that's why we're using
+            // a clr_eol first if possible.
+            String el = terminal.getStringCapability(Capability.clr_eol);
+            if (el != null) {
+                Curses.tputs(sb, el);
+            }
+            for (int i = 0; i < size.getColumns() - 2; i++) {
+                sb.append(" ");
+            }
+            sb.append(KeyMap.key(terminal, Capability.carriage_return));
+            sb.append(" ");
+            sb.append(KeyMap.key(terminal, Capability.carriage_return));
+        }
+        print(sb.toAnsi(terminal));
+        return true;
+    }
+
+    @Override
+    public synchronized void callWidget(String name) {
+        if (!reading) {
+            throw new IllegalStateException("Widgets can only be called during a `readLine` call");
+        }
+        try {
+            Widget w;
+            if (name.startsWith(".")) {
+                w = builtinWidgets.get(name.substring(1));
+            } else {
+                w = widgets.get(name);
+            }
+            if (w != null) {
+                w.apply();
+            }
+        } catch (Throwable t) {
+            Log.debug("Error executing widget '", name, "'", t);
+        }
+    }
+
+    /**
+     * Clear the line and redraw it.
+     * @return <code>true</code>
+     */
+    public boolean redrawLine() {
+        display.reset();
+        return true;
+    }
+
+    /**
+     * Write out the specified string to the buffer and the output stream.
+     * @param str the char sequence to write in the buffer
+     */
+    public void putString(final CharSequence str) {
+        buf.write(str, overTyping);
+    }
+
+    /**
+     * Flush the terminal output stream. This is important for printout out single
+     * characters (like a buf.backspace or keyboard) that we want the terminal to
+     * handle immediately.
+     */
+    public void flush() {
+        terminal.flush();
+    }
+
+    public boolean isKeyMap(String name) {
+        return keyMap.equals(name);
+    }
+
+    /**
+     * Read a character from the terminal.
+     *
+     * @return the character, or -1 if an EOF is received.
+     */
+    public int readCharacter() {
+        return bindingReader.readCharacter();
+    }
+
+    public int peekCharacter(long timeout) {
+        return bindingReader.peekCharacter(timeout);
+    }
+
+    /**
+     * Read from the input stream and decode an operation from the key map.
+     *
+     * The input stream will be read character by character until a matching
+     * binding can be found.  Characters that can't possibly be matched to
+     * any binding will be discarded.
+     *
+     * @param keys the KeyMap to use for decoding the input stream
+     * @return the decoded binding or <code>null</code> if the end of
+     *         stream has been reached
+     */
+    public Binding readBinding(KeyMap<Binding> keys) {
+        return readBinding(keys, null);
+    }
+
+    public Binding readBinding(KeyMap<Binding> keys, KeyMap<Binding> local) {
+        Binding o = bindingReader.readBinding(keys, local);
+        /*
+         * The kill ring keeps record of whether or not the
+         * previous command was a yank or a kill. We reset
+         * that state here if needed.
+         */
+        if (o instanceof Reference) {
+            String ref = ((Reference) o).name();
+            if (!YANK_POP.equals(ref) && !YANK.equals(ref)) {
+                killRing.resetLastYank();
+            }
+            if (!KILL_LINE.equals(ref) && !KILL_WHOLE_LINE.equals(ref)
+                    && !BACKWARD_KILL_WORD.equals(ref) && !KILL_WORD.equals(ref)) {
+                killRing.resetLastKill();
+            }
+        }
+        return o;
+    }
+
+    @Override
+    public ParsedLine getParsedLine() {
+        return parsedLine;
+    }
+
+    public String getLastBinding() {
+        return bindingReader.getLastBinding();
+    }
+
+    public String getSearchTerm() {
+        return searchTerm != null ? searchTerm.toString() : null;
+    }
+
+    @Override
+    public RegionType getRegionActive() {
+        return regionActive;
+    }
+
+    @Override
+    public int getRegionMark() {
+        return regionMark;
+    }
+
+    //
+    // Key Bindings
+    //
+
+    /**
+     * Sets the current keymap by name. Supported keymaps are "emacs",
+     * "viins", "vicmd".
+     * @param name The name of the keymap to switch to
+     * @return true if the keymap was set, or false if the keymap is
+     *    not recognized.
+     */
+    public boolean setKeyMap(String name) {
+        KeyMap<Binding> map = keyMaps.get(name);
+        if (map == null) {
+            return false;
+        }
+        this.keyMap = name;
+        if (reading) {
+            callWidget(CALLBACK_KEYMAP);
+        }
+        return true;
+    }
+
+    /**
+     * Returns the name of the current key mapping.
+     * @return the name of the key mapping. This will be the canonical name
+     *   of the current mode of the key map and may not reflect the name that
+     *   was used with {@link #setKeyMap(String)}.
+     */
+    public String getKeyMap() {
+        return keyMap;
+    }
+
+    @Override
+    public LineReader variable(String name, Object value) {
+        variables.put(name, value);
+        return this;
+    }
+
+    @Override
+    public Map<String, Object> getVariables() {
+        return variables;
+    }
+
+    @Override
+    public Object getVariable(String name) {
+        return variables.get(name);
+    }
+
+    @Override
+    public void setVariable(String name, Object value) {
+        variables.put(name, value);
+    }
+
+    @Override
+    public LineReader option(Option option, boolean value) {
+        options.put(option, value);
+        return this;
+    }
+
+    @Override
+    public boolean isSet(Option option) {
+        Boolean b = options.get(option);
+        return b != null ? b : option.isDef();
+    }
+
+    @Override
+    public void setOpt(Option option) {
+        options.put(option, Boolean.TRUE);
+    }
+
+    @Override
+    public void unsetOpt(Option option) {
+        options.put(option, Boolean.FALSE);
+    }
+
+
+
+    //
+    // Widget implementation
+    //
+
+    /**
+     * Clear the buffer and add its contents to the history.
+     *
+     * @return the former contents of the buffer.
+     */
+    protected String finishBuffer() {
+        String str = buf.toString();
+        String historyLine = str;
+
+        if (!isSet(Option.DISABLE_EVENT_EXPANSION)) {
+            StringBuilder sb = new StringBuilder();
+            boolean escaped = false;
+            for (int i = 0; i < str.length(); i++) {
+                char ch = str.charAt(i);
+                if (escaped) {
+                    escaped = false;
+                    if (ch != '\n') {
+                        sb.append(ch);
+                    }
+                } else if (ch == '\\') {
+                    escaped = true;
+                } else {
+                    sb.append(ch);
+                }
+            }
+            str = sb.toString();
+        }
+
+        if (maskingCallback != null) {
+            historyLine = maskingCallback.history(historyLine);
+        }
+
+        // we only add it to the history if the buffer is not empty
+        if (historyLine != null && historyLine.length() > 0 ) {
+            history.add(Instant.now(), historyLine);
+        }
+        return str;
+    }
+
+    protected void handleSignal(Signal signal) {
+        if (signal == Signal.WINCH) {
+            size.copy(terminal.getSize());
+            display.resize(size.getRows(), size.getColumns());
+            redisplay();
+        }
+        else if (signal == Signal.CONT) {
+            terminal.enterRawMode();
+            size.copy(terminal.getSize());
+            display.resize(size.getRows(), size.getColumns());
+            terminal.puts(Capability.keypad_xmit);
+            redrawLine();
+            redisplay();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected Widget getWidget(Object binding) {
+        Widget w;
+        if (binding instanceof Widget) {
+            w = (Widget) binding;
+        } else if (binding instanceof Macro) {
+            String macro = ((Macro) binding).getSequence();
+            w = () -> {
+                bindingReader.runMacro(macro);
+                return true;
+            };
+        } else if (binding instanceof Reference) {
+            String name = ((Reference) binding).name();
+            w = widgets.get(name);
+            if (w == null) {
+                w = () -> {
+                    post = () -> new AttributedString("No such widget `" + name + "'");
+                    return false;
+                };
+            }
+        } else {
+            w = () -> {
+                post = () -> new AttributedString("Unsupported widget");
+                return false;
+            };
+        }
+        return w;
+    }
+
+    //
+    // Helper methods
+    //
+
+    public void setPrompt(final String prompt) {
+        this.prompt = (prompt == null ? AttributedString.EMPTY
+                       : expandPromptPattern(prompt, 0, "", 0));
+    }
+
+    public void setRightPrompt(final String rightPrompt) {
+        this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY
+                            : expandPromptPattern(rightPrompt, 0, "", 0));
+    }
+
+    protected void setBuffer(Buffer buffer) {
+        buf.copyFrom(buffer);
+    }
+
+    /**
+     * Set the current buffer's content to the specified {@link String}. The
+     * visual terminal will be modified to show the current buffer.
+     *
+     * @param buffer the new contents of the buffer.
+     */
+    protected void setBuffer(final String buffer) {
+        buf.clear();
+        buf.write(buffer);
+    }
+
+    /**
+     * This method is calling while doing a delete-to ("d"), change-to ("c"),
+     * or yank-to ("y") and it filters out only those movement operations
+     * that are allowable during those operations. Any operation that isn't
+     * allow drops you back into movement mode.
+     *
+     * @param op The incoming operation to remap
+     * @return The remaped operation
+     */
+    protected String viDeleteChangeYankToRemap (String op) {
+        switch (op) {
+            case SEND_BREAK:
+            case BACKWARD_CHAR:
+            case FORWARD_CHAR:
+            case END_OF_LINE:
+            case VI_MATCH_BRACKET:
+            case VI_DIGIT_OR_BEGINNING_OF_LINE:
+            case NEG_ARGUMENT:
+            case DIGIT_ARGUMENT:
+            case VI_BACKWARD_CHAR:
+            case VI_BACKWARD_WORD:
+            case VI_FORWARD_CHAR:
+            case VI_FORWARD_WORD:
+            case VI_FORWARD_WORD_END:
+            case VI_FIRST_NON_BLANK:
+            case VI_GOTO_COLUMN:
+            case VI_DELETE:
+            case VI_YANK:
+            case VI_CHANGE:
+            case VI_FIND_NEXT_CHAR:
+            case VI_FIND_NEXT_CHAR_SKIP:
+            case VI_FIND_PREV_CHAR:
+            case VI_FIND_PREV_CHAR_SKIP:
+            case VI_REPEAT_FIND:
+            case VI_REV_REPEAT_FIND:
+                return op;
+
+            default:
+                return VI_CMD_MODE;
+        }
+    }
+
+    protected int switchCase(int ch) {
+        if (Character.isUpperCase(ch)) {
+            return Character.toLowerCase(ch);
+        } else if (Character.isLowerCase(ch)) {
+            return Character.toUpperCase(ch);
+        } else {
+            return ch;
+        }
+    }
+
+    /**
+     * @return true if line reader is in the middle of doing a change-to
+     *   delete-to or yank-to.
+     */
+    protected boolean isInViMoveOperation() {
+        return viMoveMode != ViMoveMode.NORMAL;
+    }
+
+    protected boolean isInViChangeOperation() {
+        return viMoveMode == ViMoveMode.CHANGE;
+    }
+
+    protected boolean isInViCmdMode() {
+        return VICMD.equals(keyMap);
+    }
+
+
+    //
+    // Movement
+    //
+
+    protected boolean viForwardChar() {
+        if (count < 0) {
+            return callNeg(this::viBackwardChar);
+        }
+        int lim = findeol();
+        if (isInViCmdMode() && !isInViMoveOperation()) {
+            lim--;
+        }
+        if (buf.cursor() >= lim) {
+            return false;
+        }
+        while (count-- > 0 && buf.cursor() < lim) {
+            buf.move(1);
+        }
+        return true;
+    }
+
+    protected boolean viBackwardChar() {
+        if (count < 0) {
+            return callNeg(this::viForwardChar);
+        }
+        int lim = findbol();
+        if (buf.cursor() == lim) {
+            return false;
+        }
+        while (count-- > 0 && buf.cursor() > 0) {
+            buf.move(-1);
+            if (buf.currChar() == '\n') {
+                buf.move(1);
+                break;
+            }
+        }
+        return true;
+    }
+
+
+    //
+    // Word movement
+    //
+
+    protected boolean forwardWord() {
+        if (count < 0) {
+            return callNeg(this::backwardWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length() && isWord(buf.currChar())) {
+                buf.move(1);
+            }
+            if (isInViChangeOperation() && count == 0) {
+                break;
+            }
+            while (buf.cursor() < buf.length() && !isWord(buf.currChar())) {
+                buf.move(1);
+            }
+        }
+        return true;
+    }
+
+    protected boolean viForwardWord() {
+        if (count < 0) {
+            return callNeg(this::backwardWord);
+        }
+        while (count-- > 0) {
+            if (isViAlphaNum(buf.currChar())) {
+                while (buf.cursor() < buf.length() && isViAlphaNum(buf.currChar())) {
+                    buf.move(1);
+                }
+            } else {
+                while (buf.cursor() < buf.length()
+                        && !isViAlphaNum(buf.currChar())
+                        && !isWhitespace(buf.currChar())) {
+                    buf.move(1);
+                }
+            }
+            if (isInViChangeOperation() && count == 0) {
+                return true;
+            }
+            int nl = buf.currChar() == '\n' ? 1 : 0;
+            while (buf.cursor() < buf.length()
+                    && nl < 2
+                    && isWhitespace(buf.currChar())) {
+                buf.move(1);
+                nl += buf.currChar() == '\n' ? 1 : 0;
+            }
+        }
+        return true;
+    }
+
+    protected boolean viForwardBlankWord() {
+        if (count < 0) {
+            return callNeg(this::viBackwardBlankWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length() && !isWhitespace(buf.currChar())) {
+                buf.move(1);
+            }
+            if (isInViChangeOperation() && count == 0) {
+                return true;
+            }
+            int nl = buf.currChar() == '\n' ? 1 : 0;
+            while (buf.cursor() < buf.length()
+                    && nl < 2
+                    && isWhitespace(buf.currChar())) {
+                buf.move(1);
+                nl += buf.currChar() == '\n' ? 1 : 0;
+            }
+        }
+        return true;
+    }
+
+    protected boolean emacsForwardWord() {
+        if (count < 0) {
+            return callNeg(this::emacsBackwardWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length() && !isWord(buf.currChar())) {
+                buf.move(1);
+            }
+            if (isInViChangeOperation() && count == 0) {
+                return true;
+            }
+            while (buf.cursor() < buf.length() && isWord(buf.currChar())) {
+                buf.move(1);
+            }
+        }
+        return true;
+    }
+
+    protected boolean viForwardBlankWordEnd() {
+        if (count < 0) {
+            return false;
+        }
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length()) {
+                buf.move(1);
+                if (!isWhitespace(buf.currChar())) {
+                    break;
+                }
+            }
+            while (buf.cursor() < buf.length()) {
+                buf.move(1);
+                if (isWhitespace(buf.currChar())) {
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected boolean viForwardWordEnd() {
+        if (count < 0) {
+            return callNeg(this::backwardWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length()) {
+                if (!isWhitespace(buf.nextChar())) {
+                    break;
+                }
+                buf.move(1);
+            }
+            if (buf.cursor() < buf.length()) {
+                if (isViAlphaNum(buf.nextChar())) {
+                    buf.move(1);
+                    while (buf.cursor() < buf.length() && isViAlphaNum(buf.nextChar())) {
+                        buf.move(1);
+                    }
+                } else {
+                    buf.move(1);
+                    while (buf.cursor() < buf.length() && !isViAlphaNum(buf.nextChar()) && !isWhitespace(buf.nextChar())) {
+                        buf.move(1);
+                    }
+                }
+            }
+        }
+        if (buf.cursor() < buf.length() && isInViMoveOperation()) {
+            buf.move(1);
+        }
+        return true;
+    }
+
+    protected boolean backwardWord() {
+        if (count < 0) {
+            return callNeg(this::forwardWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() > 0 && !isWord(buf.atChar(buf.cursor() - 1))) {
+                buf.move(-1);
+            }
+            while (buf.cursor() > 0 && isWord(buf.atChar(buf.cursor() - 1))) {
+                buf.move(-1);
+            }
+        }
+        return true;
+    }
+
+    protected boolean viBackwardWord() {
+        if (count < 0) {
+            return callNeg(this::backwardWord);
+        }
+        while (count-- > 0) {
+            int nl = 0;
+            while (buf.cursor() > 0) {
+                buf.move(-1);
+                if (!isWhitespace(buf.currChar())) {
+                    break;
+                }
+                nl += buf.currChar() == '\n' ? 1 : 0;
+                if (nl == 2) {
+                    buf.move(1);
+                    break;
+                }
+            }
+            if (buf.cursor() > 0) {
+                if (isViAlphaNum(buf.currChar())) {
+                    while (buf.cursor() > 0) {
+                        if (!isViAlphaNum(buf.prevChar())) {
+                            break;
+                        }
+                        buf.move(-1);
+                    }
+                } else {
+                    while (buf.cursor() > 0) {
+                        if (isViAlphaNum(buf.prevChar()) || isWhitespace(buf.prevChar())) {
+                            break;
+                        }
+                        buf.move(-1);
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    protected boolean viBackwardBlankWord() {
+        if (count < 0) {
+            return callNeg(this::viForwardBlankWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() > 0) {
+                buf.move(-1);
+                if (!isWhitespace(buf.currChar())) {
+                    break;
+                }
+            }
+            while (buf.cursor() > 0) {
+                buf.move(-1);
+                if (isWhitespace(buf.currChar())) {
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected boolean viBackwardWordEnd() {
+        if (count < 0) {
+            return callNeg(this::viForwardWordEnd);
+        }
+        while (count-- > 0 && buf.cursor() > 1) {
+            int start;
+            if (isViAlphaNum(buf.currChar())) {
+                start = 1;
+            } else if (!isWhitespace(buf.currChar())) {
+                start = 2;
+            } else {
+                start = 0;
+            }
+            while (buf.cursor() > 0) {
+                boolean same = (start != 1) && isWhitespace(buf.currChar());
+                if (start != 0) {
+                    same |= isViAlphaNum(buf.currChar());
+                }
+                if (same == (start == 2)) {
+                    break;
+                }
+                buf.move(-1);
+            }
+            while (buf.cursor() > 0 && isWhitespace(buf.currChar())) {
+                buf.move(-1);
+            }
+        }
+        return true;
+    }
+
+    protected boolean viBackwardBlankWordEnd() {
+        if (count < 0) {
+            return callNeg(this::viForwardBlankWordEnd);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() > 0 && !isWhitespace(buf.currChar())) {
+                buf.move(-1);
+            }
+            while (buf.cursor() > 0 && isWhitespace(buf.currChar())) {
+                buf.move(-1);
+            }
+        }
+        return true;
+    }
+
+    protected boolean emacsBackwardWord() {
+        if (count < 0) {
+            return callNeg(this::emacsForwardWord);
+        }
+        while (count-- > 0) {
+            while (buf.cursor() > 0) {
+                buf.move(-1);
+                if (isWord(buf.currChar())) {
+                    break;
+                }
+            }
+            while (buf.cursor() > 0) {
+                buf.move(-1);
+                if (!isWord(buf.currChar())) {
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected boolean backwardDeleteWord() {
+        if (count < 0) {
+            return callNeg(this::deleteWord);
+        }
+        int cursor = buf.cursor();
+        while (count-- > 0) {
+            while (cursor > 0 && !isWord(buf.atChar(cursor - 1))) {
+                cursor--;
+            }
+            while (cursor > 0 && isWord(buf.atChar(cursor - 1))) {
+                cursor--;
+            }
+        }
+        buf.backspace(buf.cursor() - cursor);
+        return true;
+    }
+
+    protected boolean viBackwardKillWord() {
+        if (count < 0) {
+            return false;
+        }
+        int lim = findbol();
+        int x = buf.cursor();
+        while (count-- > 0) {
+            while (x > lim && isWhitespace(buf.atChar(x - 1))) {
+                x--;
+            }
+            if (x > lim) {
+                if (isViAlphaNum(buf.atChar(x - 1))) {
+                    while (x > lim && isViAlphaNum(buf.atChar(x - 1))) {
+                        x--;
+                    }
+                } else {
+                    while (x > lim && !isViAlphaNum(buf.atChar(x - 1)) && !isWhitespace(buf.atChar(x - 1))) {
+                        x--;
+                    }
+                }
+            }
+        }
+        killRing.addBackwards(buf.substring(x, buf.cursor()));
+        buf.backspace(buf.cursor() - x);
+        return true;
+    }
+
+    protected boolean backwardKillWord() {
+        if (count < 0) {
+            return callNeg(this::killWord);
+        }
+        int x = buf.cursor();
+        while (count-- > 0) {
+            while (x > 0 && !isWord(buf.atChar(x - 1))) {
+                x--;
+            }
+            while (x > 0 && isWord(buf.atChar(x - 1))) {
+                x--;
+            }
+        }
+        killRing.addBackwards(buf.substring(x, buf.cursor()));
+        buf.backspace(buf.cursor() - x);
+        return true;
+    }
+
+    protected boolean copyPrevWord() {
+        if (count <= 0) {
+            return false;
+        }
+        int t1, t0 = buf.cursor();
+        while (true) {
+            t1 = t0;
+            while (t0 > 0 && !isWord(buf.atChar(t0 - 1))) {
+                t0--;
+            }
+            while (t0 > 0 && isWord(buf.atChar(t0 - 1))) {
+                t0--;
+            }
+            if (--count == 0) {
+                break;
+            }
+            if (t0 == 0) {
+                return false;
+            }
+        }
+        buf.write(buf.substring(t0, t1));
+        return true;
+    }
+
+    protected boolean upCaseWord() {
+        int count = Math.abs(this.count);
+        int cursor = buf.cursor();
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length() && !isWord(buf.currChar())) {
+                buf.move(1);
+            }
+            while (buf.cursor() < buf.length() && isWord(buf.currChar())) {
+                buf.currChar(Character.toUpperCase(buf.currChar()));
+                buf.move(1);
+            }
+        }
+        if (this.count < 0) {
+            buf.cursor(cursor);
+        }
+        return true;
+    }
+
+    protected boolean downCaseWord() {
+        int count = Math.abs(this.count);
+        int cursor = buf.cursor();
+        while (count-- > 0) {
+            while (buf.cursor() < buf.length() && !isWord(buf.currChar())) {
+                buf.move(1);
+            }
+            while (buf.cursor() < buf.length() && isWord(buf.currChar())) {
+                buf.currChar(Character.toLowerCase(buf.currChar()));
+                buf.move(1);
+            }
+        }
+        if (this.count < 0) {
+            buf.cursor(cursor);
+        }
+        return true;
+    }
+
+    protected boolean capitalizeWord() {
+        int count = Math.abs(this.count);
+        int cursor = buf.cursor();
+        while (count-- > 0) {
+            boolean first = true;
+            while (buf.cursor() < buf.length() && !isWord(buf.currChar())) {
+                buf.move(1);
+            }
+            while (buf.cursor() < buf.length() && isWord(buf.currChar()) && !isAlpha(buf.currChar())) {
+                buf.move(1);
+            }
+            while (buf.cursor() < buf.length() && isWord(buf.currChar())) {
+                buf.currChar(first
+                        ? Character.toUpperCase(buf.currChar())
+                        : Character.toLowerCase(buf.currChar()));
+                buf.move(1);
+                first = false;
+            }
+        }
+        if (this.count < 0) {
+            buf.cursor(cursor);
+        }
+        return true;
+    }
+
+    protected boolean deleteWord() {
+        if (count < 0) {
+            return callNeg(this::backwardDeleteWord);
+        }
+        int x = buf.cursor();
+        while (count-- > 0) {
+            while (x < buf.length() && !isWord(buf.atChar(x))) {
+                x++;
+            }
+            while (x < buf.length() && isWord(buf.atChar(x))) {
+                x++;
+            }
+        }
+        buf.delete(x - buf.cursor());
+        return true;
+    }
+
+    protected boolean killWord() {
+        if (count < 0) {
+            return callNeg(this::backwardKillWord);
+        }
+        int x = buf.cursor();
+        while (count-- > 0) {
+            while (x < buf.length() && !isWord(buf.atChar(x))) {
+                x++;
+            }
+            while (x < buf.length() && isWord(buf.atChar(x))) {
+                x++;
+            }
+        }
+        killRing.add(buf.substring(buf.cursor(), x));
+        buf.delete(x - buf.cursor());
+        return true;
+    }
+
+    protected boolean transposeWords() {
+        int lstart = buf.cursor() - 1;
+        int lend = buf.cursor();
+        while (buf.atChar(lstart) != 0 && buf.atChar(lstart) != '\n') {
+            lstart--;
+        }
+        lstart++;
+        while (buf.atChar(lend) != 0 && buf.atChar(lend) != '\n') {
+            lend++;
+        }
+        if (lend - lstart < 2) {
+            return false;
+        }
+        int words = 0;
+        boolean inWord = false;
+        if (!isDelimiter(buf.atChar(lstart))) {
+            words++;
+            inWord = true;
+        }
+        for (int i = lstart; i < lend; i++) {
+            if (isDelimiter(buf.atChar(i))) {
+                inWord = false;
+            } else {
+                if (!inWord) {
+                    words++;
+                }
+                inWord = true;
+            }
+        }
+        if (words < 2) {
+            return false;
+        }
+        // TODO: use isWord instead of isDelimiter
+        boolean neg = this.count < 0;
+        for (int count = Math.max(this.count, -this.count); count > 0; --count) {
+            int sta1, end1, sta2, end2;
+            // Compute current word boundaries
+            sta1 = buf.cursor();
+            while (sta1 > lstart && !isDelimiter(buf.atChar(sta1 - 1))) {
+                sta1--;
+            }
+            end1 = sta1;
+            while (end1 < lend && !isDelimiter(buf.atChar(++end1)));
+            if (neg) {
+                end2 = sta1 - 1;
+                while (end2 > lstart && isDelimiter(buf.atChar(end2 - 1))) {
+                    end2--;
+                }
+                if (end2 < lstart) {
+                    // No word before, use the word after
+                    sta2 = end1;
+                    while (isDelimiter(buf.atChar(++sta2)));
+                    end2 = sta2;
+                    while (end2 < lend && !isDelimiter(buf.atChar(++end2)));
+                } else {
+                    sta2 = end2;
+                    while (sta2 > lstart && !isDelimiter(buf.atChar(sta2 - 1))) {
+                        sta2--;
+                    }
+                }
+            } else {
+                sta2 = end1;
+                while (sta2 < lend && isDelimiter(buf.atChar(++sta2)));
+                if (sta2 == lend) {
+                    // No word after, use the word before
+                    end2 = sta1;
+                    while (isDelimiter(buf.atChar(end2 - 1))) {
+                        end2--;
+                    }
+                    sta2 = end2;
+                    while (sta2 > lstart && !isDelimiter(buf.atChar(sta2 - 1))) {
+                        sta2--;
+                    }
+                } else {
+                    end2 = sta2;
+                    while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ;
+                }
+            }
+            if (sta1 < sta2) {
+                String res = buf.substring(0, sta1) + buf.substring(sta2, end2)
+                        + buf.substring(end1, sta2) + buf.substring(sta1, end1)
+                        + buf.substring(end2);
+                buf.clear();
+                buf.write(res);
+                buf.cursor(neg ? end1 : end2);
+            } else {
+                String res = buf.substring(0, sta2) + buf.substring(sta1, end1)
+                        + buf.substring(end2, sta1) + buf.substring(sta2, end2)
+                        + buf.substring(end1);
+                buf.clear();
+                buf.write(res);
+                buf.cursor(neg ? end2 : end1);
+            }
+        }
+        return true;
+    }
+
+    private int findbol() {
+        int x = buf.cursor();
+        while (x > 0 && buf.atChar(x - 1) != '\n') {
+            x--;
+        }
+        return x;
+    }
+
+    private int findeol() {
+        int x = buf.cursor();
+        while (x < buf.length() && buf.atChar(x) != '\n') {
+            x++;
+        }
+        return x;
+    }
+
+    protected boolean insertComment() {
+        return doInsertComment(false);
+    }
+
+    protected boolean viInsertComment() {
+        return doInsertComment(true);
+    }
+
+    protected boolean doInsertComment(boolean isViMode) {
+        String comment = getString(COMMENT_BEGIN, DEFAULT_COMMENT_BEGIN);
+        beginningOfLine();
+        putString(comment);
+        if (isViMode) {
+            setKeyMap(VIINS);
+        }
+        return acceptLine();
+    }
+
+    protected boolean viFindNextChar() {
+        if ((findChar = vigetkey()) > 0) {
+            findDir = 1;
+            findTailAdd = 0;
+            return vifindchar(false);
+        }
+        return false;
+    }
+
+    protected boolean viFindPrevChar() {
+        if ((findChar = vigetkey()) > 0) {
+            findDir = -1;
+            findTailAdd = 0;
+            return vifindchar(false);
+        }
+        return false;
+    }
+
+    protected boolean viFindNextCharSkip() {
+        if ((findChar = vigetkey()) > 0) {
+            findDir = 1;
+            findTailAdd = -1;
+            return vifindchar(false);
+        }
+        return false;
+    }
+
+    protected boolean viFindPrevCharSkip() {
+        if ((findChar = vigetkey()) > 0) {
+            findDir = -1;
+            findTailAdd = 1;
+            return vifindchar(false);
+        }
+        return false;
+    }
+
+    protected boolean viRepeatFind() {
+        return vifindchar(true);
+    }
+
+    protected boolean viRevRepeatFind() {
+        if (count < 0) {
+            return callNeg(() -> vifindchar(true));
+        }
+        findTailAdd = -findTailAdd;
+        findDir = -findDir;
+        boolean ret = vifindchar(true);
+        findTailAdd = -findTailAdd;
+        findDir = -findDir;
+        return ret;
+    }
+
+    private int vigetkey() {
+        int ch = readCharacter();
+        KeyMap<Binding> km = keyMaps.get(MAIN);
+        if (km != null) {
+            Binding b = km.getBound(new String(Character.toChars(ch)));
+            if (b instanceof Reference) {
+                String func = ((Reference) b).name();
+                if (SEND_BREAK.equals(func)) {
+                    return -1;
+                }
+            }
+        }
+        return ch;
+    }
+
+    private boolean vifindchar(boolean repeat) {
+        if (findDir == 0) {
+            return false;
+        }
+        if (count < 0) {
+            return callNeg(this::viRevRepeatFind);
+        }
+        if (repeat && findTailAdd != 0) {
+            if (findDir > 0) {
+                if (buf.cursor() < buf.length() && buf.nextChar() == findChar) {
+                    buf.move(1);
+                }
+            } else {
+                if (buf.cursor() > 0 && buf.prevChar() == findChar) {
+                    buf.move(-1);
+                }
+            }
+        }
+        int cursor = buf.cursor();
+        while (count-- > 0) {
+            do {
+                buf.move(findDir);
+            } while (buf.cursor() > 0 && buf.cursor() < buf.length()
+                    && buf.currChar() != findChar
+                    && buf.currChar() != '\n');
+            if (buf.cursor() <= 0 || buf.cursor() >= buf.length()
+                    || buf.currChar() == '\n') {
+                buf.cursor(cursor);
+                return false;
+            }
+        }
+        if (findTailAdd != 0) {
+            buf.move(findTailAdd);
+        }
+        if (findDir == 1 && isInViMoveOperation()) {
+            buf.move(1);
+        }
+        return true;
+    }
+
+    private boolean callNeg(Widget widget) {
+        this.count = -this.count;
+        boolean ret = widget.apply();
+        this.count = -this.count;
+        return ret;
+    }
+
+    /**
+     * Implements vi search ("/" or "?").
+     *
+     * @return <code>true</code> if the search was successful
+     */
+    protected boolean viHistorySearchForward() {
+        searchDir = 1;
+        searchIndex = 0;
+        return getViSearchString() && viRepeatSearch();
+    }
+
+    protected boolean viHistorySearchBackward() {
+        searchDir = -1;
+        searchIndex = history.size() - 1;
+        return getViSearchString() && viRepeatSearch();
+    }
+
+    protected boolean viRepeatSearch() {
+        if (searchDir == 0) {
+            return false;
+        }
+        int si = searchDir < 0
+                ? searchBackwards(searchString, searchIndex, false)
+                : searchForwards(searchString, searchIndex, false);
+        if (si == -1 || si == history.index()) {
+            return false;
+        }
+        searchIndex = si;
+
+        /*
+         * Show the match.
+         */
+        buf.clear();
+        history.moveTo(searchIndex);
+        buf.write(history.get(searchIndex));
+        if (VICMD.equals(keyMap)) {
+            buf.move(-1);
+        }
+        return true;
+    }
+
+    protected boolean viRevRepeatSearch() {
+        boolean ret;
+        searchDir = -searchDir;
+        ret = viRepeatSearch();
+        searchDir = -searchDir;
+        return ret;
+    }
+
+    private boolean getViSearchString() {
+        if (searchDir == 0) {
+            return false;
+        }
+        String searchPrompt = searchDir < 0 ? "?" : "/";
+        Buffer searchBuffer = new BufferImpl();
+
+        KeyMap<Binding> keyMap = keyMaps.get(MAIN);
+        if (keyMap == null) {
+            keyMap = keyMaps.get(SAFE);
+        }
+        while (true) {
+            post = () -> new AttributedString(searchPrompt + searchBuffer.toString() + "_");
+            redisplay();
+            Binding b = bindingReader.readBinding(keyMap);
+            if (b instanceof Reference) {
+                String func = ((Reference) b).name();
+                switch (func) {
+                    case SEND_BREAK:
+                        post = null;
+                        return false;
+                    case ACCEPT_LINE:
+                    case VI_CMD_MODE:
+                        searchString = searchBuffer.toString();
+                        post = null;
+                        return true;
+                    case MAGIC_SPACE:
+                        searchBuffer.write(' ');
+                        break;
+                    case REDISPLAY:
+                        redisplay();
+                        break;
+                    case CLEAR_SCREEN:
+                        clearScreen();
+                        break;
+                    case SELF_INSERT:
+                        searchBuffer.write(getLastBinding());
+                        break;
+                    case SELF_INSERT_UNMETA:
+                        if (getLastBinding().charAt(0) == '\u001b') {
+                            String s = getLastBinding().substring(1);
+                            if ("\r".equals(s)) {
+                                s = "\n";
+                            }
+                            searchBuffer.write(s);
+                        }
+                        break;
+                    case BACKWARD_DELETE_CHAR:
+                    case VI_BACKWARD_DELETE_CHAR:
+                        if (searchBuffer.length() > 0) {
+                            searchBuffer.backspace();
+                        }
+                        break;
+                    case BACKWARD_KILL_WORD:
+                    case VI_BACKWARD_KILL_WORD:
+                        if (searchBuffer.length() > 0 && !isWhitespace(searchBuffer.prevChar())) {
+                            searchBuffer.backspace();
+                        }
+                        if (searchBuffer.length() > 0 && isWhitespace(searchBuffer.prevChar())) {
+                            searchBuffer.backspace();
+                        }
+                        break;
+                    case QUOTED_INSERT:
+                    case VI_QUOTED_INSERT:
+                        int c = readCharacter();
+                        if (c >= 0) {
+                            searchBuffer.write(c);
+                        } else {
+                            beep();
+                        }
+                        break;
+                    default:
+                        beep();
+                        break;
+                }
+            }
+        }
+    }
+
+    protected boolean insertCloseCurly() {
+        return insertClose("}");
+    }
+
+    protected boolean insertCloseParen() {
+        return insertClose(")");
+    }
+
+    protected boolean insertCloseSquare() {
+        return insertClose("]");
+    }
+
+    protected boolean insertClose(String s) {
+        putString(s);
+
+        long blink = getLong(BLINK_MATCHING_PAREN, DEFAULT_BLINK_MATCHING_PAREN);
+        if (blink <= 0) {
+            return true;
+        }
+
+        int closePosition = buf.cursor();
+
+        buf.move(-1);
+        doViMatchBracket();
+        redisplay();
+
+        peekCharacter(blink);
+
+        buf.cursor(closePosition);
+        return true;
+    }
+
+    protected boolean viMatchBracket() {
+        return doViMatchBracket();
+    }
+
+    protected boolean undefinedKey() {
+        return false;
+    }
+
+    /**
+     * Implements vi style bracket matching ("%" command). The matching
+     * bracket for the current bracket type that you are sitting on is matched.
+     *
+     * @return true if it worked, false if the cursor was not on a bracket
+     *   character or if there was no matching bracket.
+     */
+    protected boolean doViMatchBracket() {
+        int pos        = buf.cursor();
+
+        if (pos == buf.length()) {
+            return false;
+        }
+
+        int type       = getBracketType(buf.atChar(pos));
+        int move       = (type < 0) ? -1 : 1;
+        int count      = 1;
+
+        if (type == 0)
+            return false;
+
+        while (count > 0) {
+            pos += move;
+
+            // Fell off the start or end.
+            if (pos < 0 || pos >= buf.length()) {
+                return false;
+            }
+
+            int curType = getBracketType(buf.atChar(pos));
+            if (curType == type) {
+                ++count;
+            }
+            else if (curType == -type) {
+                --count;
+            }
+        }
+
+        /*
+         * Slight adjustment for delete-to, yank-to, change-to to ensure
+         * that the matching paren is consumed
+         */
+        if (move > 0 && isInViMoveOperation())
+            ++pos;
+
+        buf.cursor(pos);
+        return true;
+    }
+
+    /**
+     * Given a character determines what type of bracket it is (paren,
+     * square, curly, or none).
+     * @param ch The character to check
+     * @return 1 is square, 2 curly, 3 parent, or zero for none.  The value
+     *   will be negated if it is the closing form of the bracket.
+     */
+    protected int getBracketType (int ch) {
+        switch (ch) {
+            case '[': return  1;
+            case ']': return -1;
+            case '{': return  2;
+            case '}': return -2;
+            case '(': return  3;
+            case ')': return -3;
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Performs character transpose. The character prior to the cursor and the
+     * character under the cursor are swapped and the cursor is advanced one.
+     * Do not cross line breaks.
+     * @return true
+     */
+    protected boolean transposeChars() {
+        int lstart = buf.cursor() - 1;
+        int lend = buf.cursor();
+        while (buf.atChar(lstart) != 0 && buf.atChar(lstart) != '\n') {
+            lstart--;
+        }
+        lstart++;
+        while (buf.atChar(lend) != 0 && buf.atChar(lend) != '\n') {
+            lend++;
+        }
+        if (lend - lstart < 2) {
+            return false;
+        }
+        boolean neg = this.count < 0;
+        for (int count = Math.max(this.count, -this.count); count > 0; --count) {
+            while (buf.cursor() <= lstart) {
+                buf.move(1);
+            }
+            while (buf.cursor() >= lend) {
+                buf.move(-1);
+            }
+            int c = buf.currChar();
+            buf.currChar(buf.prevChar());
+            buf.move(-1);
+            buf.currChar(c);
+            buf.move(neg ? 0 : 2);
+        }
+        return true;
+    }
+
+    protected boolean undo() {
+        isUndo = true;
+        if (undo.canUndo()) {
+            undo.undo();
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean redo() {
+        isUndo = true;
+        if (undo.canRedo()) {
+            undo.redo();
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean sendBreak() {
+        if (searchTerm == null) {
+            buf.clear();
+            println();
+            redrawLine();
+//            state = State.INTERRUPT;
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean backwardChar() {
+        return buf.move(-count) != 0;
+    }
+
+    protected boolean forwardChar() {
+        return buf.move(count) != 0;
+    }
+
+    protected boolean viDigitOrBeginningOfLine() {
+        if (repeatCount > 0) {
+            return digitArgument();
+        } else {
+            return beginningOfLine();
+        }
+    }
+
+    protected boolean universalArgument() {
+        mult *= universal;
+        isArgDigit = true;
+        return true;
+    }
+
+    protected boolean argumentBase() {
+        if (repeatCount > 0 && repeatCount < 32) {
+            universal = repeatCount;
+            isArgDigit = true;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean negArgument() {
+        mult *= -1;
+        isArgDigit = true;
+        return true;
+    }
+
+    protected boolean digitArgument() {
+        String s = getLastBinding();
+        repeatCount = (repeatCount * 10) + s.charAt(s.length() - 1) - '0';
+        isArgDigit = true;
+        return true;
+    }
+
+    protected boolean viDelete() {
+        int cursorStart = buf.cursor();
+        Binding o = readBinding(getKeys());
+        if (o instanceof Reference) {
+            // TODO: be smarter on how to get the vi range
+            String op = viDeleteChangeYankToRemap(((Reference) o).name());
+            // This is a weird special case. In vi
+            // "dd" deletes the current line. So if we
+            // get a delete-to, followed by a delete-to,
+            // we delete the line.
+            if (VI_DELETE.equals(op)) {
+                killWholeLine();
+            } else {
+                viMoveMode = ViMoveMode.DELETE;
+                Widget widget = widgets.get(op);
+                if (widget != null && !widget.apply()) {
+                    viMoveMode = ViMoveMode.NORMAL;
+                    return false;
+                }
+                viMoveMode = ViMoveMode.NORMAL;
+            }
+            return viDeleteTo(cursorStart, buf.cursor());
+        } else {
+            pushBackBinding();
+            return false;
+        }
+    }
+
+    protected boolean viYankTo() {
+        int cursorStart = buf.cursor();
+        Binding o = readBinding(getKeys());
+        if (o instanceof Reference) {
+            // TODO: be smarter on how to get the vi range
+            String op = viDeleteChangeYankToRemap(((Reference) o).name());
+            // Similar to delete-to, a "yy" yanks the whole line.
+            if (VI_YANK.equals(op)) {
+                yankBuffer = buf.toString();
+                return true;
+            } else {
+                viMoveMode = ViMoveMode.YANK;
+                Widget widget = widgets.get(op);
+                if (widget != null && !widget.apply()) {
+                    return false;
+                }
+                viMoveMode = ViMoveMode.NORMAL;
+            }
+            return viYankTo(cursorStart, buf.cursor());
+        } else {
+            pushBackBinding();
+            return false;
+        }
+    }
+
+    protected boolean viYankWholeLine() {
+        int s, e;
+        int p = buf.cursor();
+        while (buf.move(-1) == -1 && buf.prevChar() != '\n') ;
+        s = buf.cursor();
+        for (int i = 0; i < repeatCount; i++) {
+            while (buf.move(1) == 1 && buf.prevChar() != '\n') ;
+        }
+        e = buf.cursor();
+        yankBuffer = buf.substring(s, e);
+        if (!yankBuffer.endsWith("\n")) {
+            yankBuffer += "\n";
+        }
+        buf.cursor(p);
+        return true;
+    }
+
+    protected boolean viChange() {
+        int cursorStart = buf.cursor();
+        Binding o = readBinding(getKeys());
+        if (o instanceof Reference) {
+            // TODO: be smarter on how to get the vi range
+            String op = viDeleteChangeYankToRemap(((Reference) o).name());
+            // change whole line
+            if (VI_CHANGE.equals(op)) {
+                killWholeLine();
+            } else {
+                viMoveMode = ViMoveMode.CHANGE;
+                Widget widget = widgets.get(op);
+                if (widget != null && !widget.apply()) {
+                    viMoveMode = ViMoveMode.NORMAL;
+                    return false;
+                }
+                viMoveMode = ViMoveMode.NORMAL;
+            }
+            boolean res = viChange(cursorStart, buf.cursor());
+            setKeyMap(VIINS);
+            return res;
+        } else {
+            pushBackBinding();
+            return false;
+        }
+    }
+
+    /*
+    protected int getViRange(Reference cmd, ViMoveMode mode) {
+        Buffer buffer = buf.copy();
+        int oldMark = mark;
+        int pos = buf.cursor();
+        String bind = getLastBinding();
+
+        if (visual != 0) {
+            if (buf.length() == 0) {
+                return -1;
+            }
+            pos = mark;
+            v
+        } else {
+            viMoveMode = mode;
+            mark = -1;
+            Binding b = bindingReader.readBinding(getKeys(), keyMaps.get(VIOPP));
+            if (b == null || new Reference(SEND_BREAK).equals(b)) {
+                viMoveMode = ViMoveMode.NORMAL;
+                mark = oldMark;
+                return -1;
+            }
+            if (cmd.equals(b)) {
+                doViLineRange();
+            }
+            Widget w = getWidget(b);
+            if (w )
+            if (b instanceof Reference) {
+
+            }
+        }
+
+    }
+    */
+
+    protected void cleanup() {
+        if (isSet(Option.ERASE_LINE_ON_FINISH)) {
+            Buffer oldBuffer = buf.copy();
+            AttributedString oldPrompt = prompt;
+            buf.clear();
+            prompt = new AttributedString("");
+            doCleanup(false);
+            prompt = oldPrompt;
+            buf.copyFrom(oldBuffer);
+        } else {
+            doCleanup(true);
+        }
+    }
+
+    protected void doCleanup(boolean nl) {
+        buf.cursor(buf.length());
+        post = null;
+        if (size.getColumns() > 0 || size.getRows() > 0) {
+            redisplay(false);
+            if (nl) {
+                println();
+            }
+            terminal.puts(Capability.keypad_local);
+            terminal.trackMouse(Terminal.MouseTracking.Off);
+            if (isSet(Option.BRACKETED_PASTE))
+                terminal.writer().write(BRACKETED_PASTE_OFF);
+            flush();
+        }
+        history.moveToEnd();
+    }
+
+    protected boolean historyIncrementalSearchForward() {
+        return doSearchHistory(false);
+    }
+
+    protected boolean historyIncrementalSearchBackward() {
+        return doSearchHistory(true);
+    }
+
+    static class Pair<U,V> {
+        final U u; final V v;
+        public Pair(U u, V v) {
+            this.u = u;
+            this.v = v;
+        }
+        public U getU() {
+            return u;
+        }
+        public V getV() {
+            return v;
+        }
+    }
+
+    protected boolean doSearchHistory(boolean backward) {
+        if (history.isEmpty()) {
+            return false;
+        }
+
+        KeyMap<Binding> terminators = new KeyMap<>();
+        getString(SEARCH_TERMINATORS, DEFAULT_SEARCH_TERMINATORS)
+                .codePoints().forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c))));
+
+        Buffer originalBuffer = buf.copy();
+        searchIndex = -1;
+        searchTerm = new StringBuffer();
+        searchBackward = backward;
+        searchFailing = false;
+        post = () -> new AttributedString((searchFailing ? "failing" + " " : "")
+                        + (searchBackward ? "bck-i-search" : "fwd-i-search")
+                        + ": " + searchTerm + "_");
+
+        redisplay();
+        try {
+            while (true) {
+                int prevSearchIndex = searchIndex;
+                Binding operation = readBinding(getKeys(), terminators);
+                String ref = (operation instanceof Reference) ? ((Reference) operation).name() : "";
+                boolean next = false;
+                switch (ref) {
+                    case SEND_BREAK:
+                        beep();
+                        buf.copyFrom(originalBuffer);
+                        return true;
+                    case HISTORY_INCREMENTAL_SEARCH_BACKWARD:
+                        searchBackward = true;
+                        next = true;
+                        break;
+                    case HISTORY_INCREMENTAL_SEARCH_FORWARD:
+                        searchBackward = false;
+                        next = true;
+                        break;
+                    case BACKWARD_DELETE_CHAR:
+                        if (searchTerm.length() > 0) {
+                            searchTerm.deleteCharAt(searchTerm.length() - 1);
+                        }
+                        break;
+                    case SELF_INSERT:
+                        searchTerm.append(getLastBinding());
+                        break;
+                    default:
+                        // Set buffer and cursor position to the found string.
+                        if (searchIndex != -1) {
+                            history.moveTo(searchIndex);
+                        }
+                        pushBackBinding();
+                        return true;
+                }
+
+                // print the search status
+                String pattern = doGetSearchPattern();
+                if (pattern.length() == 0) {
+                    buf.copyFrom(originalBuffer);
+                    searchFailing = false;
+                } else {
+                    boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH);
+                    Pattern pat = Pattern.compile(pattern, caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
+                                                                           : Pattern.UNICODE_CASE);
+                    Pair<Integer, Integer> pair = null;
+                    if (searchBackward) {
+                        boolean nextOnly = next;
+                        pair = matches(pat, buf.toString(), searchIndex).stream()
+                                .filter(p -> nextOnly ? p.v < buf.cursor() : p.v <= buf.cursor())
+                                .max(Comparator.comparing(Pair::getV))
+                                .orElse(null);
+                        if (pair == null) {
+                            pair = StreamSupport.stream(
+                                    Spliterators.spliteratorUnknownSize(history.reverseIterator(searchIndex < 0 ? history.last() : searchIndex - 1), Spliterator.ORDERED), false)
+                                    .flatMap(e -> matches(pat, e.line(), e.index()).stream())
+                                    .findFirst()
+                                    .orElse(null);
+                        }
+                    } else {
+                        boolean nextOnly = next;
+                        pair = matches(pat, buf.toString(), searchIndex).stream()
+                                .filter(p -> nextOnly ? p.v > buf.cursor() : p.v >= buf.cursor())
+                                .min(Comparator.comparing(Pair::getV))
+                                .orElse(null);
+                        if (pair == null) {
+                            pair = StreamSupport.stream(
+                                    Spliterators.spliteratorUnknownSize(history.iterator((searchIndex < 0 ? history.last() : searchIndex) + 1), Spliterator.ORDERED), false)
+                                    .flatMap(e -> matches(pat, e.line(), e.index()).stream())
+                                    .findFirst()
+                                    .orElse(null);
+                            if (pair == null && searchIndex >= 0) {
+                                pair = matches(pat, originalBuffer.toString(), -1).stream()
+                                        .min(Comparator.comparing(Pair::getV))
+                                        .orElse(null);
+                            }
+                        }
+                    }
+                    if (pair != null) {
+                        searchIndex = pair.u;
+                        buf.clear();
+                        if (searchIndex >= 0) {
+                            buf.write(history.get(searchIndex));
+                        } else {
+                            buf.write(originalBuffer.toString());
+                        }
+                        buf.cursor(pair.v);
+                        searchFailing = false;
+                    } else {
+                        searchFailing = true;
+                        beep();
+                    }
+                }
+                redisplay();
+            }
+        } catch (IOError e) {
+            // Ignore Ctrl+C interrupts and just exit the loop
+            if (!(e.getCause() instanceof InterruptedException)) {
+                throw e;
+            }
+            return true;
+        } finally {
+            searchTerm = null;
+            searchIndex = -1;
+            post = null;
+        }
+    }
+
+    private List<Pair<Integer, Integer>> matches(Pattern p, String line, int index) {
+        List<Pair<Integer, Integer>> starts = new ArrayList<>();
+        Matcher m = p.matcher(line);
+        while (m.find()) {
+            starts.add(new Pair<>(index, m.start()));
+        }
+        return starts;
+   }
+
+    private String doGetSearchPattern() {
+        StringBuilder sb = new StringBuilder();
+        boolean inQuote = false;
+        for (int i = 0; i < searchTerm.length(); i++) {
+            char c = searchTerm.charAt(i);
+            if (Character.isLowerCase(c)) {
+                if (inQuote) {
+                    sb.append("\\E");
+                    inQuote = false;
+                }
+                sb.append("[").append(Character.toLowerCase(c)).append(Character.toUpperCase(c)).append("]");
+            } else {
+                if (!inQuote) {
+                    sb.append("\\Q");
+                    inQuote = true;
+                }
+                sb.append(c);
+            }
+        }
+        if (inQuote) {
+            sb.append("\\E");
+        }
+        return sb.toString();
+    }
+
+    private void pushBackBinding() {
+        pushBackBinding(false);
+    }
+
+    private void pushBackBinding(boolean skip) {
+        String s = getLastBinding();
+        if (s != null) {
+            bindingReader.runMacro(s);
+            skipRedisplay = skip;
+        }
+    }
+
+    protected boolean historySearchForward() {
+        if (historyBuffer == null || buf.length() == 0
+                || !buf.toString().equals(history.current())) {
+            historyBuffer = buf.copy();
+            searchBuffer = getFirstWord();
+        }
+        int index = history.index() + 1;
+
+        if (index < history.last() + 1) {
+            int searchIndex = searchForwards(searchBuffer.toString(), index, true);
+            if (searchIndex == -1) {
+                history.moveToEnd();
+                if (!buf.toString().equals(historyBuffer.toString())) {
+                    setBuffer(historyBuffer.toString());
+                    historyBuffer = null;
+                } else {
+                    return false;
+                }
+            } else {
+                // Maintain cursor position while searching.
+                if (history.moveTo(searchIndex)) {
+                    setBuffer(history.current());
+                } else {
+                    history.moveToEnd();
+                    setBuffer(historyBuffer.toString());
+                    return false;
+                }
+            }
+        } else {
+            history.moveToEnd();
+            if (!buf.toString().equals(historyBuffer.toString())) {
+                setBuffer(historyBuffer.toString());
+                historyBuffer = null;
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private CharSequence getFirstWord() {
+        String s = buf.toString();
+        int i = 0;
+        while (i < s.length() && !Character.isWhitespace(s.charAt(i))) {
+            i++;
+        }
+        return s.substring(0, i);
+    }
+
+    protected boolean historySearchBackward() {
+        if (historyBuffer == null || buf.length() == 0
+                || !buf.toString().equals(history.current())) {
+            historyBuffer = buf.copy();
+            searchBuffer = getFirstWord();
+        }
+        int searchIndex = searchBackwards(searchBuffer.toString(), history.index(), true);
+
+        if (searchIndex == -1) {
+            return false;
+        } else {
+            // Maintain cursor position while searching.
+            if (history.moveTo(searchIndex)) {
+                setBuffer(history.current());
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    //
+    // History search
+    //
+    /**
+     * Search backward in history from a given position.
+     *
+     * @param searchTerm substring to search for.
+     * @param startIndex the index from which on to search
+     * @return index where this substring has been found, or -1 else.
+     */
+    public int searchBackwards(String searchTerm, int startIndex) {
+        return searchBackwards(searchTerm, startIndex, false);
+    }
+
+    /**
+     * Search backwards in history from the current position.
+     *
+     * @param searchTerm substring to search for.
+     * @return index where the substring has been found, or -1 else.
+     */
+    public int searchBackwards(String searchTerm) {
+        return searchBackwards(searchTerm, history.index(), false);
+    }
+
+    public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) {
+        boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH);
+        if (caseInsensitive) {
+            searchTerm = searchTerm.toLowerCase();
+        }
+        ListIterator<History.Entry> it = history.iterator(startIndex);
+        while (it.hasPrevious()) {
+            History.Entry e = it.previous();
+            String line = e.line();
+            if (caseInsensitive) {
+                line = line.toLowerCase();
+            }
+            int idx = line.indexOf(searchTerm);
+            if ((startsWith && idx == 0) || (!startsWith && idx >= 0)) {
+                return e.index();
+            }
+        }
+        return -1;
+    }
+
+    public int searchForwards(String searchTerm, int startIndex, boolean startsWith) {
+        boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH);
+        if (caseInsensitive) {
+            searchTerm = searchTerm.toLowerCase();
+        }
+        if (startIndex > history.last()) {
+            startIndex = history.last();
+        }
+        ListIterator<History.Entry> it = history.iterator(startIndex);
+        if (searchIndex != -1 && it.hasNext()) {
+            it.next();
+        }
+        while (it.hasNext()) {
+            History.Entry e = it.next();
+            String line = e.line();
+            if (caseInsensitive) {
+                line = line.toLowerCase();
+            }
+            int idx = line.indexOf(searchTerm);
+            if ((startsWith && idx == 0) || (!startsWith && idx >= 0)) {
+                return e.index();
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Search forward in history from a given position.
+     *
+     * @param searchTerm substring to search for.
+     * @param startIndex the index from which on to search
+     * @return index where this substring has been found, or -1 else.
+     */
+    public int searchForwards(String searchTerm, int startIndex) {
+        return searchForwards(searchTerm, startIndex, false);
+    }
+    /**
+     * Search forwards in history from the current position.
+     *
+     * @param searchTerm substring to search for.
+     * @return index where the substring has been found, or -1 else.
+     */
+    public int searchForwards(String searchTerm) {
+        return searchForwards(searchTerm, history.index());
+    }
+
+    protected boolean quit() {
+        getBuffer().clear();
+        return acceptLine();
+    }
+
+    protected boolean acceptLine() {
+        parsedLine = null;
+        if (!isSet(Option.DISABLE_EVENT_EXPANSION)) {
+            try {
+                String str = buf.toString();
+                String exp = expander.expandHistory(history, str);
+                if (!exp.equals(str)) {
+                    buf.clear();
+                    buf.write(exp);
+                    if (isSet(Option.HISTORY_VERIFY)) {
+                        return true;
+                    }
+                }
+            } catch (IllegalArgumentException e) {
+                // Ignore
+            }
+        }
+        try {
+            parsedLine = parser.parse(buf.toString(), buf.cursor(), ParseContext.ACCEPT_LINE);
+        } catch (EOFError e) {
+            buf.write("\n");
+            return true;
+        } catch (SyntaxError e) {
+            // do nothing
+        }
+        callWidget(CALLBACK_FINISH);
+        state = State.DONE;
+        return true;
+    }
+
+    protected boolean selfInsert() {
+        for (int count = this.count; count > 0; count--) {
+            putString(getLastBinding());
+        }
+        return true;
+    }
+
+    protected boolean selfInsertUnmeta() {
+        if (getLastBinding().charAt(0) == '\u001b') {
+            String s = getLastBinding().substring(1);
+            if ("\r".equals(s)) {
+                s = "\n";
+            }
+            for (int count = this.count; count > 0; count--) {
+                putString(s);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean overwriteMode() {
+        overTyping = !overTyping;
+        return true;
+    }
+
+
+    //
+    // History Control
+    //
+
+    protected boolean beginningOfBufferOrHistory() {
+        if (findbol() != 0) {
+            buf.cursor(0);
+            return true;
+        } else {
+            return beginningOfHistory();
+        }
+    }
+
+    protected boolean beginningOfHistory() {
+        if (history.moveToFirst()) {
+            setBuffer(history.current());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean endOfBufferOrHistory() {
+        if (findeol() != buf.length()) {
+            buf.cursor(buf.length());
+            return true;
+        } else {
+            return endOfHistory();
+        }
+    }
+
+    protected boolean endOfHistory() {
+        if (history.moveToLast()) {
+            setBuffer(history.current());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean beginningOfLineHist() {
+        if (count < 0) {
+            return callNeg(this::endOfLineHist);
+        }
+        while (count-- > 0) {
+            int bol = findbol();
+            if (bol != buf.cursor()) {
+                buf.cursor(bol);
+            } else {
+                moveHistory(false);
+                buf.cursor(0);
+            }
+        }
+        return true;
+    }
+
+    protected boolean endOfLineHist() {
+        if (count < 0) {
+            return callNeg(this::beginningOfLineHist);
+        }
+        while (count-- > 0) {
+            int eol = findeol();
+            if (eol != buf.cursor()) {
+                buf.cursor(eol);
+            } else {
+                moveHistory(true);
+            }
+        }
+        return true;
+    }
+
+    protected boolean upHistory() {
+        while (count-- > 0) {
+            if (!moveHistory(false)) {
+                return !isSet(Option.HISTORY_BEEP);
+            }
+        }
+        return true;
+    }
+
+    protected boolean downHistory() {
+        while (count-- > 0) {
+            if (!moveHistory(true)) {
+                return !isSet(Option.HISTORY_BEEP);
+            }
+        }
+        return true;
+    }
+
+    protected boolean viUpLineOrHistory() {
+        return upLine()
+                || upHistory() && viFirstNonBlank();
+    }
+
+    protected boolean viDownLineOrHistory() {
+        return downLine()
+                || downHistory() && viFirstNonBlank();
+    }
+
+    protected boolean upLine() {
+        return buf.up();
+    }
+
+    protected boolean downLine() {
+        return buf.down();
+    }
+
+    protected boolean upLineOrHistory() {
+        return upLine() || upHistory();
+    }
+
+    protected boolean upLineOrSearch() {
+        return upLine() || historySearchBackward();
+    }
+
+    protected boolean downLineOrHistory() {
+        return downLine() || downHistory();
+    }
+
+    protected boolean downLineOrSearch() {
+        return downLine() || historySearchForward();
+    }
+
+    protected boolean viCmdMode() {
+        // If we are re-entering move mode from an
+        // aborted yank-to, delete-to, change-to then
+        // don't move the cursor back. The cursor is
+        // only move on an explicit entry to movement
+        // mode.
+        if (state == State.NORMAL) {
+            buf.move(-1);
+        }
+        return setKeyMap(VICMD);
+    }
+
+    protected boolean viInsert() {
+        return setKeyMap(VIINS);
+    }
+
+    protected boolean viAddNext() {
+        buf.move(1);
+        return setKeyMap(VIINS);
+    }
+
+    protected boolean viAddEol() {
+        return endOfLine() && setKeyMap(VIINS);
+    }
+
+    protected boolean emacsEditingMode() {
+        return setKeyMap(EMACS);
+    }
+
+    protected boolean viChangeWholeLine() {
+        return viFirstNonBlank() && viChangeEol();
+    }
+
+    protected boolean viChangeEol() {
+        return viChange(buf.cursor(), buf.length())
+                && setKeyMap(VIINS);
+    }
+
+    protected boolean viKillEol() {
+        int eol = findeol();
+        if (buf.cursor() == eol) {
+            return false;
+        }
+        killRing.add(buf.substring(buf.cursor(), eol));
+        buf.delete(eol - buf.cursor());
+        return true;
+    }
+
+    protected boolean quotedInsert() {
+        int c = readCharacter();
+        while (count-- > 0) {
+            putString(new String(Character.toChars(c)));
+        }
+        return true;
+    }
+
+    protected boolean viJoin() {
+        if (buf.down()) {
+            while (buf.move(-1) == -1 && buf.prevChar() != '\n') ;
+            buf.backspace();
+            buf.write(' ');
+            buf.move(-1);
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean viKillWholeLine() {
+        return killWholeLine() && setKeyMap(VIINS);
+    }
+
+    protected boolean viInsertBol() {
+        return beginningOfLine() && setKeyMap(VIINS);
+    }
+
+    protected boolean backwardDeleteChar() {
+        if (count < 0) {
+            return callNeg(this::deleteChar);
+        }
+        if (buf.cursor() == 0) {
+            return false;
+        }
+        buf.backspace(count);
+        return true;
+    }
+
+    protected boolean viFirstNonBlank() {
+        beginningOfLine();
+        while (buf.cursor() < buf.length() && isWhitespace(buf.currChar())) {
+            buf.move(1);
+        }
+        return true;
+    }
+
+    protected boolean viBeginningOfLine() {
+        buf.cursor(findbol());
+        return true;
+    }
+
+    protected boolean viEndOfLine() {
+        if (count < 0) {
+            return false;
+        }
+        while (count-- > 0) {
+            buf.cursor(findeol() + 1);
+        }
+        buf.move(-1);
+        return true;
+    }
+
+    protected boolean beginningOfLine() {
+        while (count-- > 0) {
+            while (buf.move(-1) == -1 && buf.prevChar() != '\n') ;
+        }
+        return true;
+    }
+
+    protected boolean endOfLine() {
+        while (count-- > 0) {
+            while (buf.move(1) == 1 && buf.currChar() != '\n') ;
+        }
+        return true;
+    }
+
+    protected boolean deleteChar() {
+        if (count < 0) {
+            return callNeg(this::backwardDeleteChar);
+        }
+        if (buf.cursor() == buf.length()) {
+            return false;
+        }
+        buf.delete(count);
+        return true;
+    }
+
+    /**
+     * Deletes the previous character from the cursor position
+     * @return <code>true</code> if it succeeded, <code>false</code> otherwise
+     */
+    protected boolean viBackwardDeleteChar() {
+        for (int i = 0; i < count; i++) {
+            if (!buf.backspace()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Deletes the character you are sitting on and sucks the rest of
+     * the line in from the right.
+     * @return <code>true</code> if it succeeded, <code>false</code> otherwise
+     */
+    protected boolean viDeleteChar() {
+        for (int i = 0; i < count; i++) {
+            if (!buf.delete()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Switches the case of the current character from upper to lower
+     * or lower to upper as necessary and advances the cursor one
+     * position to the right.
+     * @return <code>true</code> if it succeeded, <code>false</code> otherwise
+     */
+    protected boolean viSwapCase() {
+        for (int i = 0; i < count; i++) {
+            if (buf.cursor() < buf.length()) {
+                int ch = buf.atChar(buf.cursor());
+                ch = switchCase(ch);
+                buf.currChar(ch);
+                buf.move(1);
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Implements the vi change character command (in move-mode "r"
+     * followed by the character to change to).
+     * @return <code>true</code> if it succeeded, <code>false</code> otherwise
+     */
+    protected boolean viReplaceChars() {
+        int c = readCharacter();
+        // EOF, ESC, or CTRL-C aborts.
+        if (c < 0 || c == '\033' || c == '\003') {
+            return true;
+        }
+
+        for (int i = 0; i < count; i++) {
+            if (buf.currChar((char) c)) {
+                if (i < count - 1) {
+                    buf.move(1);
+                }
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected boolean viChange(int startPos, int endPos) {
+        return doViDeleteOrChange(startPos, endPos, true);
+    }
+
+    protected boolean viDeleteTo(int startPos, int endPos) {
+        return doViDeleteOrChange(startPos, endPos, false);
+    }
+
+    /**
+     * Performs the vi "delete-to" action, deleting characters between a given
+     * span of the input line.
+     * @param startPos The start position
+     * @param endPos The end position.
+     * @param isChange If true, then the delete is part of a change operationg
+     *    (e.g. "c$" is change-to-end-of line, so we first must delete to end
+     *    of line to start the change
+     * @return <code>true</code> if it succeeded, <code>false</code> otherwise
+     */
+    protected boolean doViDeleteOrChange(int startPos, int endPos, boolean isChange) {
+        if (startPos == endPos) {
+            return true;
+        }
+
+        if (endPos < startPos) {
+            int tmp = endPos;
+            endPos = startPos;
+            startPos = tmp;
+        }
+
+        buf.cursor(startPos);
+        buf.delete(endPos - startPos);
+
+        // If we are doing a delete operation (e.g. "d$") then don't leave the
+        // cursor dangling off the end. In reality the "isChange" flag is silly
+        // what is really happening is that if we are in "move-mode" then the
+        // cursor can't be moved off the end of the line, but in "edit-mode" it
+        // is ok, but I have no easy way of knowing which mode we are in.
+        if (! isChange && startPos > 0 && startPos == buf.length()) {
+            buf.move(-1);
+        }
+        return true;
+    }
+
+    /**
+     * Implement the "vi" yank-to operation.  This operation allows you
+     * to yank the contents of the current line based upon a move operation,
+     * for example "yw" yanks the current word, "3yw" yanks 3 words, etc.
+     *
+     * @param startPos The starting position from which to yank
+     * @param endPos The ending position to which to yank
+     * @return <code>true</code> if the yank succeeded
+     */
+    protected boolean viYankTo(int startPos, int endPos) {
+        int cursorPos = startPos;
+
+        if (endPos < startPos) {
+            int tmp = endPos;
+            endPos = startPos;
+            startPos = tmp;
+        }
+
+        if (startPos == endPos) {
+            yankBuffer = "";
+            return true;
+        }
+
+        yankBuffer = buf.substring(startPos, endPos);
+
+        /*
+         * It was a movement command that moved the cursor to find the
+         * end position, so put the cursor back where it started.
+         */
+        buf.cursor(cursorPos);
+        return true;
+    }
+
+    protected boolean viOpenLineAbove() {
+        while (buf.move(-1) == -1 && buf.prevChar() != '\n') ;
+        buf.write('\n');
+        buf.move(-1);
+        return setKeyMap(VIINS);
+    }
+
+    protected boolean viOpenLineBelow() {
+        while (buf.move(1) == 1 && buf.currChar() != '\n') ;
+        buf.write('\n');
+        return setKeyMap(VIINS);
+    }
+
+    /**
+     * Pasts the yank buffer to the right of the current cursor position
+     * and moves the cursor to the end of the pasted region.
+     * @return <code>true</code>
+     */
+    protected boolean viPutAfter() {
+        if (yankBuffer.indexOf('\n') >= 0) {
+            while (buf.move(1) == 1 && buf.currChar() != '\n');
+            buf.move(1);
+            putString(yankBuffer);
+            buf.move(- yankBuffer.length());
+        } else if (yankBuffer.length () != 0) {
+            if (buf.cursor() < buf.length()) {
+                buf.move(1);
+            }
+            for (int i = 0; i < count; i++) {
+                putString(yankBuffer);
+            }
+            buf.move(-1);
+        }
+        return true;
+    }
+
+    protected boolean viPutBefore() {
+        if (yankBuffer.indexOf('\n') >= 0) {
+            while (buf.move(-1) == -1 && buf.prevChar() != '\n');
+            putString(yankBuffer);
+            buf.move(- yankBuffer.length());
+        } else if (yankBuffer.length () != 0) {
+            if (buf.cursor() > 0) {
+                buf.move(-1);
+            }
+            for (int i = 0; i < count; i++) {
+                putString(yankBuffer);
+            }
+            buf.move(-1);
+        }
+        return true;
+    }
+
+    protected boolean doLowercaseVersion() {
+        bindingReader.runMacro(getLastBinding().toLowerCase());
+        return true;
+    }
+
+    protected boolean setMarkCommand() {
+        if (count < 0) {
+            regionActive = RegionType.NONE;
+            return true;
+        }
+        regionMark = buf.cursor();
+        regionActive = RegionType.CHAR;
+        return true;
+    }
+
+    protected boolean exchangePointAndMark() {
+        if (count == 0) {
+            regionActive = RegionType.CHAR;
+            return true;
+        }
+        int x = regionMark;
+        regionMark = buf.cursor();
+        buf.cursor(x);
+        if (buf.cursor() > buf.length()) {
+            buf.cursor(buf.length());
+        }
+        if (count > 0) {
+            regionActive = RegionType.CHAR;
+        }
+        return true;
+    }
+
+    protected boolean visualMode() {
+        if (isInViMoveOperation()) {
+            isArgDigit = true;
+            forceLine = false;
+            forceChar = true;
+            return true;
+        }
+        if (regionActive == RegionType.NONE) {
+            regionMark = buf.cursor();
+            regionActive = RegionType.CHAR;
+        } else if (regionActive == RegionType.CHAR) {
+            regionActive = RegionType.NONE;
+        } else if (regionActive == RegionType.LINE) {
+            regionActive = RegionType.CHAR;
+        }
+        return true;
+    }
+
+    protected boolean visualLineMode() {
+        if (isInViMoveOperation()) {
+            isArgDigit = true;
+            forceLine = true;
+            forceChar = false;
+            return true;
+        }
+        if (regionActive == RegionType.NONE) {
+            regionMark = buf.cursor();
+            regionActive = RegionType.LINE;
+        } else if (regionActive == RegionType.CHAR) {
+            regionActive = RegionType.LINE;
+        } else if (regionActive == RegionType.LINE) {
+            regionActive = RegionType.NONE;
+        }
+        return true;
+    }
+
+    protected boolean deactivateRegion() {
+        regionActive = RegionType.NONE;
+        return true;
+    }
+
+    protected boolean whatCursorPosition() {
+        post = () -> {
+            AttributedStringBuilder sb = new AttributedStringBuilder();
+            if (buf.cursor() < buf.length()) {
+                int c = buf.currChar();
+                sb.append("Char: ");
+                if (c == ' ') {
+                    sb.append("SPC");
+                } else if (c == '\n') {
+                    sb.append("LFD");
+                } else if (c < 32) {
+                    sb.append('^');
+                    sb.append((char) (c + 'A' - 1));
+                } else if (c == 127) {
+                    sb.append("^?");
+                } else {
+                    sb.append((char) c);
+                }
+                sb.append(" (");
+                sb.append("0").append(Integer.toOctalString(c)).append(" ");
+                sb.append(Integer.toString(c)).append(" ");
+                sb.append("0x").append(Integer.toHexString(c)).append(" ");
+                sb.append(")");
+            } else {
+                sb.append("EOF");
+            }
+            sb.append("   ");
+            sb.append("point ");
+            sb.append(Integer.toString(buf.cursor() + 1));
+            sb.append(" of ");
+            sb.append(Integer.toString(buf.length() + 1));
+            sb.append(" (");
+            sb.append(Integer.toString(buf.length() == 0 ? 100 : ((100 * buf.cursor()) / buf.length())));
+            sb.append("%)");
+            sb.append("   ");
+            sb.append("column ");
+            sb.append(Integer.toString(buf.cursor() - findbol()));
+            return sb.toAttributedString();
+        };
+        return true;
+    }
+
+    protected Map<String, Widget> builtinWidgets() {
+        Map<String, Widget> widgets = new HashMap<>();
+        widgets.put(ACCEPT_LINE, this::acceptLine);
+        widgets.put(ARGUMENT_BASE, this::argumentBase);
+        widgets.put(BACKWARD_CHAR, this::backwardChar);
+        widgets.put(BACKWARD_DELETE_CHAR, this::backwardDeleteChar);
+        widgets.put(BACKWARD_DELETE_WORD, this::backwardDeleteWord);
+        widgets.put(BACKWARD_KILL_LINE, this::backwardKillLine);
+        widgets.put(BACKWARD_KILL_WORD, this::backwardKillWord);
+        widgets.put(BACKWARD_WORD, this::backwardWord);
+        widgets.put(BEEP, this::beep);
+        widgets.put(BEGINNING_OF_BUFFER_OR_HISTORY, this::beginningOfBufferOrHistory);
+        widgets.put(BEGINNING_OF_HISTORY, this::beginningOfHistory);
+        widgets.put(BEGINNING_OF_LINE, this::beginningOfLine);
+        widgets.put(BEGINNING_OF_LINE_HIST, this::beginningOfLineHist);
+        widgets.put(CAPITALIZE_WORD, this::capitalizeWord);
+        widgets.put(CLEAR, this::clear);
+        widgets.put(CLEAR_SCREEN, this::clearScreen);
+        widgets.put(COMPLETE_PREFIX, this::completePrefix);
+        widgets.put(COMPLETE_WORD, this::completeWord);
+        widgets.put(COPY_PREV_WORD, this::copyPrevWord);
+        widgets.put(COPY_REGION_AS_KILL, this::copyRegionAsKill);
+        widgets.put(DELETE_CHAR, this::deleteChar);
+        widgets.put(DELETE_CHAR_OR_LIST, this::deleteCharOrList);
+        widgets.put(DELETE_WORD, this::deleteWord);
+        widgets.put(DIGIT_ARGUMENT, this::digitArgument);
+        widgets.put(DO_LOWERCASE_VERSION, this::doLowercaseVersion);
+        widgets.put(DOWN_CASE_WORD, this::downCaseWord);
+        widgets.put(DOWN_LINE, this::downLine);
+        widgets.put(DOWN_LINE_OR_HISTORY, this::downLineOrHistory);
+        widgets.put(DOWN_LINE_OR_SEARCH, this::downLineOrSearch);
+        widgets.put(DOWN_HISTORY, this::downHistory);
+        widgets.put(EMACS_EDITING_MODE, this::emacsEditingMode);
+        widgets.put(EMACS_BACKWARD_WORD, this::emacsBackwardWord);
+        widgets.put(EMACS_FORWARD_WORD, this::emacsForwardWord);
+        widgets.put(END_OF_BUFFER_OR_HISTORY, this::endOfBufferOrHistory);
+        widgets.put(END_OF_HISTORY, this::endOfHistory);
+        widgets.put(END_OF_LINE, this::endOfLine);
+        widgets.put(END_OF_LINE_HIST, this::endOfLineHist);
+        widgets.put(EXCHANGE_POINT_AND_MARK, this::exchangePointAndMark);
+        widgets.put(EXPAND_HISTORY, this::expandHistory);
+        widgets.put(EXPAND_OR_COMPLETE, this::expandOrComplete);
+        widgets.put(EXPAND_OR_COMPLETE_PREFIX, this::expandOrCompletePrefix);
+        widgets.put(EXPAND_WORD, this::expandWord);
+        widgets.put(FRESH_LINE, this::freshLine);
+        widgets.put(FORWARD_CHAR, this::forwardChar);
+        widgets.put(FORWARD_WORD, this::forwardWord);
+        widgets.put(HISTORY_INCREMENTAL_SEARCH_BACKWARD, this::historyIncrementalSearchBackward);
+        widgets.put(HISTORY_INCREMENTAL_SEARCH_FORWARD, this::historyIncrementalSearchForward);
+        widgets.put(HISTORY_SEARCH_BACKWARD, this::historySearchBackward);
+        widgets.put(HISTORY_SEARCH_FORWARD, this::historySearchForward);
+        widgets.put(INSERT_CLOSE_CURLY, this::insertCloseCurly);
+        widgets.put(INSERT_CLOSE_PAREN, this::insertCloseParen);
+        widgets.put(INSERT_CLOSE_SQUARE, this::insertCloseSquare);
+        widgets.put(INSERT_COMMENT, this::insertComment);
+        widgets.put(KILL_BUFFER, this::killBuffer);
+        widgets.put(KILL_LINE, this::killLine);
+        widgets.put(KILL_REGION, this::killRegion);
+        widgets.put(KILL_WHOLE_LINE, this::killWholeLine);
+        widgets.put(KILL_WORD, this::killWord);
+        widgets.put(LIST_CHOICES, this::listChoices);
+        widgets.put(MENU_COMPLETE, this::menuComplete);
+        widgets.put(MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete);
+        widgets.put(NEG_ARGUMENT, this::negArgument);
+        widgets.put(OVERWRITE_MODE, this::overwriteMode);
+//        widgets.put(QUIT, this::quit);
+        widgets.put(QUOTED_INSERT, this::quotedInsert);
+        widgets.put(REDISPLAY, this::redisplay);
+        widgets.put(REDRAW_LINE, this::redrawLine);
+        widgets.put(REDO, this::redo);
+        widgets.put(SELF_INSERT, this::selfInsert);
+        widgets.put(SELF_INSERT_UNMETA, this::selfInsertUnmeta);
+        widgets.put(SEND_BREAK, this::sendBreak);
+        widgets.put(SET_MARK_COMMAND, this::setMarkCommand);
+        widgets.put(TRANSPOSE_CHARS, this::transposeChars);
+        widgets.put(TRANSPOSE_WORDS, this::transposeWords);
+        widgets.put(UNDEFINED_KEY, this::undefinedKey);
+        widgets.put(UNIVERSAL_ARGUMENT, this::universalArgument);
+        widgets.put(UNDO, this::undo);
+        widgets.put(UP_CASE_WORD, this::upCaseWord);
+        widgets.put(UP_HISTORY, this::upHistory);
+        widgets.put(UP_LINE, this::upLine);
+        widgets.put(UP_LINE_OR_HISTORY, this::upLineOrHistory);
+        widgets.put(UP_LINE_OR_SEARCH, this::upLineOrSearch);
+        widgets.put(VI_ADD_EOL, this::viAddEol);
+        widgets.put(VI_ADD_NEXT, this::viAddNext);
+        widgets.put(VI_BACKWARD_CHAR, this::viBackwardChar);
+        widgets.put(VI_BACKWARD_DELETE_CHAR, this::viBackwardDeleteChar);
+        widgets.put(VI_BACKWARD_BLANK_WORD, this::viBackwardBlankWord);
+        widgets.put(VI_BACKWARD_BLANK_WORD_END, this::viBackwardBlankWordEnd);
+        widgets.put(VI_BACKWARD_KILL_WORD, this::viBackwardKillWord);
+        widgets.put(VI_BACKWARD_WORD, this::viBackwardWord);
+        widgets.put(VI_BACKWARD_WORD_END, this::viBackwardWordEnd);
+        widgets.put(VI_BEGINNING_OF_LINE, this::viBeginningOfLine);
+        widgets.put(VI_CMD_MODE, this::viCmdMode);
+        widgets.put(VI_DIGIT_OR_BEGINNING_OF_LINE, this::viDigitOrBeginningOfLine);
+        widgets.put(VI_DOWN_LINE_OR_HISTORY, this::viDownLineOrHistory);
+        widgets.put(VI_CHANGE, this::viChange);
+        widgets.put(VI_CHANGE_EOL, this::viChangeEol);
+        widgets.put(VI_CHANGE_WHOLE_LINE, this::viChangeWholeLine);
+        widgets.put(VI_DELETE_CHAR, this::viDeleteChar);
+        widgets.put(VI_DELETE, this::viDelete);
+        widgets.put(VI_END_OF_LINE, this::viEndOfLine);
+        widgets.put(VI_KILL_EOL, this::viKillEol);
+        widgets.put(VI_FIRST_NON_BLANK, this::viFirstNonBlank);
+        widgets.put(VI_FIND_NEXT_CHAR, this::viFindNextChar);
+        widgets.put(VI_FIND_NEXT_CHAR_SKIP, this::viFindNextCharSkip);
+        widgets.put(VI_FIND_PREV_CHAR, this::viFindPrevChar);
+        widgets.put(VI_FIND_PREV_CHAR_SKIP, this::viFindPrevCharSkip);
+        widgets.put(VI_FORWARD_BLANK_WORD, this::viForwardBlankWord);
+        widgets.put(VI_FORWARD_BLANK_WORD_END, this::viForwardBlankWordEnd);
+        widgets.put(VI_FORWARD_CHAR, this::viForwardChar);
+        widgets.put(VI_FORWARD_WORD, this::viForwardWord);
+        widgets.put(VI_FORWARD_WORD, this::viForwardWord);
+        widgets.put(VI_FORWARD_WORD_END, this::viForwardWordEnd);
+        widgets.put(VI_HISTORY_SEARCH_BACKWARD, this::viHistorySearchBackward);
+        widgets.put(VI_HISTORY_SEARCH_FORWARD, this::viHistorySearchForward);
+        widgets.put(VI_INSERT, this::viInsert);
+        widgets.put(VI_INSERT_BOL, this::viInsertBol);
+        widgets.put(VI_INSERT_COMMENT, this::viInsertComment);
+        widgets.put(VI_JOIN, this::viJoin);
+        widgets.put(VI_KILL_LINE, this::viKillWholeLine);
+        widgets.put(VI_MATCH_BRACKET, this::viMatchBracket);
+        widgets.put(VI_OPEN_LINE_ABOVE, this::viOpenLineAbove);
+        widgets.put(VI_OPEN_LINE_BELOW, this::viOpenLineBelow);
+        widgets.put(VI_PUT_AFTER, this::viPutAfter);
+        widgets.put(VI_PUT_BEFORE, this::viPutBefore);
+        widgets.put(VI_REPEAT_FIND, this::viRepeatFind);
+        widgets.put(VI_REPEAT_SEARCH, this::viRepeatSearch);
+        widgets.put(VI_REPLACE_CHARS, this::viReplaceChars);
+        widgets.put(VI_REV_REPEAT_FIND, this::viRevRepeatFind);
+        widgets.put(VI_REV_REPEAT_SEARCH, this::viRevRepeatSearch);
+        widgets.put(VI_SWAP_CASE, this::viSwapCase);
+        widgets.put(VI_UP_LINE_OR_HISTORY, this::viUpLineOrHistory);
+        widgets.put(VI_YANK, this::viYankTo);
+        widgets.put(VI_YANK_WHOLE_LINE, this::viYankWholeLine);
+        widgets.put(VISUAL_LINE_MODE, this::visualLineMode);
+        widgets.put(VISUAL_MODE, this::visualMode);
+        widgets.put(WHAT_CURSOR_POSITION, this::whatCursorPosition);
+        widgets.put(YANK, this::yank);
+        widgets.put(YANK_POP, this::yankPop);
+        widgets.put(MOUSE, this::mouse);
+        widgets.put(BEGIN_PASTE, this::beginPaste);
+        widgets.put(FOCUS_IN, this::focusIn);
+        widgets.put(FOCUS_OUT, this::focusOut);
+        return widgets;
+    }
+
+    public boolean redisplay() {
+        redisplay(true);
+        return true;
+    }
+
+    protected synchronized void redisplay(boolean flush) {
+        if (skipRedisplay) {
+            skipRedisplay = false;
+            return;
+        }
+
+        Status status = Status.getStatus(terminal, false);
+        if (status != null) {
+            status.redraw();
+        }
+
+        if (size.getRows() > 0 && size.getRows() < MIN_ROWS) {
+            AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
+
+            sb.append(prompt);
+            concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb);
+            AttributedString full = sb.toAttributedString();
+
+            sb.setLength(0);
+            sb.append(prompt);
+            String line = buf.upToCursor();
+            if(maskingCallback != null) {
+                line = maskingCallback.display(line);
+            }
+
+            concat(new AttributedString(line).columnSplitLength(Integer.MAX_VALUE), sb);
+            AttributedString toCursor = sb.toAttributedString();
+
+            int w = WCWidth.wcwidth('\u2026');
+            int width = size.getColumns();
+            int cursor = toCursor.columnLength();
+            int inc = width /2 + 1;
+            while (cursor <= smallTerminalOffset + w) {
+                smallTerminalOffset -= inc;
+            }
+            while (cursor >= smallTerminalOffset + width - w) {
+                smallTerminalOffset += inc;
+            }
+            if (smallTerminalOffset > 0) {
+                sb.setLength(0);
+                sb.append("\u2026");
+                sb.append(full.columnSubSequence(smallTerminalOffset + w, Integer.MAX_VALUE));
+                full = sb.toAttributedString();
+            }
+            int length = full.columnLength();
+            if (length >= smallTerminalOffset + width) {
+                sb.setLength(0);
+                sb.append(full.columnSubSequence(0, width - w));
+                sb.append("\u2026");
+                full = sb.toAttributedString();
+            }
+
+            display.update(Collections.singletonList(full), cursor - smallTerminalOffset, flush);
+            return;
+        }
+
+        List<AttributedString> secondaryPrompts = new ArrayList<>();
+        AttributedString full = getDisplayedBufferWithPrompts(secondaryPrompts);
+
+        List<AttributedString> newLines;
+        if (size.getColumns() <= 0) {
+            newLines = new ArrayList<>();
+            newLines.add(full);
+        } else {
+            newLines = full.columnSplitLength(size.getColumns(), true, display.delayLineWrap());
+        }
+
+        List<AttributedString> rightPromptLines;
+        if (rightPrompt.length() == 0 || size.getColumns() <= 0) {
+            rightPromptLines = new ArrayList<>();
+        } else {
+            rightPromptLines = rightPrompt.columnSplitLength(size.getColumns());
+        }
+        while (newLines.size() < rightPromptLines.size()) {
+            newLines.add(new AttributedString(""));
+        }
+        for (int i = 0; i < rightPromptLines.size(); i++) {
+            AttributedString line = rightPromptLines.get(i);
+            newLines.set(i, addRightPrompt(line, newLines.get(i)));
+        }
+
+        int cursorPos = -1;
+        if (size.getColumns() > 0) {
+            AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
+            sb.append(prompt);
+            String buffer = buf.upToCursor();
+            if (maskingCallback != null) {
+                buffer = maskingCallback.display(buffer);
+            }
+            sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false));
+            List<AttributedString> promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap());
+            if (!promptLines.isEmpty()) {
+                cursorPos = size.cursorPos(promptLines.size() - 1,
+                                           promptLines.get(promptLines.size() - 1).columnLength());
+            }
+        }
+
+        display.update(newLines, cursorPos, flush);
+    }
+
+    private void concat(List<AttributedString> lines, AttributedStringBuilder sb) {
+        if (lines.size() > 1) {
+            for (int i = 0; i < lines.size() - 1; i++) {
+                sb.append(lines.get(i));
+                sb.style(sb.style().inverse());
+                sb.append("\\n");
+                sb.style(sb.style().inverseOff());
+            }
+        }
+        sb.append(lines.get(lines.size() - 1));
+    }
+
+    /**
+     * Compute the full string to be displayed with the left, right and secondary prompts
+     * @param secondaryPrompts a list to store the secondary prompts
+     * @return the displayed string including the buffer, left prompts and the help below
+     */
+    public AttributedString getDisplayedBufferWithPrompts(List<AttributedString> secondaryPrompts) {
+        AttributedString attBuf = getHighlightedBuffer(buf.toString());
+
+        AttributedString tNewBuf = insertSecondaryPrompts(attBuf, secondaryPrompts);
+        AttributedStringBuilder full = new AttributedStringBuilder().tabs(TAB_WIDTH);
+        full.append(prompt);
+        full.append(tNewBuf);
+        if (post != null) {
+            full.append("\n");
+            full.append(post.get());
+        }
+        return full.toAttributedString();
+    }
+
+    private AttributedString getHighlightedBuffer(String buffer) {
+        if (maskingCallback != null) {
+            buffer = maskingCallback.display(buffer);
+        }
+        if (highlighter != null && !isSet(Option.DISABLE_HIGHLIGHTER)) {
+            return highlighter.highlight(this, buffer);
+        }
+        return new AttributedString(buffer);
+    }
+
+    private AttributedString expandPromptPattern(String pattern, int padToWidth,
+                                                 String message, int line) {
+        ArrayList<AttributedString> parts = new ArrayList<>();
+        boolean isHidden = false;
+        int padPartIndex = -1;
+        StringBuilder padPartString = null;
+        StringBuilder sb = new StringBuilder();
+        // Add "%{" to avoid special case for end of string.
+        pattern = pattern + "%{";
+        int plen = pattern.length();
+        int padChar = -1;
+        int padPos = -1;
+        int cols = 0;
+        for (int i = 0; i < plen; ) {
+            char ch = pattern.charAt(i++);
+            if (ch == '%' && i < plen) {
+                int count = 0;
+                boolean countSeen = false;
+                decode: while (true) {
+                    ch = pattern.charAt(i++);
+                    switch (ch) {
+                       case '{':
+                       case '}':
+                           String str = sb.toString();
+                           AttributedString astr;
+                           if (!isHidden) {
+                               astr = AttributedString.fromAnsi(str);
+                               cols += astr.columnLength();
+                           } else {
+                               astr = new AttributedString(str, AttributedStyle.HIDDEN);
+                           }
+                           if (padPartIndex == parts.size()) {
+                               padPartString = sb;
+                               if (i < plen) {
+                                   sb = new StringBuilder();
+                               }
+                           } else {
+                               sb.setLength(0);
+                           }
+                           parts.add(astr);
+                           isHidden = ch == '{';
+                            break decode;
+                        case '%':
+                            sb.append(ch);
+                            break decode;
+                        case 'N':
+                            sb.append(getInt(LINE_OFFSET, 0) + line);
+                            break decode;
+                        case 'M':
+                            if (message != null)
+                                sb.append(message);
+                            break decode;
+                        case 'P':
+                            if (countSeen && count >= 0)
+                                padToWidth = count;
+                            if (i < plen) {
+                                padChar = pattern.charAt(i++);
+                                // FIXME check surrogate
+                            }
+                            padPos = sb.length();
+                            padPartIndex = parts.size();
+                            break decode;
+                        case '-':
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                        case '8':
+                        case '9':
+                            boolean neg = false;
+                            if (ch == '-') {
+                                neg = true;
+                                ch = pattern.charAt(i++);
+                            }
+                            countSeen = true;
+                            count = 0;
+                            while (ch >= '0' && ch <= '9') {
+                                count = (count < 0 ? 0 : 10 * count) + (ch - '0');
+                                ch = pattern.charAt(i++);
+                            }
+                            if (neg) {
+                                count = -count;
+                            }
+                            i--;
+                            break;
+                        default:
+                            break decode;
+                    }
+                }
+            } else
+                sb.append(ch);
+        }
+        if (padToWidth > cols) {
+            int padCharCols = WCWidth.wcwidth(padChar);
+            int padCount = (padToWidth - cols) / padCharCols;
+            sb = padPartString;
+            while (--padCount >= 0)
+                sb.insert(padPos, (char) padChar); // FIXME if wide
+            parts.set(padPartIndex, AttributedString.fromAnsi(sb.toString()));
+        }
+        return AttributedString.join(null, parts);
+    }
+
+    private AttributedString insertSecondaryPrompts(AttributedString str, List<AttributedString> prompts) {
+        return insertSecondaryPrompts(str, prompts, true);
+    }
+
+    private AttributedString insertSecondaryPrompts(AttributedString strAtt, List<AttributedString> prompts, boolean computePrompts) {
+        Objects.requireNonNull(prompts);
+        List<AttributedString> lines = strAtt.columnSplitLength(Integer.MAX_VALUE);
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        String secondaryPromptPattern = getString(SECONDARY_PROMPT_PATTERN, DEFAULT_SECONDARY_PROMPT_PATTERN);
+        boolean needsMessage = secondaryPromptPattern.contains("%M");
+        AttributedStringBuilder buf = new AttributedStringBuilder();
+        int width = 0;
+        List<String> missings = new ArrayList<>();
+        if (computePrompts && secondaryPromptPattern.contains("%P")) {
+            width = prompt.columnLength();
+            for (int line = 0; line < lines.size() - 1; line++) {
+                AttributedString prompt;
+                buf.append(lines.get(line)).append("\n");
+                String missing = "";
+                if (needsMessage) {
+                    try {
+                        parser.parse(buf.toString(), buf.length(), ParseContext.SECONDARY_PROMPT);
+                    } catch (EOFError e) {
+                        missing = e.getMissing();
+                    } catch (SyntaxError e) {
+                        // Ignore
+                    }
+                }
+                missings.add(missing);
+                prompt = expandPromptPattern(secondaryPromptPattern, 0, missing, line + 1);
+                width = Math.max(width, prompt.columnLength());
+            }
+            buf.setLength(0);
+        }
+        int line = 0;
+        while (line < lines.size() - 1) {
+            sb.append(lines.get(line)).append("\n");
+            buf.append(lines.get(line)).append("\n");
+            AttributedString prompt;
+            if (computePrompts) {
+                String missing = "";
+                if (needsMessage) {
+                    if (missings.isEmpty()) {
+                        try {
+                            parser.parse(buf.toString(), buf.length(), ParseContext.SECONDARY_PROMPT);
+                        } catch (EOFError e) {
+                            missing = e.getMissing();
+                        } catch (SyntaxError e) {
+                            // Ignore
+                        }
+                    } else {
+                        missing = missings.get(line);
+                    }
+                }
+                prompt = expandPromptPattern(secondaryPromptPattern, width, missing, line + 1);
+            } else {
+                prompt = prompts.get(line);
+            }
+            prompts.add(prompt);
+            sb.append(prompt);
+            line++;
+        }
+        sb.append(lines.get(line));
+        buf.append(lines.get(line));
+        return sb.toAttributedString();
+    }
+
+    private AttributedString addRightPrompt(AttributedString prompt, AttributedString line) {
+        int width = prompt.columnLength();
+        boolean endsWithNl = line.length() > 0
+            && line.charAt(line.length() - 1) == '\n';
+        // columnLength counts -1 for the final newline; adjust for that
+        int nb = size.getColumns() - width
+            - (line.columnLength() + (endsWithNl ? 1 : 0));
+        if (nb >= 3) {
+            AttributedStringBuilder sb = new AttributedStringBuilder(size.getColumns());
+            sb.append(line, 0, endsWithNl ? line.length() - 1 : line.length());
+            for (int j = 0; j < nb; j++) {
+                sb.append(' ');
+            }
+            sb.append(prompt);
+            if (endsWithNl) {
+                sb.append('\n');
+            }
+            line = sb.toAttributedString();
+        }
+        return line;
+    }
+
+    //
+    // Completion
+    //
+
+    protected boolean insertTab() {
+        return isSet(Option.INSERT_TAB)
+                    && getLastBinding().equals("\t")
+                    && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*");
+    }
+
+    protected boolean expandHistory() {
+        String str = buf.toString();
+        String exp = expander.expandHistory(history, str);
+        if (!exp.equals(str)) {
+            buf.clear();
+            buf.write(exp);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected enum CompletionType {
+        Expand,
+        ExpandComplete,
+        Complete,
+        List,
+    }
+
+    protected boolean expandWord() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.Expand, isSet(Option.MENU_COMPLETE), false);
+        }
+    }
+
+    protected boolean expandOrComplete() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.ExpandComplete, isSet(Option.MENU_COMPLETE), false);
+        }
+    }
+
+    protected boolean expandOrCompletePrefix() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.ExpandComplete, isSet(Option.MENU_COMPLETE), true);
+        }
+    }
+
+    protected boolean completeWord() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.Complete, isSet(Option.MENU_COMPLETE), false);
+        }
+    }
+
+    protected boolean menuComplete() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.Complete, true, false);
+        }
+    }
+
+    protected boolean menuExpandOrComplete() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.ExpandComplete, true, false);
+        }
+    }
+
+    protected boolean completePrefix() {
+        if (insertTab()) {
+            return selfInsert();
+        } else {
+            return doComplete(CompletionType.Complete, isSet(Option.MENU_COMPLETE), true);
+        }
+    }
+
+    protected boolean listChoices() {
+        return doComplete(CompletionType.List, isSet(Option.MENU_COMPLETE), false);
+    }
+
+    protected boolean deleteCharOrList() {
+        if (buf.cursor() != buf.length() || buf.length() == 0) {
+            return deleteChar();
+        } else {
+            return doComplete(CompletionType.List, isSet(Option.MENU_COMPLETE), false);
+        }
+    }
+
+    protected boolean doComplete(CompletionType lst, boolean useMenu, boolean prefix) {
+        // If completion is disabled, just bail out
+        if (getBoolean(DISABLE_COMPLETION, false)) {
+            return true;
+        }
+        // Try to expand history first
+        // If there is actually an expansion, bail out now
+        if (!isSet(Option.DISABLE_EVENT_EXPANSION)) {
+            try {
+                if (expandHistory()) {
+                    return true;
+                }
+            } catch (Exception e) {
+                Log.info("Error while expanding history", e);
+                return false;
+            }
+        }
+
+        // Parse the command line
+        CompletingParsedLine line;
+        try {
+            line = wrap(parser.parse(buf.toString(), buf.cursor(), ParseContext.COMPLETE));
+        } catch (Exception e) {
+            Log.info("Error while parsing line", e);
+            return false;
+        }
+
+        // Find completion candidates
+        List<Candidate> candidates = new ArrayList<>();
+        try {
+            if (completer != null) {
+                completer.complete(this, line, candidates);
+            }
+        } catch (Exception e) {
+            Log.info("Error while finding completion candidates", e);
+            return false;
+        }
+
+        if (lst == CompletionType.ExpandComplete || lst == CompletionType.Expand) {
+            String w = expander.expandVar(line.word());
+            if (!line.word().equals(w)) {
+                if (prefix) {
+                    buf.backspace(line.wordCursor());
+                } else {
+                    buf.move(line.word().length() - line.wordCursor());
+                    buf.backspace(line.word().length());
+                }
+                buf.write(w);
+                return true;
+            }
+            if (lst == CompletionType.Expand) {
+                return false;
+            } else {
+                lst = CompletionType.Complete;
+            }
+        }
+
+        boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE);
+        int errors = getInt(ERRORS, DEFAULT_ERRORS);
+
+        // Build a list of sorted candidates
+        Map<String, List<Candidate>> sortedCandidates = new HashMap<>();
+        for (Candidate cand : candidates) {
+            sortedCandidates
+                    .computeIfAbsent(AttributedString.fromAnsi(cand.value()).toString(), s -> new ArrayList<>())
+                    .add(cand);
+        }
+
+        // Find matchers
+        // TODO: glob completion
+        List<Function<Map<String, List<Candidate>>,
+                      Map<String, List<Candidate>>>> matchers;
+        Predicate<String> exact;
+        if (prefix) {
+            String wd = line.word();
+            String wdi = caseInsensitive ? wd.toLowerCase() : wd;
+            String wp = wdi.substring(0, line.wordCursor());
+            matchers = Arrays.asList(
+                    simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)),
+                    simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)),
+                    typoMatcher(wp, errors, caseInsensitive)
+            );
+            exact = s -> caseInsensitive ? s.equalsIgnoreCase(wp) : s.equals(wp);
+        } else if (isSet(Option.COMPLETE_IN_WORD)) {
+            String wd = line.word();
+            String wdi = caseInsensitive ? wd.toLowerCase() : wd;
+            String wp = wdi.substring(0, line.wordCursor());
+            String ws = wdi.substring(line.wordCursor());
+            Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
+            Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
+            matchers = Arrays.asList(
+                    simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s).matches()),
+                    simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s).matches()),
+                    typoMatcher(wdi, errors, caseInsensitive)
+            );
+            exact = s -> caseInsensitive ? s.equalsIgnoreCase(wd) : s.equals(wd);
+        } else {
+            String wd = line.word();
+            String wdi = caseInsensitive ? wd.toLowerCase() : wd;
+            matchers = Arrays.asList(
+                    simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)),
+                    simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)),
+                    typoMatcher(wdi, errors, caseInsensitive)
+            );
+            exact = s -> caseInsensitive ? s.equalsIgnoreCase(wd) : s.equals(wd);
+        }
+        // Find matching candidates
+        Map<String, List<Candidate>> matching = Collections.emptyMap();
+        for (Function<Map<String, List<Candidate>>,
+                      Map<String, List<Candidate>>> matcher : matchers) {
+            matching = matcher.apply(sortedCandidates);
+            if (!matching.isEmpty()) {
+                break;
+            }
+        }
+
+        // If we have no matches, bail out
+        if (matching.isEmpty()) {
+            return false;
+        }
+
+        // If we only need to display the list, do it now
+        if (lst == CompletionType.List) {
+            List<Candidate> possible = matching.entrySet().stream()
+                    .flatMap(e -> e.getValue().stream())
+                    .collect(Collectors.toList());
+            doList(possible, line.word(), false, line::escape);
+            return !possible.isEmpty();
+        }
+
+        // Check if there's a single possible match
+        Candidate completion = null;
+        // If there's a single possible completion
+        if (matching.size() == 1) {
+            completion = matching.values().stream().flatMap(Collection::stream)
+                    .findFirst().orElse(null);
+        }
+        // Or if RECOGNIZE_EXACT is set, try to find an exact match
+        else if (isSet(Option.RECOGNIZE_EXACT)) {
+            completion = matching.values().stream().flatMap(Collection::stream)
+                    .filter(Candidate::complete)
+                    .filter(c -> exact.test(c.value()))
+                    .findFirst().orElse(null);
+        }
+        // Complete and exit
+        if (completion != null && !completion.value().isEmpty()) {
+            if (prefix) {
+                buf.backspace(line.rawWordCursor());
+            } else {
+                buf.move(line.rawWordLength() - line.rawWordCursor());
+                buf.backspace(line.rawWordLength());
+            }
+            buf.write(line.escape(completion.value(), completion.complete()));
+            if (completion.complete()) {
+                if (buf.currChar() != ' ') {
+                    buf.write(" ");
+                } else {
+                    buf.move(1);
+                }
+            }
+            if (completion.suffix() != null) {
+                redisplay();
+                Binding op = readBinding(getKeys());
+                if (op != null) {
+                    String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS);
+                    String ref = op instanceof Reference ? ((Reference) op).name() : null;
+                    if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0
+                            || ACCEPT_LINE.equals(ref)) {
+                        buf.backspace(completion.suffix().length());
+                        if (getLastBinding().charAt(0) != ' ') {
+                            buf.write(' ');
+                        }
+                    }
+                    pushBackBinding(true);
+                }
+            }
+            return true;
+        }
+
+        List<Candidate> possible = matching.entrySet().stream()
+                .flatMap(e -> e.getValue().stream())
+                .collect(Collectors.toList());
+
+        if (useMenu) {
+            buf.move(line.word().length() - line.wordCursor());
+            buf.backspace(line.word().length());
+            doMenu(possible, line.word(), line::escape);
+            return true;
+        }
+
+        // Find current word and move to end
+        String current;
+        if (prefix) {
+            current = line.word().substring(0, line.wordCursor());
+        } else {
+            current = line.word();
+            buf.move(line.rawWordLength() - line.rawWordCursor());
+        }
+        // Now, we need to find the unambiguous completion
+        // TODO: need to find common suffix
+        String commonPrefix = null;
+        for (String key : matching.keySet()) {
+            commonPrefix = commonPrefix == null ? key : getCommonStart(commonPrefix, key, caseInsensitive);
+        }
+        boolean hasUnambiguous = commonPrefix.startsWith(current) && !commonPrefix.equals(current);
+
+        if (hasUnambiguous) {
+            buf.backspace(line.rawWordLength());
+            buf.write(line.escape(commonPrefix, false));
+            current = commonPrefix;
+            if ((!isSet(Option.AUTO_LIST) && isSet(Option.AUTO_MENU))
+                    || (isSet(Option.AUTO_LIST) && isSet(Option.LIST_AMBIGUOUS))) {
+                if (!nextBindingIsComplete()) {
+                    return true;
+                }
+            }
+        }
+        if (isSet(Option.AUTO_LIST)) {
+            if (!doList(possible, current, true, line::escape)) {
+                return true;
+            }
+        }
+        if (isSet(Option.AUTO_MENU)) {
+            buf.backspace(current.length());
+            doMenu(possible, line.word(), line::escape);
+        }
+        return true;
+    }
+
+    private CompletingParsedLine wrap(ParsedLine line) {
+        if (line instanceof CompletingParsedLine) {
+            return (CompletingParsedLine) line;
+        } else {
+            return new CompletingParsedLine() {
+                public String word() {
+                    return line.word();
+                }
+                public int wordCursor() {
+                    return line.wordCursor();
+                }
+                public int wordIndex() {
+                    return line.wordIndex();
+                }
+                public List<String> words() {
+                    return line.words();
+                }
+                public String line() {
+                    return line.line();
+                }
+                public int cursor() {
+                    return line.cursor();
+                }
+                public CharSequence escape(CharSequence candidate, boolean complete) {
+                    return candidate;
+                }
+                public int rawWordCursor() {
+                    return wordCursor();
+                }
+                public int rawWordLength() {
+                    return word().length();
+                }
+            };
+        }
+    }
+
+    protected Comparator<Candidate> getCandidateComparator(boolean caseInsensitive, String word) {
+        String wdi = caseInsensitive ? word.toLowerCase() : word;
+        ToIntFunction<String> wordDistance = w -> distance(wdi, caseInsensitive ? w.toLowerCase() : w);
+        return Comparator
+                .comparing(Candidate::value, Comparator.comparingInt(wordDistance))
+                .thenComparing(Candidate::value, Comparator.comparingInt(String::length))
+                .thenComparing(Comparator.naturalOrder());
+    }
+
+    protected String getOthersGroupName() {
+        return getString(OTHERS_GROUP_NAME, DEFAULT_OTHERS_GROUP_NAME);
+    }
+
+    protected String getOriginalGroupName() {
+        return getString(ORIGINAL_GROUP_NAME, DEFAULT_ORIGINAL_GROUP_NAME);
+    }
+
+
+    protected Comparator<String> getGroupComparator() {
+        return Comparator.<String>comparingInt(s -> getOthersGroupName().equals(s) ? 1 : getOriginalGroupName().equals(s) ? -1 : 0)
+                .thenComparing(String::toLowerCase, Comparator.naturalOrder());
+    }
+
+    private void mergeCandidates(List<Candidate> possible) {
+        // Merge candidates if the have the same key
+        Map<String, List<Candidate>> keyedCandidates = new HashMap<>();
+        for (Candidate candidate : possible) {
+            if (candidate.key() != null) {
+                List<Candidate> cands = keyedCandidates.computeIfAbsent(candidate.key(), s -> new ArrayList<>());
+                cands.add(candidate);
+            }
+        }
+        if (!keyedCandidates.isEmpty()) {
+            for (List<Candidate> candidates : keyedCandidates.values()) {
+                if (candidates.size() >= 1) {
+                    possible.removeAll(candidates);
+                    // Candidates with the same key are supposed to have
+                    // the same description
+                    candidates.sort(Comparator.comparing(Candidate::value));
+                    Candidate first = candidates.get(0);
+                    String disp = candidates.stream()
+                            .map(Candidate::displ)
+                            .collect(Collectors.joining(" "));
+                    possible.add(new Candidate(first.value(), disp, first.group(),
+                            first.descr(), first.suffix(), null, first.complete()));
+                }
+            }
+        }
+    }
+
+    private Function<Map<String, List<Candidate>>,
+                     Map<String, List<Candidate>>> simpleMatcher(Predicate<String> pred) {
+        return m -> m.entrySet().stream()
+                .filter(e -> pred.test(e.getKey()))
+                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+    }
+
+    private Function<Map<String, List<Candidate>>,
+                     Map<String, List<Candidate>>> typoMatcher(String word, int errors, boolean caseInsensitive) {
+        return m -> {
+            Map<String, List<Candidate>> map = m.entrySet().stream()
+                    .filter(e -> distance(word, caseInsensitive ? e.getKey() : e.getKey().toLowerCase()) < errors)
+                    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+            if (map.size() > 1) {
+                map.computeIfAbsent(word, w -> new ArrayList<>())
+                        .add(new Candidate(word, word, getOriginalGroupName(), null, null, null, false));
+            }
+            return map;
+        };
+    }
+
+    private int distance(String word, String cand) {
+        if (word.length() < cand.length()) {
+            int d1 = Levenshtein.distance(word, cand.substring(0, Math.min(cand.length(), word.length())));
+            int d2 = Levenshtein.distance(word, cand);
+            return Math.min(d1, d2);
+        } else {
+            return Levenshtein.distance(word, cand);
+        }
+    }
+
+    protected boolean nextBindingIsComplete() {
+        redisplay();
+        KeyMap<Binding> keyMap = keyMaps.get(MENU);
+        Binding operation = readBinding(getKeys(), keyMap);
+        if (operation instanceof Reference && MENU_COMPLETE.equals(((Reference) operation).name())) {
+            return true;
+        } else {
+            pushBackBinding();
+            return false;
+        }
+    }
+
+    private class MenuSupport implements Supplier<AttributedString> {
+        final List<Candidate> possible;
+        final BiFunction<CharSequence, Boolean, CharSequence> escaper;
+        int selection;
+        int topLine;
+        String word;
+        AttributedString computed;
+        int lines;
+        int columns;
+        String completed;
+
+        public MenuSupport(List<Candidate> original, String completed, BiFunction<CharSequence, Boolean, CharSequence> escaper) {
+            this.possible = new ArrayList<>();
+            this.escaper = escaper;
+            this.selection = -1;
+            this.topLine = 0;
+            this.word = "";
+            this.completed = completed;
+            computePost(original, null, possible, completed);
+            next();
+        }
+
+        public Candidate completion() {
+            return possible.get(selection);
+        }
+
+        public void next() {
+            selection = (selection + 1) % possible.size();
+            update();
+        }
+
+        public void previous() {
+            selection = (selection + possible.size() - 1) % possible.size();
+            update();
+        }
+
+        /**
+         * Move 'step' options along the major axis of the menu.<p>
+         * ie. if the menu is listing rows first, change row (up/down);
+         * otherwise move column (left/right)
+         *
+         * @param step number of options to move by
+         */
+        private void major(int step) {
+            int axis = isSet(Option.LIST_ROWS_FIRST) ? columns : lines;
+            int sel = selection + step * axis;
+            if (sel < 0) {
+                int pos = (sel + axis) % axis; // needs +axis as (-1)%x == -1
+                int remainders = possible.size() % axis;
+                sel = possible.size() - remainders + pos;
+                if (sel >= possible.size()) {
+                    sel -= axis;
+                }
+            } else if (sel >= possible.size()) {
+                sel = sel % axis;
+            }
+            selection = sel;
+            update();
+        }
+
+        /**
+         * Move 'step' options along the minor axis of the menu.<p>
+         * ie. if the menu is listing rows first, move along the row (left/right);
+         * otherwise move along the column (up/down)
+         *
+         * @param step number of options to move by
+         */
+        private void minor(int step) {
+            int axis = isSet(Option.LIST_ROWS_FIRST) ? columns : lines;
+            int row = selection % axis;
+            int options = possible.size();
+            if (selection - row + axis > options) {
+                // selection is the last row/column
+                // so there are fewer options than other rows
+                axis = options%axis;
+            }
+            selection = selection - row + ((axis + row + step) % axis);
+            update();
+        }
+
+        public void up() {
+            if (isSet(Option.LIST_ROWS_FIRST)) {
+                major(-1);
+            } else {
+                minor(-1);
+            }
+        }
+
+        public void down() {
+            if (isSet(Option.LIST_ROWS_FIRST)) {
+                major(1);
+            } else {
+                minor(1);
+            }
+        }
+
+        public void left() {
+            if (isSet(Option.LIST_ROWS_FIRST)) {
+                minor(-1);
+            } else {
+                major(-1);
+            }
+        }
+
+        public void right() {
+            if (isSet(Option.LIST_ROWS_FIRST)) {
+                minor(1);
+            } else {
+                major(1);
+            }
+        }
+
+        private void update() {
+            buf.backspace(word.length());
+            word = escaper.apply(completion().value(), true).toString();
+            buf.write(word);
+
+            // Compute displayed prompt
+            PostResult pr = computePost(possible, completion(), null, completed);
+            AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>());
+            int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size();
+            if (pr.lines > size.getRows() - promptLines) {
+                int displayed = size.getRows() - promptLines - 1;
+                if (pr.selectedLine >= 0) {
+                    if (pr.selectedLine < topLine) {
+                        topLine = pr.selectedLine;
+                    } else if (pr.selectedLine >= topLine + displayed) {
+                        topLine = pr.selectedLine - displayed + 1;
+                    }
+                }
+                AttributedString post = pr.post;
+                if (post.length() > 0 && post.charAt(post.length() - 1) != '\n') {
+                    post = new AttributedStringBuilder(post.length() + 1)
+                            .append(post).append("\n").toAttributedString();
+                }
+                List<AttributedString> lines = post.columnSplitLength(size.getColumns(), true, display.delayLineWrap());
+                List<AttributedString> sub = new ArrayList<>(lines.subList(topLine, topLine + displayed));
+                sub.add(new AttributedStringBuilder()
+                        .style(AttributedStyle.DEFAULT.foreground(AttributedStyle.CYAN))
+                        .append("rows ")
+                        .append(Integer.toString(topLine + 1))
+                        .append(" to ")
+                        .append(Integer.toString(topLine + displayed))
+                        .append(" of ")
+                        .append(Integer.toString(lines.size()))
+                        .append("\n")
+                        .style(AttributedStyle.DEFAULT).toAttributedString());
+                computed = AttributedString.join(AttributedString.EMPTY, sub);
+            } else {
+                computed = pr.post;
+            }
+            lines = pr.lines;
+            columns = (possible.size() + lines - 1) / lines;
+        }
+
+        @Override
+        public AttributedString get() {
+            return computed;
+        }
+
+    }
+
+    protected boolean doMenu(List<Candidate> original, String completed, BiFunction<CharSequence, Boolean, CharSequence> escaper) {
+        // Reorder candidates according to display order
+        final List<Candidate> possible = new ArrayList<>();
+        boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE);
+        original.sort(getCandidateComparator(caseInsensitive, completed));
+        mergeCandidates(original);
+        computePost(original, null, possible, completed);
+
+        // Build menu support
+        MenuSupport menuSupport = new MenuSupport(original, completed, escaper);
+        post = menuSupport;
+        redisplay();
+
+        // Loop
+        KeyMap<Binding> keyMap = keyMaps.get(MENU);
+        Binding operation;
+        while ((operation = readBinding(getKeys(), keyMap)) != null) {
+            String ref = (operation instanceof Reference) ? ((Reference) operation).name() : "";
+            switch (ref) {
+                case MENU_COMPLETE:
+                    menuSupport.next();
+                    break;
+                case REVERSE_MENU_COMPLETE:
+                    menuSupport.previous();
+                    break;
+                case UP_LINE_OR_HISTORY:
+                case UP_LINE_OR_SEARCH:
+                    menuSupport.up();
+                    break;
+                case DOWN_LINE_OR_HISTORY:
+                case DOWN_LINE_OR_SEARCH:
+                    menuSupport.down();
+                    break;
+                case FORWARD_CHAR:
+                    menuSupport.right();
+                    break;
+                case BACKWARD_CHAR:
+                    menuSupport.left();
+                    break;
+                case CLEAR_SCREEN:
+                    clearScreen();
+                    break;
+                default: {
+                    Candidate completion = menuSupport.completion();
+                    if (completion.suffix() != null) {
+                        String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS);
+                        if (SELF_INSERT.equals(ref)
+                                && chars.indexOf(getLastBinding().charAt(0)) >= 0
+                                || BACKWARD_DELETE_CHAR.equals(ref)) {
+                            buf.backspace(completion.suffix().length());
+                        }
+                    }
+                    if (completion.complete()
+                            && getLastBinding().charAt(0) != ' '
+                            && (SELF_INSERT.equals(ref) || getLastBinding().charAt(0) != ' ')) {
+                        buf.write(' ');
+                    }
+                    if (!ACCEPT_LINE.equals(ref)
+                            && !(SELF_INSERT.equals(ref)
+                                && completion.suffix() != null
+                                && completion.suffix().startsWith(getLastBinding()))) {
+                        pushBackBinding(true);
+                    }
+                    post = null;
+                    return true;
+                }
+            }
+            redisplay();
+        }
+        return false;
+    }
+
+    protected boolean doList(List<Candidate> possible, String completed, boolean runLoop, BiFunction<CharSequence, Boolean, CharSequence> escaper) {
+        // If we list only and if there's a big
+        // number of items, we should ask the user
+        // for confirmation, display the list
+        // and redraw the line at the bottom
+        mergeCandidates(possible);
+        AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>());
+        int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size();
+        PostResult postResult = computePost(possible, null, null, completed);
+        int lines = postResult.lines;
+        int listMax = getInt(LIST_MAX, DEFAULT_LIST_MAX);
+        if (listMax > 0 && possible.size() >= listMax
+                || lines >= size.getRows() - promptLines) {
+            // prompt
+            post = () -> new AttributedString(getAppName() + ": do you wish to see to see all " + possible.size()
+                    + " possibilities (" + lines + " lines)?");
+            redisplay(true);
+            int c = readCharacter();
+            if (c != 'y' && c != 'Y' && c != '\t') {
+                post = null;
+                return false;
+            }
+        }
+
+        boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE);
+        StringBuilder sb = new StringBuilder();
+        while (true) {
+            String current = completed + sb.toString();
+            List<Candidate> cands;
+            if (sb.length() > 0) {
+                cands = possible.stream()
+                        .filter(c -> caseInsensitive
+                                    ? c.value().toLowerCase().startsWith(current.toLowerCase())
+                                    : c.value().startsWith(current))
+                        .sorted(getCandidateComparator(caseInsensitive, current))
+                        .collect(Collectors.toList());
+            } else {
+                cands = possible.stream()
+                        .sorted(getCandidateComparator(caseInsensitive, current))
+                        .collect(Collectors.toList());
+            }
+            post = () -> {
+                AttributedString t = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>());
+                int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size();
+                PostResult pr = computePost(cands, null, null, current);
+                if (pr.lines >= size.getRows() - pl) {
+                    post = null;
+                    int oldCursor = buf.cursor();
+                    buf.cursor(buf.length());
+                    redisplay(false);
+                    buf.cursor(oldCursor);
+                    println();
+                    List<AttributedString> ls = postResult.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap());
+                    Display d = new Display(terminal, false);
+                    d.resize(size.getRows(), size.getColumns());
+                    d.update(ls, -1);
+                    redrawLine();
+                    return new AttributedString("");
+                }
+                return pr.post;
+            };
+            if (!runLoop) {
+                return false;
+            }
+            redisplay();
+            // TODO: use a different keyMap ?
+            Binding b = bindingReader.readBinding(getKeys());
+            if (b instanceof Reference) {
+                String name = ((Reference) b).name();
+                if (BACKWARD_DELETE_CHAR.equals(name) || VI_BACKWARD_DELETE_CHAR.equals(name)) {
+                    if (sb.length() == 0) {
+                        pushBackBinding();
+                        post = null;
+                        return false;
+                    } else {
+                        sb.setLength(sb.length() - 1);
+                        buf.backspace();
+                    }
+                } else if (SELF_INSERT.equals(name)) {
+                    sb.append(getLastBinding());
+                    buf.write(getLastBinding());
+                    if (cands.isEmpty()) {
+                        post = null;
+                        return false;
+                    }
+                } else if ("\t".equals(getLastBinding())) {
+                    if (cands.size() == 1 || sb.length() > 0) {
+                        post = null;
+                        pushBackBinding();
+                    } else if (isSet(Option.AUTO_MENU)) {
+                        buf.backspace(escaper.apply(current, false).length());
+                        doMenu(cands, current, escaper);
+                    }
+                    return false;
+                } else {
+                    pushBackBinding();
+                    post = null;
+                    return false;
+                }
+            } else if (b == null) {
+                post = null;
+                return false;
+            }
+        }
+    }
+
+    protected static class PostResult {
+        final AttributedString post;
+        final int lines;
+        final int selectedLine;
+
+        public PostResult(AttributedString post, int lines, int selectedLine) {
+            this.post = post;
+            this.lines = lines;
+            this.selectedLine = selectedLine;
+        }
+    }
+
+    protected PostResult computePost(List<Candidate> possible, Candidate selection, List<Candidate> ordered, String completed) {
+        return computePost(possible, selection, ordered, completed, display::wcwidth, size.getColumns(), isSet(Option.AUTO_GROUP), isSet(Option.GROUP), isSet(Option.LIST_ROWS_FIRST));
+    }
+
+    protected PostResult computePost(List<Candidate> possible, Candidate selection, List<Candidate> ordered, String completed, Function<String, Integer> wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) {
+        List<Object> strings = new ArrayList<>();
+        if (groupName) {
+            Comparator<String> groupComparator = getGroupComparator();
+            Map<String, Map<String, Candidate>> sorted;
+            sorted = groupComparator != null
+                        ? new TreeMap<>(groupComparator)
+                        : new LinkedHashMap<>();
+            for (Candidate cand : possible) {
+                String group = cand.group();
+                sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>())
+                        .put(cand.value(), cand);
+            }
+            for (Map.Entry<String, Map<String, Candidate>> entry : sorted.entrySet()) {
+                String group = entry.getKey();
+                if (group.isEmpty() && sorted.size() > 1) {
+                    group = getOthersGroupName();
+                }
+                if (!group.isEmpty() && autoGroup) {
+                    strings.add(group);
+                }
+                strings.add(new ArrayList<>(entry.getValue().values()));
+                if (ordered != null) {
+                    ordered.addAll(entry.getValue().values());
+                }
+            }
+        } else {
+            Set<String> groups = new LinkedHashSet<>();
+            TreeMap<String, Candidate> sorted = new TreeMap<>();
+            for (Candidate cand : possible) {
+                String group = cand.group();
+                if (group != null) {
+                    groups.add(group);
+                }
+                sorted.put(cand.value(), cand);
+            }
+            if (autoGroup) {
+                strings.addAll(groups);
+            }
+            strings.add(new ArrayList<>(sorted.values()));
+            if (ordered != null) {
+                ordered.addAll(sorted.values());
+            }
+        }
+        return toColumns(strings, selection, completed, wcwidth, width, rowsFirst);
+    }
+
+    private static final String DESC_PREFIX = "(";
+    private static final String DESC_SUFFIX = ")";
+    private static final int MARGIN_BETWEEN_DISPLAY_AND_DESC = 1;
+    private static final int MARGIN_BETWEEN_COLUMNS = 3;
+
+    @SuppressWarnings("unchecked")
+    protected PostResult toColumns(List<Object> items, Candidate selection, String completed, Function<String, Integer> wcwidth, int width, boolean rowsFirst) {
+        int[] out = new int[2];
+        // TODO: support Option.LIST_PACKED
+        // Compute column width
+        int maxWidth = 0;
+        for (Object item : items) {
+            if (item instanceof String) {
+                int len = wcwidth.apply((String) item);
+                maxWidth = Math.max(maxWidth, len);
+            }
+            else if (item instanceof List) {
+                for (Candidate cand : (List<Candidate>) item) {
+                    int len = wcwidth.apply(cand.displ());
+                    if (cand.descr() != null) {
+                        len += MARGIN_BETWEEN_DISPLAY_AND_DESC;
+                        len += DESC_PREFIX.length();
+                        len += wcwidth.apply(cand.descr());
+                        len += DESC_SUFFIX.length();
+                    }
+                    maxWidth = Math.max(maxWidth, len);
+                }
+            }
+        }
+        // Build columns
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        for (Object list : items) {
+            toColumns(list, width, maxWidth, sb, selection, completed, rowsFirst, out);
+        }
+        if (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n') {
+            sb.setLength(sb.length() - 1);
+        }
+        return new PostResult(sb.toAttributedString(), out[0], out[1]);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected void toColumns(Object items, int width, int maxWidth, AttributedStringBuilder sb, Candidate selection, String completed, boolean rowsFirst, int[] out) {
+        if (maxWidth <= 0) {
+            return;
+        }
+        // This is a group
+        if (items instanceof String) {
+            sb.style(getCompletionStyleGroup())
+                    .append((String) items)
+                    .style(AttributedStyle.DEFAULT)
+                    .append("\n");
+            out[0]++;
+        }
+        // This is a Candidate list
+        else if (items instanceof List) {
+            List<Candidate> candidates = (List<Candidate>) items;
+            maxWidth = Math.min(width, maxWidth);
+            int c = width / maxWidth;
+            while (c > 1 && c * maxWidth + (c - 1) * MARGIN_BETWEEN_COLUMNS >= width) {
+                c--;
+            }
+            int lines = (candidates.size() + c - 1) / c;
+            // Try to minimize the number of columns for the given number of rows
+            // Prevents eg 9 candiates being split 6/3 instead of 5/4.
+            final int columns = (candidates.size() + lines - 1) / lines;
+            IntBinaryOperator index;
+            if (rowsFirst) {
+                index = (i, j) -> i * columns + j;
+            } else {
+                index = (i, j) -> j * lines + i;
+            }
+            for (int i = 0; i < lines; i++) {
+                for (int j = 0; j < columns; j++) {
+                    int idx = index.applyAsInt(i, j);
+                    if (idx < candidates.size()) {
+                        Candidate cand = candidates.get(idx);
+                        boolean hasRightItem = j < columns - 1 && index.applyAsInt(i, j + 1) < candidates.size();
+                        AttributedString left = AttributedString.fromAnsi(cand.displ());
+                        AttributedString right = AttributedString.fromAnsi(cand.descr());
+                        int lw = left.columnLength();
+                        int rw = 0;
+                        if (right != null) {
+                            int rem = maxWidth - (lw + MARGIN_BETWEEN_DISPLAY_AND_DESC
+                                    + DESC_PREFIX.length() + DESC_SUFFIX.length());
+                            rw = right.columnLength();
+                            if (rw > rem) {
+                                right = AttributedStringBuilder.append(
+                                            right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')),
+                                            "\u2026");
+                                rw = right.columnLength();
+                            }
+                            right = AttributedStringBuilder.append(DESC_PREFIX, right, DESC_SUFFIX);
+                            rw += DESC_PREFIX.length() + DESC_SUFFIX.length();
+                        }
+                        if (cand == selection) {
+                            out[1] = i;
+                            sb.style(getCompletionStyleSelection());
+                            if (left.toString().regionMatches(
+                                    isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) {
+                                sb.append(left.toString(), 0, completed.length());
+                                sb.append(left.toString(), completed.length(), left.length());
+                            } else {
+                                sb.append(left.toString());
+                            }
+                            for (int k = 0; k < maxWidth - lw - rw; k++) {
+                                sb.append(' ');
+                            }
+                            if (right != null) {
+                                sb.append(right);
+                            }
+                            sb.style(AttributedStyle.DEFAULT);
+                        } else {
+                            if (left.toString().regionMatches(
+                                    isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) {
+                                sb.style(getCompletionStyleStarting());
+                                sb.append(left, 0, completed.length());
+                                sb.style(AttributedStyle.DEFAULT);
+                                sb.append(left, completed.length(), left.length());
+                            } else {
+                                sb.append(left);
+                            }
+                            if (right != null || hasRightItem) {
+                                for (int k = 0; k < maxWidth - lw - rw; k++) {
+                                    sb.append(' ');
+                                }
+                            }
+                            if (right != null) {
+                                sb.style(getCompletionStyleDescription());
+                                sb.append(right);
+                                sb.style(AttributedStyle.DEFAULT);
+                            }
+                        }
+                        if (hasRightItem) {
+                            for (int k = 0; k < MARGIN_BETWEEN_COLUMNS; k++) {
+                                sb.append(' ');
+                            }
+                        }
+                    }
+                }
+                sb.append('\n');
+            }
+            out[0] += lines;
+        }
+    }
+
+    private AttributedStyle getCompletionStyleStarting() {
+        return getCompletionStyle(COMPLETION_STYLE_STARTING, DEFAULT_COMPLETION_STYLE_STARTING);
+    }
+
+    protected AttributedStyle getCompletionStyleDescription() {
+        return getCompletionStyle(COMPLETION_STYLE_DESCRIPTION, DEFAULT_COMPLETION_STYLE_DESCRIPTION);
+    }
+
+    protected AttributedStyle getCompletionStyleGroup() {
+        return getCompletionStyle(COMPLETION_STYLE_GROUP, DEFAULT_COMPLETION_STYLE_GROUP);
+    }
+
+    protected AttributedStyle getCompletionStyleSelection() {
+        return getCompletionStyle(COMPLETION_STYLE_SELECTION, DEFAULT_COMPLETION_STYLE_SELECTION);
+    }
+
+    protected AttributedStyle getCompletionStyle(String name, String value) {
+        return buildStyle(getString(name, value));
+    }
+
+    protected AttributedStyle buildStyle(String str) {
+        return AttributedString.fromAnsi("\u001b[" + str + "m ").styleAt(0);
+    }
+
+    private String getCommonStart(String str1, String str2, boolean caseInsensitive) {
+        int[] s1 = str1.codePoints().toArray();
+        int[] s2 = str2.codePoints().toArray();
+        int len = 0;
+        while (len < Math.min(s1.length, s2.length)) {
+            int ch1 = s1[len];
+            int ch2 = s2[len];
+            if (ch1 != ch2 && caseInsensitive) {
+                ch1 = Character.toUpperCase(ch1);
+                ch2 = Character.toUpperCase(ch2);
+                if (ch1 != ch2) {
+                    ch1 = Character.toLowerCase(ch1);
+                    ch2 = Character.toLowerCase(ch2);
+                }
+            }
+            if (ch1 != ch2) {
+                break;
+            }
+            len++;
+        }
+        return new String(s1, 0, len);
+    }
+
+    /**
+     * Used in "vi" mode for argumented history move, to move a specific
+     * number of history entries forward or back.
+     *
+     * @param next If true, move forward
+     * @param count The number of entries to move
+     * @return true if the move was successful
+     */
+    protected boolean moveHistory(final boolean next, int count) {
+        boolean ok = true;
+        for (int i = 0; i < count && (ok = moveHistory(next)); i++) {
+            /* empty */
+        }
+        return ok;
+    }
+
+    /**
+     * Move up or down the history tree.
+     * @param next <code>true</code> to go to the next, <code>false</code> for the previous.
+     * @return <code>true</code> if successful, <code>false</code> otherwise
+     */
+    protected boolean moveHistory(final boolean next) {
+        if (!buf.toString().equals(history.current())) {
+            modifiedHistory.put(history.index(), buf.toString());
+        }
+        if (next && !history.next()) {
+            return false;
+        }
+        else if (!next && !history.previous()) {
+            return false;
+        }
+
+        setBuffer(modifiedHistory.containsKey(history.index())
+                    ? modifiedHistory.get(history.index())
+                    : history.current());
+
+        return true;
+    }
+
+    //
+    // Printing
+    //
+
+    /**
+     * Raw output printing.
+     * @param str the string to print to the terminal
+     */
+    void print(String str) {
+        terminal.writer().write(str);
+    }
+
+    void println(String s) {
+        print(s);
+        println();
+    }
+
+    /**
+     * Output a platform-dependant newline.
+     */
+    void println() {
+        terminal.puts(Capability.carriage_return);
+        print("\n");
+        redrawLine();
+    }
+
+
+    //
+    // Actions
+    //
+
+    protected boolean killBuffer() {
+        killRing.add(buf.toString());
+        buf.clear();
+        return true;
+    }
+
+    protected boolean killWholeLine() {
+        if (buf.length() == 0) {
+            return false;
+        }
+        int start;
+        int end;
+        if (count < 0) {
+            end = buf.cursor();
+            while (buf.atChar(end) != 0 && buf.atChar(end) != '\n') {
+                end++;
+            }
+            start = end;
+            for (int count = -this.count; count > 0; --count) {
+                while (start > 0 && buf.atChar(start - 1) != '\n') {
+                    start--;
+                }
+                start--;
+            }
+        } else {
+            start = buf.cursor();
+            while (start > 0 && buf.atChar(start - 1) != '\n') {
+                start--;
+            }
+            end = start;
+            while (count-- > 0) {
+                while (end < buf.length() && buf.atChar(end) != '\n') {
+                    end++;
+                }
+                end++;
+            }
+        }
+        String killed = buf.substring(start, end);
+        buf.cursor(start);
+        buf.delete(end - start);
+        killRing.add(killed);
+        return true;
+    }
+
+    /**
+     * Kill the buffer ahead of the current cursor position.
+     *
+     * @return true if successful
+     */
+    public boolean killLine() {
+        if (count < 0) {
+            return callNeg(this::backwardKillLine);
+        }
+        if (buf.cursor() == buf.length()) {
+            return false;
+        }
+        int cp = buf.cursor();
+        int len = cp;
+        while (count-- > 0) {
+            if (buf.atChar(len) == '\n') {
+                len++;
+            } else {
+                while (buf.atChar(len) != 0 && buf.atChar(len) != '\n') {
+                    len++;
+                }
+            }
+        }
+        int num = len - cp;
+        String killed = buf.substring(cp, cp + num);
+        buf.delete(num);
+        killRing.add(killed);
+        return true;
+    }
+
+    public boolean backwardKillLine() {
+        if (count < 0) {
+            return callNeg(this::killLine);
+        }
+        if (buf.cursor() == 0) {
+            return false;
+        }
+        int cp = buf.cursor();
+        int beg = cp;
+        while (count-- > 0) {
+            if (beg == 0) {
+                break;
+            }
+            if (buf.atChar(beg - 1) == '\n') {
+                beg--;
+            } else {
+                while (beg > 0 && buf.atChar(beg - 1) != 0 && buf.atChar(beg - 1) != '\n') {
+                    beg--;
+                }
+            }
+        }
+        int num = cp - beg;
+        String killed = buf.substring(cp - beg, cp);
+        buf.cursor(beg);
+        buf.delete(num);
+        killRing.add(killed);
+        return true;
+    }
+
+    public boolean killRegion() {
+        return doCopyKillRegion(true);
+    }
+
+    public boolean copyRegionAsKill() {
+        return doCopyKillRegion(false);
+    }
+
+    private boolean doCopyKillRegion(boolean kill) {
+        if (regionMark > buf.length()) {
+            regionMark = buf.length();
+        }
+        if (regionActive == RegionType.LINE) {
+            int start = regionMark;
+            int end = buf.cursor();
+            if (start < end) {
+                while (start > 0 && buf.atChar(start - 1) != '\n') {
+                    start--;
+                }
+                while (end < buf.length() - 1 && buf.atChar(end + 1) != '\n') {
+                    end++;
+                }
+                if (isInViCmdMode()) {
+                    end++;
+                }
+                killRing.add(buf.substring(start, end));
+                if (kill) {
+                    buf.backspace(end - start);
+                }
+            } else {
+                while (end > 0 && buf.atChar(end - 1) != '\n') {
+                    end--;
+                }
+                while (start < buf.length() && buf.atChar(start) != '\n') {
+                    start++;
+                }
+                if (isInViCmdMode()) {
+                    start++;
+                }
+                killRing.addBackwards(buf.substring(end, start));
+                if (kill) {
+                    buf.cursor(end);
+                    buf.delete(start - end);
+                }
+            }
+        } else if (regionMark > buf.cursor()) {
+            if (isInViCmdMode()) {
+                regionMark++;
+            }
+            killRing.add(buf.substring(buf.cursor(), regionMark));
+            if (kill) {
+                buf.delete(regionMark - buf.cursor());
+            }
+        } else {
+            if (isInViCmdMode()) {
+                buf.move(1);
+            }
+            killRing.add(buf.substring(regionMark, buf.cursor()));
+            if (kill) {
+                buf.backspace(buf.cursor() - regionMark);
+            }
+        }
+        if (kill) {
+            regionActive = RegionType.NONE;
+        }
+        return true;
+    }
+
+    public boolean yank() {
+        String yanked = killRing.yank();
+        if (yanked == null) {
+            return false;
+        } else {
+            putString(yanked);
+            return true;
+        }
+    }
+
+    public boolean yankPop() {
+        if (!killRing.lastYank()) {
+            return false;
+        }
+        String current = killRing.yank();
+        if (current == null) {
+            // This shouldn't happen.
+            return false;
+        }
+        buf.backspace(current.length());
+        String yanked = killRing.yankPop();
+        if (yanked == null) {
+            // This shouldn't happen.
+            return false;
+        }
+
+        putString(yanked);
+        return true;
+    }
+
+    public boolean mouse() {
+        MouseEvent event = readMouseEvent();
+        if (event.getType() == MouseEvent.Type.Released
+                && event.getButton() == MouseEvent.Button.Button1) {
+            StringBuilder tsb = new StringBuilder();
+            Cursor cursor = terminal.getCursorPosition(c -> tsb.append((char) c));
+            bindingReader.runMacro(tsb.toString());
+
+            List<AttributedString> secondaryPrompts = new ArrayList<>();
+            getDisplayedBufferWithPrompts(secondaryPrompts);
+
+            AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
+            sb.append(prompt);
+            sb.append(insertSecondaryPrompts(new AttributedString(buf.upToCursor()), secondaryPrompts, false));
+            List<AttributedString> promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap());
+
+            int currentLine = promptLines.size() - 1;
+            int wantedLine = Math.max(0, Math.min(currentLine + event.getY() - cursor.getY(), secondaryPrompts.size()));
+            int pl0 = currentLine == 0 ? prompt.columnLength() : secondaryPrompts.get(currentLine - 1).columnLength();
+            int pl1 = wantedLine == 0 ? prompt.columnLength() : secondaryPrompts.get(wantedLine - 1).columnLength();
+            int adjust = pl1 - pl0;
+            buf.moveXY(event.getX() - cursor.getX() - adjust, event.getY() - cursor.getY());
+        }
+        return true;
+    }
+
+    public boolean beginPaste() {
+        final Object SELF_INSERT = new Object();
+        final Object END_PASTE = new Object();
+        KeyMap<Object> keyMap = new KeyMap<>();
+        keyMap.setUnicode(SELF_INSERT);
+        keyMap.setNomatch(SELF_INSERT);
+        keyMap.setAmbiguousTimeout(0);
+        keyMap.bind(END_PASTE, BRACKETED_PASTE_END);
+        StringBuilder sb = new StringBuilder();
+        while (true) {
+            Object b = bindingReader.readBinding(keyMap);
+            if (b == END_PASTE) {
+                break;
+            }
+            String s = getLastBinding();
+            if ("\r".equals(s)) {
+                s = "\n";
+            }
+            sb.append(s);
+        }
+        regionActive = RegionType.PASTE;
+        regionMark = getBuffer().cursor();
+        getBuffer().write(sb);
+        return true;
+    }
+
+    public boolean focusIn() {
+        return false;
+    }
+
+    public boolean focusOut() {
+        return false;
+    }
+
+    /**
+     * Clean the used display
+     * @return <code>true</code>
+     */
+    public boolean clear() {
+        display.update(Collections.emptyList(), 0);
+        return true;
+    }
+
+    /**
+     * Clear the screen by issuing the ANSI "clear screen" code.
+     * @return <code>true</code>
+     */
+    public boolean clearScreen() {
+        if (terminal.puts(Capability.clear_screen)) {
+            Status status = Status.getStatus(terminal, false);
+            if (status != null) {
+                status.reset();
+            }
+            redrawLine();
+        } else {
+            println();
+        }
+        return true;
+    }
+
+    /**
+     * Issue an audible keyboard bell.
+     * @return <code>true</code>
+     */
+    public boolean beep() {
+        BellType bell_preference = BellType.AUDIBLE;
+        switch (getString(BELL_STYLE, DEFAULT_BELL_STYLE).toLowerCase()) {
+            case "none":
+            case "off":
+                bell_preference = BellType.NONE;
+                break;
+            case "audible":
+                bell_preference = BellType.AUDIBLE;
+                break;
+            case "visible":
+                bell_preference = BellType.VISIBLE;
+                break;
+            case "on":
+                bell_preference = getBoolean(PREFER_VISIBLE_BELL, false)
+                        ? BellType.VISIBLE : BellType.AUDIBLE;
+                break;
+        }
+        if (bell_preference == BellType.VISIBLE) {
+            if (terminal.puts(Capability.flash_screen)
+                    || terminal.puts(Capability.bell)) {
+                flush();
+            }
+        } else if (bell_preference == BellType.AUDIBLE) {
+            if (terminal.puts(Capability.bell)) {
+                flush();
+            }
+        }
+        return true;
+    }
+
+    //
+    // Helpers
+    //
+
+    /**
+     * Checks to see if the specified character is a delimiter. We consider a
+     * character a delimiter if it is anything but a letter or digit.
+     *
+     * @param c     The character to test
+     * @return      True if it is a delimiter
+     */
+    protected boolean isDelimiter(int c) {
+        return !Character.isLetterOrDigit(c);
+    }
+
+    /**
+     * Checks to see if a character is a whitespace character. Currently
+     * this delegates to {@link Character#isWhitespace(char)}, however
+     * eventually it should be hooked up so that the definition of whitespace
+     * can be configured, as readline does.
+     *
+     * @param c The character to check
+     * @return true if the character is a whitespace
+     */
+    protected boolean isWhitespace(int c) {
+        return Character.isWhitespace(c);
+    }
+
+    protected boolean isViAlphaNum(int c) {
+        return c == '_' || Character.isLetterOrDigit(c);
+    }
+
+    protected boolean isAlpha(int c) {
+        return Character.isLetter(c);
+    }
+
+    protected boolean isWord(int c) {
+        String wordchars = getString(WORDCHARS, DEFAULT_WORDCHARS);
+        return Character.isLetterOrDigit(c)
+                || (c < 128 && wordchars.indexOf((char) c) >= 0);
+    }
+
+    String getString(String name, String def) {
+        return ReaderUtils.getString(this, name, def);
+    }
+
+    boolean getBoolean(String name, boolean def) {
+        return ReaderUtils.getBoolean(this, name, def);
+    }
+
+    int getInt(String name, int def) {
+        return ReaderUtils.getInt(this, name, def);
+    }
+
+    long getLong(String name, long def) {
+        return ReaderUtils.getLong(this, name, def);
+    }
+
+    @Override
+    public Map<String, KeyMap<Binding>> defaultKeyMaps() {
+        Map<String, KeyMap<Binding>> keyMaps = new HashMap<>();
+        keyMaps.put(EMACS, emacs());
+        keyMaps.put(VICMD, viCmd());
+        keyMaps.put(VIINS, viInsertion());
+        keyMaps.put(MENU, menu());
+        keyMaps.put(VIOPP, viOpp());
+        keyMaps.put(VISUAL, visual());
+        keyMaps.put(SAFE, safe());
+        if (getBoolean(BIND_TTY_SPECIAL_CHARS, true)) {
+            Attributes attr = terminal.getAttributes();
+            bindConsoleChars(keyMaps.get(EMACS), attr);
+            bindConsoleChars(keyMaps.get(VIINS), attr);
+        }
+        // Put default
+        for (KeyMap<Binding> keyMap : keyMaps.values()) {
+            keyMap.setUnicode(new Reference(SELF_INSERT));
+            keyMap.setAmbiguousTimeout(getLong(AMBIGUOUS_BINDING, DEFAULT_AMBIGUOUS_BINDING));
+        }
+        // By default, link main to emacs
+        keyMaps.put(MAIN, keyMaps.get(EMACS));
+        return keyMaps;
+    }
+
+    public KeyMap<Binding> emacs() {
+        KeyMap<Binding> emacs = new KeyMap<>();
+        bind(emacs, SET_MARK_COMMAND,                       ctrl('@'));
+        bind(emacs, BEGINNING_OF_LINE,                      ctrl('A'));
+        bind(emacs, BACKWARD_CHAR,                          ctrl('B'));
+        bind(emacs, DELETE_CHAR_OR_LIST,                    ctrl('D'));
+        bind(emacs, END_OF_LINE,                            ctrl('E'));
+        bind(emacs, FORWARD_CHAR,                           ctrl('F'));
+        bind(emacs, SEND_BREAK,                             ctrl('G'));
+        bind(emacs, BACKWARD_DELETE_CHAR,                   ctrl('H'));
+        bind(emacs, EXPAND_OR_COMPLETE,                     ctrl('I'));
+        bind(emacs, ACCEPT_LINE,                            ctrl('J'));
+        bind(emacs, KILL_LINE,                              ctrl('K'));
+        bind(emacs, CLEAR_SCREEN,                           ctrl('L'));
+        bind(emacs, ACCEPT_LINE,                            ctrl('M'));
+        bind(emacs, DOWN_LINE_OR_HISTORY,                   ctrl('N'));
+        bind(emacs, UP_LINE_OR_HISTORY,                     ctrl('P'));
+        bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD,    ctrl('R'));
+        bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD,     ctrl('S'));
+        bind(emacs, TRANSPOSE_CHARS,                        ctrl('T'));
+        bind(emacs, KILL_WHOLE_LINE,                        ctrl('U'));
+        bind(emacs, QUOTED_INSERT,                          ctrl('V'));
+        bind(emacs, BACKWARD_KILL_WORD,                     ctrl('W'));
+        bind(emacs, YANK,                                   ctrl('Y'));
+        bind(emacs, CHARACTER_SEARCH,                       ctrl(']'));
+        bind(emacs, UNDO,                                   ctrl('_'));
+        bind(emacs, SELF_INSERT,                            range(" -~"));
+        bind(emacs, INSERT_CLOSE_PAREN,                     ")");
+        bind(emacs, INSERT_CLOSE_SQUARE,                    "]");
+        bind(emacs, INSERT_CLOSE_CURLY,                     "}");
+        bind(emacs, BACKWARD_DELETE_CHAR,                   del());
+        bind(emacs, VI_MATCH_BRACKET,                       translate("^X^B"));
+        bind(emacs, SEND_BREAK,                             translate("^X^G"));
+        bind(emacs, VI_FIND_NEXT_CHAR,                      translate("^X^F"));
+        bind(emacs, VI_JOIN,                                translate("^X^J"));
+        bind(emacs, KILL_BUFFER,                            translate("^X^K"));
+        bind(emacs, INFER_NEXT_HISTORY,                     translate("^X^N"));
+        bind(emacs, OVERWRITE_MODE,                         translate("^X^O"));
+        bind(emacs, REDO,                                   translate("^X^R"));
+        bind(emacs, UNDO,                                   translate("^X^U"));
+        bind(emacs, VI_CMD_MODE,                            translate("^X^V"));
+        bind(emacs, EXCHANGE_POINT_AND_MARK,                translate("^X^X"));
+        bind(emacs, DO_LOWERCASE_VERSION,                   translate("^XA-^XZ"));
+        bind(emacs, WHAT_CURSOR_POSITION,                   translate("^X="));
+        bind(emacs, KILL_LINE,                              translate("^X^?"));
+        bind(emacs, SEND_BREAK,                             alt(ctrl('G')));
+        bind(emacs, BACKWARD_KILL_WORD,                     alt(ctrl('H')));
+        bind(emacs, SELF_INSERT_UNMETA,                     alt(ctrl('M')));
+        bind(emacs, COMPLETE_WORD,                          alt(esc()));
+        bind(emacs, CHARACTER_SEARCH_BACKWARD,              alt(ctrl(']')));
+        bind(emacs, COPY_PREV_WORD,                         alt(ctrl('_')));
+        bind(emacs, SET_MARK_COMMAND,                       alt(' '));
+        bind(emacs, NEG_ARGUMENT,                           alt('-'));
+        bind(emacs, DIGIT_ARGUMENT,                         range("\\E0-\\E9"));
+        bind(emacs, BEGINNING_OF_HISTORY,                   alt('<'));
+        bind(emacs, LIST_CHOICES,                           alt('='));
+        bind(emacs, END_OF_HISTORY,                         alt('>'));
+        bind(emacs, LIST_CHOICES,                           alt('?'));
+        bind(emacs, DO_LOWERCASE_VERSION,                   range("^[A-^[Z"));
+        bind(emacs, BACKWARD_WORD,                          alt('b'));
+        bind(emacs, CAPITALIZE_WORD,                        alt('c'));
+        bind(emacs, KILL_WORD,                              alt('d'));
+        bind(emacs, KILL_WORD,                              translate("^[[3;5~")); // ctrl-delete
+        bind(emacs, FORWARD_WORD,                           alt('f'));
+        bind(emacs, DOWN_CASE_WORD,                         alt('l'));
+        bind(emacs, HISTORY_SEARCH_FORWARD,                 alt('n'));
+        bind(emacs, HISTORY_SEARCH_BACKWARD,                alt('p'));
+        bind(emacs, TRANSPOSE_WORDS,                        alt('t'));
+        bind(emacs, UP_CASE_WORD,                           alt('u'));
+        bind(emacs, YANK_POP,                               alt('y'));
+        bind(emacs, BACKWARD_KILL_WORD,                     alt(del()));
+        bindArrowKeys(emacs);
+        bind(emacs, FORWARD_WORD,                           translate("^[[1;5C")); // ctrl-left
+        bind(emacs, BACKWARD_WORD,                          translate("^[[1;5D")); // ctrl-right
+        bind(emacs, FORWARD_WORD,                           alt(key(Capability.key_right)));
+        bind(emacs, BACKWARD_WORD,                          alt(key(Capability.key_left)));
+        bind(emacs, FORWARD_WORD,                           alt(translate("^[[C")));
+        bind(emacs, BACKWARD_WORD,                          alt(translate("^[[D")));
+        return emacs;
+    }
+
+    public KeyMap<Binding> viInsertion() {
+        KeyMap<Binding> viins = new KeyMap<>();
+        bind(viins, SELF_INSERT,                            range("^@-^_"));
+        bind(viins, LIST_CHOICES,                           ctrl('D'));
+        bind(viins, SEND_BREAK,                             ctrl('G'));
+        bind(viins, BACKWARD_DELETE_CHAR,                   ctrl('H'));
+        bind(viins, EXPAND_OR_COMPLETE,                     ctrl('I'));
+        bind(viins, ACCEPT_LINE,                            ctrl('J'));
+        bind(viins, CLEAR_SCREEN,                           ctrl('L'));
+        bind(viins, ACCEPT_LINE,                            ctrl('M'));
+        bind(viins, MENU_COMPLETE,                          ctrl('N'));
+        bind(viins, REVERSE_MENU_COMPLETE,                  ctrl('P'));
+        bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD,    ctrl('R'));
+        bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD,     ctrl('S'));
+        bind(viins, TRANSPOSE_CHARS,                        ctrl('T'));
+        bind(viins, KILL_WHOLE_LINE,                        ctrl('U'));
+        bind(viins, QUOTED_INSERT,                          ctrl('V'));
+        bind(viins, BACKWARD_KILL_WORD,                     ctrl('W'));
+        bind(viins, YANK,                                   ctrl('Y'));
+        bind(viins, VI_CMD_MODE,                            ctrl('['));
+        bind(viins, UNDO,                                   ctrl('_'));
+        bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD,    ctrl('X') + "r");
+        bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD,     ctrl('X') + "s");
+        bind(viins, SELF_INSERT,                            range(" -~"));
+        bind(viins, INSERT_CLOSE_PAREN,                     ")");
+        bind(viins, INSERT_CLOSE_SQUARE,                    "]");
+        bind(viins, INSERT_CLOSE_CURLY,                     "}");
+        bind(viins, BACKWARD_DELETE_CHAR,                   del());
+        bindArrowKeys(viins);
+        return viins;
+    }
+
+    public KeyMap<Binding> viCmd() {
+        KeyMap<Binding> vicmd = new KeyMap<>();
+        bind(vicmd, LIST_CHOICES,                           ctrl('D'));
+        bind(vicmd, EMACS_EDITING_MODE,                     ctrl('E'));
+        bind(vicmd, SEND_BREAK,                             ctrl('G'));
+        bind(vicmd, VI_BACKWARD_CHAR,                       ctrl('H'));
+        bind(vicmd, ACCEPT_LINE,                            ctrl('J'));
+        bind(vicmd, KILL_LINE,                              ctrl('K'));
+        bind(vicmd, CLEAR_SCREEN,                           ctrl('L'));
+        bind(vicmd, ACCEPT_LINE,                            ctrl('M'));
+        bind(vicmd, VI_DOWN_LINE_OR_HISTORY,                ctrl('N'));
+        bind(vicmd, VI_UP_LINE_OR_HISTORY,                  ctrl('P'));
+        bind(vicmd, QUOTED_INSERT,                          ctrl('Q'));
+        bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD,    ctrl('R'));
+        bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD,     ctrl('S'));
+        bind(vicmd, TRANSPOSE_CHARS,                        ctrl('T'));
+        bind(vicmd, KILL_WHOLE_LINE,                        ctrl('U'));
+        bind(vicmd, QUOTED_INSERT,                          ctrl('V'));
+        bind(vicmd, BACKWARD_KILL_WORD,                     ctrl('W'));
+        bind(vicmd, YANK,                                   ctrl('Y'));
+        bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD,    ctrl('X') + "r");
+        bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD,     ctrl('X') + "s");
+        bind(vicmd, SEND_BREAK,                             alt(ctrl('G')));
+        bind(vicmd, BACKWARD_KILL_WORD,                     alt(ctrl('H')));
+        bind(vicmd, SELF_INSERT_UNMETA,                     alt(ctrl('M')));
+        bind(vicmd, COMPLETE_WORD,                          alt(esc()));
+        bind(vicmd, CHARACTER_SEARCH_BACKWARD,              alt(ctrl(']')));
+        bind(vicmd, SET_MARK_COMMAND,                       alt(' '));
+//        bind(vicmd, INSERT_COMMENT,                         alt('#'));
+//        bind(vicmd, INSERT_COMPLETIONS,                     alt('*'));
+        bind(vicmd, DIGIT_ARGUMENT,                         alt('-'));
+        bind(vicmd, BEGINNING_OF_HISTORY,                   alt('<'));
+        bind(vicmd, LIST_CHOICES,                           alt('='));
+        bind(vicmd, END_OF_HISTORY,                         alt('>'));
+        bind(vicmd, LIST_CHOICES,                           alt('?'));
+        bind(vicmd, DO_LOWERCASE_VERSION,                   range("^[A-^[Z"));
+        bind(vicmd, BACKWARD_WORD,                          alt('b'));
+        bind(vicmd, CAPITALIZE_WORD,                        alt('c'));
+        bind(vicmd, KILL_WORD,                              alt('d'));
+        bind(vicmd, FORWARD_WORD,                           alt('f'));
+        bind(vicmd, DOWN_CASE_WORD,                         alt('l'));
+        bind(vicmd, HISTORY_SEARCH_FORWARD,                 alt('n'));
+        bind(vicmd, HISTORY_SEARCH_BACKWARD,                alt('p'));
+        bind(vicmd, TRANSPOSE_WORDS,                        alt('t'));
+        bind(vicmd, UP_CASE_WORD,                           alt('u'));
+        bind(vicmd, YANK_POP,                               alt('y'));
+        bind(vicmd, BACKWARD_KILL_WORD,                     alt(del()));
+
+        bind(vicmd, FORWARD_CHAR,                           " ");
+        bind(vicmd, VI_INSERT_COMMENT,                      "#");
+        bind(vicmd, END_OF_LINE,                            "$");
+        bind(vicmd, VI_MATCH_BRACKET,                       "%");
+        bind(vicmd, VI_DOWN_LINE_OR_HISTORY,                "+");
+        bind(vicmd, VI_REV_REPEAT_FIND,                     ",");
+        bind(vicmd, VI_UP_LINE_OR_HISTORY,                  "-");
+        bind(vicmd, VI_REPEAT_CHANGE,                       ".");
+        bind(vicmd, VI_HISTORY_SEARCH_BACKWARD,             "/");
+        bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE,          "0");
+        bind(vicmd, DIGIT_ARGUMENT,                         range("1-9"));
+        bind(vicmd, VI_REPEAT_FIND,                         ";");
+        bind(vicmd, LIST_CHOICES,                           "=");
+        bind(vicmd, VI_HISTORY_SEARCH_FORWARD,              "?");
+        bind(vicmd, VI_ADD_EOL,                             "A");
+        bind(vicmd, VI_BACKWARD_BLANK_WORD,                 "B");
+        bind(vicmd, VI_CHANGE_EOL,                          "C");
+        bind(vicmd, VI_KILL_EOL,                            "D");
+        bind(vicmd, VI_FORWARD_BLANK_WORD_END,              "E");
+        bind(vicmd, VI_FIND_PREV_CHAR,                      "F");
+        bind(vicmd, VI_FETCH_HISTORY,                       "G");
+        bind(vicmd, VI_INSERT_BOL,                          "I");
+        bind(vicmd, VI_JOIN,                                "J");
+        bind(vicmd, VI_REV_REPEAT_SEARCH,                   "N");
+        bind(vicmd, VI_OPEN_LINE_ABOVE,                     "O");
+        bind(vicmd, VI_PUT_BEFORE,                          "P");
+        bind(vicmd, VI_REPLACE,                             "R");
+        bind(vicmd, VI_KILL_LINE,                           "S");
+        bind(vicmd, VI_FIND_PREV_CHAR_SKIP,                 "T");
+        bind(vicmd, REDO,                                   "U");
+        bind(vicmd, VISUAL_LINE_MODE,                       "V");
+        bind(vicmd, VI_FORWARD_BLANK_WORD,                  "W");
+        bind(vicmd, VI_BACKWARD_DELETE_CHAR,                "X");
+        bind(vicmd, VI_YANK_WHOLE_LINE,                     "Y");
+        bind(vicmd, VI_FIRST_NON_BLANK,                     "^");
+        bind(vicmd, VI_ADD_NEXT,                            "a");
+        bind(vicmd, VI_BACKWARD_WORD,                       "b");
+        bind(vicmd, VI_CHANGE,                              "c");
+        bind(vicmd, VI_DELETE,                              "d");
+        bind(vicmd, VI_FORWARD_WORD_END,                    "e");
+        bind(vicmd, VI_FIND_NEXT_CHAR,                      "f");
+        bind(vicmd, WHAT_CURSOR_POSITION,                   "ga");
+        bind(vicmd, VI_BACKWARD_BLANK_WORD_END,             "gE");
+        bind(vicmd, VI_BACKWARD_WORD_END,                   "ge");
+        bind(vicmd, VI_BACKWARD_CHAR,                       "h");
+        bind(vicmd, VI_INSERT,                              "i");
+        bind(vicmd, DOWN_LINE_OR_HISTORY,                   "j");
+        bind(vicmd, UP_LINE_OR_HISTORY,                     "k");
+        bind(vicmd, VI_FORWARD_CHAR,                        "l");
+        bind(vicmd, VI_REPEAT_SEARCH,                       "n");
+        bind(vicmd, VI_OPEN_LINE_BELOW,                     "o");
+        bind(vicmd, VI_PUT_AFTER,                           "p");
+        bind(vicmd, VI_REPLACE_CHARS,                       "r");
+        bind(vicmd, VI_SUBSTITUTE,                          "s");
+        bind(vicmd, VI_FIND_NEXT_CHAR_SKIP,                 "t");
+        bind(vicmd, UNDO,                                   "u");
+        bind(vicmd, VISUAL_MODE,                            "v");
+        bind(vicmd, VI_FORWARD_WORD,                        "w");
+        bind(vicmd, VI_DELETE_CHAR,                         "x");
+        bind(vicmd, VI_YANK,                                "y");
+        bind(vicmd, VI_GOTO_COLUMN,                         "|");
+        bind(vicmd, VI_SWAP_CASE,                           "~");
+        bind(vicmd, VI_BACKWARD_CHAR,                       del());
+
+        bindArrowKeys(vicmd);
+        return vicmd;
+    }
+
+    public KeyMap<Binding> menu() {
+        KeyMap<Binding> menu = new KeyMap<>();
+        bind(menu, MENU_COMPLETE,                     "\t");
+        bind(menu, REVERSE_MENU_COMPLETE,             key(Capability.back_tab));
+        bind(menu, ACCEPT_LINE,                       "\r", "\n");
+        bindArrowKeys(menu);
+        return menu;
+    }
+
+    public KeyMap<Binding> safe() {
+        KeyMap<Binding> safe = new KeyMap<>();
+        bind(safe, SELF_INSERT,                 range("^@-^?"));
+        bind(safe, ACCEPT_LINE,                 "\r", "\n");
+        bind(safe, SEND_BREAK,                  ctrl('G'));
+        return safe;
+    }
+
+    public KeyMap<Binding> visual() {
+        KeyMap<Binding> visual = new KeyMap<>();
+        bind(visual, UP_LINE,                   key(Capability.key_up),     "k");
+        bind(visual, DOWN_LINE,                 key(Capability.key_down),   "j");
+        bind(visual, this::deactivateRegion,    esc());
+        bind(visual, EXCHANGE_POINT_AND_MARK,   "o");
+        bind(visual, PUT_REPLACE_SELECTION,     "p");
+        bind(visual, VI_DELETE,                 "x");
+        bind(visual, VI_OPER_SWAP_CASE,         "~");
+        return visual;
+    }
+
+    public KeyMap<Binding> viOpp() {
+        KeyMap<Binding> viOpp = new KeyMap<>();
+        bind(viOpp, UP_LINE,                    key(Capability.key_up),     "k");
+        bind(viOpp, DOWN_LINE,                  key(Capability.key_down),   "j");
+        bind(viOpp, VI_CMD_MODE,                esc());
+        return viOpp;
+    }
+
+    private void bind(KeyMap<Binding> map, String widget, Iterable<? extends CharSequence> keySeqs) {
+        map.bind(new Reference(widget), keySeqs);
+    }
+
+    private void bind(KeyMap<Binding> map, String widget, CharSequence... keySeqs) {
+        map.bind(new Reference(widget), keySeqs);
+    }
+
+    private void bind(KeyMap<Binding> map, Widget widget, CharSequence... keySeqs) {
+        map.bind(widget, keySeqs);
+    }
+
+    private String key(Capability capability) {
+        return KeyMap.key(terminal, capability);
+    }
+
+    private void bindArrowKeys(KeyMap<Binding> map) {
+        bind(map, UP_LINE_OR_SEARCH,    key(Capability.key_up));
+        bind(map, DOWN_LINE_OR_SEARCH,  key(Capability.key_down));
+        bind(map, BACKWARD_CHAR,        key(Capability.key_left));
+        bind(map, FORWARD_CHAR,         key(Capability.key_right));
+        bind(map, BEGINNING_OF_LINE,    key(Capability.key_home));
+        bind(map, END_OF_LINE,          key(Capability.key_end));
+        bind(map, DELETE_CHAR,          key(Capability.key_dc));
+        bind(map, KILL_WHOLE_LINE,      key(Capability.key_dl));
+        bind(map, OVERWRITE_MODE,       key(Capability.key_ic));
+        bind(map, MOUSE,                key(Capability.key_mouse));
+        bind(map, BEGIN_PASTE,          BRACKETED_PASTE_BEGIN);
+        bind(map, FOCUS_IN,             FOCUS_IN_SEQ);
+        bind(map, FOCUS_OUT,            FOCUS_OUT_SEQ);
+    }
+
+    /**
+     * Bind special chars defined by the terminal instead of
+     * the default bindings
+     */
+    private void bindConsoleChars(KeyMap<Binding> keyMap, Attributes attr) {
+        if (attr != null) {
+            rebind(keyMap, BACKWARD_DELETE_CHAR,
+                    del(), (char) attr.getControlChar(ControlChar.VERASE));
+            rebind(keyMap, BACKWARD_KILL_WORD,
+                    ctrl('W'),  (char) attr.getControlChar(ControlChar.VWERASE));
+            rebind(keyMap, KILL_WHOLE_LINE,
+                    ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL));
+            rebind(keyMap, QUOTED_INSERT,
+                    ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT));
+        }
+    }
+
+    private void rebind(KeyMap<Binding> keyMap, String operation, String prevBinding, char newBinding) {
+        if (newBinding > 0 && newBinding < 128) {
+            Reference ref = new Reference(operation);
+            bind(keyMap, SELF_INSERT, prevBinding);
+            keyMap.bind(ref, Character.toString(newBinding));
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import jdk.internal.org.jline.reader.LineReader;
+
+public class ReaderUtils {
+
+    private ReaderUtils() { }
+
+    public static boolean isSet(LineReader reader, LineReader.Option option) {
+        return reader != null && reader.isSet(option);
+    }
+
+    public static String getString(LineReader reader, String name, String def) {
+        Object v = reader != null ? reader.getVariable(name) : null;
+        return v != null ? v.toString() : def;
+    }
+
+    public static boolean getBoolean(LineReader reader, String name, boolean def) {
+        Object v = reader != null ? reader.getVariable(name) : null;
+        if (v instanceof Boolean) {
+            return (Boolean) v;
+        } else if (v != null) {
+            String s = v.toString();
+            return s.isEmpty() || s.equalsIgnoreCase("on")
+                    || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true");
+        }
+        return def;
+    }
+
+    public static int getInt(LineReader reader, String name, int def) {
+        int nb = def;
+        Object v = reader != null ? reader.getVariable(name) : null;
+        if (v instanceof Number) {
+            return ((Number) v).intValue();
+        } else if (v != null) {
+            nb = 0;
+            try {
+                nb = Integer.parseInt(v.toString());
+            } catch (NumberFormatException e) {
+                // Ignore
+            }
+        }
+        return nb;
+    }
+
+    public static long getLong(LineReader reader, String name, long def) {
+        long nb = def;
+        Object v = reader != null ? reader.getVariable(name) : null;
+        if (v instanceof Number) {
+            return ((Number) v).longValue();
+        } else if (v != null) {
+            nb = 0;
+            try {
+                nb = Long.parseLong(v.toString());
+            } catch (NumberFormatException e) {
+                // Ignore
+            }
+        }
+        return nb;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import jdk.internal.org.jline.reader.MaskingCallback;
+
+import java.util.Objects;
+
+/**
+ * Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask.
+ * If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String.
+ */
+public final class SimpleMaskingCallback implements MaskingCallback {
+    private final Character mask;
+
+    public SimpleMaskingCallback(Character mask) {
+        this.mask = Objects.requireNonNull(mask, "mask must be a non null character");
+    }
+
+    @Override
+    public String display(String line) {
+        if (mask.equals(LineReaderImpl.NULL_MASK)) {
+            return "";
+        } else {
+            StringBuilder sb = new StringBuilder(line.length());
+            for (int i = line.length(); i-- > 0;) {
+                sb.append((char) mask);
+            }
+            return sb.toString();
+        }
+    }
+
+    @Override
+    public String history(String line) {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl;
+
+import java.util.function.Consumer;
+
+/**
+ * Simple undo tree.
+ * Note that the first added state can't be undone
+ */
+public class UndoTree<T> {
+
+    private final Consumer<T> state;
+    private final Node parent;
+    private Node current;
+
+    public UndoTree(Consumer<T> s) {
+        state = s;
+        parent = new Node(null);
+        parent.left = parent;
+        clear();
+    }
+
+    public void clear() {
+        current = parent;
+    }
+
+    public void newState(T state) {
+        Node node = new Node(state);
+        current.right = node;
+        node.left = current;
+        current = node;
+    }
+
+    public boolean canUndo() {
+        return current.left != parent;
+    }
+
+    public boolean canRedo() {
+        return current.right != null;
+    }
+
+    public void undo() {
+        if (!canUndo()) {
+            throw new IllegalStateException("Cannot undo.");
+        }
+        current = current.left;
+        state.accept(current.state);
+    }
+
+    public void redo() {
+        if (!canRedo()) {
+            throw new IllegalStateException("Cannot redo.");
+        }
+        current = current.right;
+        state.accept(current.state);
+    }
+
+    private class Node {
+        private final T state;
+        private Node left = null;
+        private Node right = null;
+
+        public Node(T s) {
+            state = s;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.ParsedLine;
+
+/**
+ * Completer which contains multiple completers and aggregates them together.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class AggregateCompleter
+    implements Completer
+{
+    private final Collection<Completer> completers;
+
+    /**
+     * Construct an AggregateCompleter with the given completers.
+     * The completers will be used in the order given.
+     *
+     * @param completers the completers
+     */
+    public AggregateCompleter(final Completer... completers) {
+        this(Arrays.asList(completers));
+    }
+
+    /**
+     * Construct an AggregateCompleter with the given completers.
+     * The completers will be used in the order given.
+     *
+     * @param completers the completers
+     */
+    public AggregateCompleter(Collection<Completer> completers) {
+        assert completers != null;
+        this.completers = completers;
+    }
+
+    /**
+     * Retrieve the collection of completers currently being aggregated.
+     *
+     * @return the aggregated completers
+     */
+    public Collection<Completer> getCompleters() {
+        return completers;
+    }
+
+    /**
+     * Perform a completion operation across all aggregated completers.
+     *
+     * The effect is similar to the following code:
+     * <blockquote><pre>{@code completers.forEach(c -> c.complete(reader, line, candidates));}</pre></blockquote>
+     *
+     * @see Completer#complete(LineReader, ParsedLine, List)
+     */
+    public void complete(LineReader reader, final ParsedLine line, final List<Candidate> candidates) {
+        Objects.requireNonNull(line);
+        Objects.requireNonNull(candidates);
+        completers.forEach(c -> c.complete(reader, line, candidates));
+    }
+
+    /**
+     * @return a string representing the aggregated completers
+     */
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+            "completers=" + completers +
+            '}';
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.ParsedLine;
+
+/**
+ * A {@link Completer} implementation that invokes a child completer using the appropriate <i>separator</i> argument.
+ * This can be used instead of the individual completers having to know about argument parsing semantics.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class ArgumentCompleter implements Completer
+{
+    private final List<Completer> completers = new ArrayList<>();
+
+    private boolean strict = true;
+
+    /**
+     * Create a new completer.
+     *
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final Collection<Completer> completers) {
+        Objects.requireNonNull(completers);
+        this.completers.addAll(completers);
+    }
+
+    /**
+     * Create a new completer.
+     *
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final Completer... completers) {
+        this(Arrays.asList(completers));
+    }
+
+    /**
+     * If true, a completion at argument index N will only succeed
+     * if all the completions from 0-(N-1) also succeed.
+     *
+     * @param strict the strict flag
+     */
+    public void setStrict(final boolean strict) {
+        this.strict = strict;
+    }
+
+    /**
+     * Returns whether a completion at argument index N will success
+     * if all the completions from arguments 0-(N-1) also succeed.
+     *
+     * @return  True if strict.
+     * @since 2.3
+     */
+    public boolean isStrict() {
+        return this.strict;
+    }
+
+    /**
+     * Returns the list of completers used inside this <code>ArgumentCompleter</code>.
+     * @return The list of completers.
+     * @since 2.3
+     */
+    public List<Completer> getCompleters() {
+        return completers;
+    }
+
+    public void complete(LineReader reader, ParsedLine line, final List<Candidate> candidates) {
+        Objects.requireNonNull(line);
+        Objects.requireNonNull(candidates);
+
+        if (line.wordIndex() < 0) {
+            return;
+        }
+
+        List<Completer> completers = getCompleters();
+        Completer completer;
+
+        // if we are beyond the end of the completers, just use the last one
+        if (line.wordIndex() >= completers.size()) {
+            completer = completers.get(completers.size() - 1);
+        }
+        else {
+            completer = completers.get(line.wordIndex());
+        }
+
+        // ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
+        for (int i = 0; isStrict() && (i < line.wordIndex()); i++) {
+            Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i);
+            List<? extends CharSequence> args = line.words();
+            String arg = (args == null || i >= args.size()) ? "" : args.get(i).toString();
+
+            List<Candidate> subCandidates = new LinkedList<>();
+            sub.complete(reader, new ArgumentLine(arg, arg.length()), subCandidates);
+
+            boolean found = false;
+            for (Candidate cand : subCandidates) {
+                if (cand.value().equals(arg)) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                return;
+            }
+        }
+
+        completer.complete(reader, line, candidates);
+    }
+
+    public static class ArgumentLine implements ParsedLine {
+        private final String word;
+        private final int cursor;
+
+        public ArgumentLine(String word, int cursor) {
+            this.word = word;
+            this.cursor = cursor;
+        }
+
+        @Override
+        public String word() {
+            return word;
+        }
+
+        @Override
+        public int wordCursor() {
+            return cursor;
+        }
+
+        @Override
+        public int wordIndex() {
+            return 0;
+        }
+
+        @Override
+        public List<String> words() {
+            return Collections.singletonList(word);
+        }
+
+        @Override
+        public String line() {
+            return word;
+        }
+
+        @Override
+        public int cursor() {
+            return cursor;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.util.Objects;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+
+/**
+ * {@link Completer} for {@link Enum} names.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class EnumCompleter extends StringsCompleter
+{
+    public EnumCompleter(Class<? extends Enum<?>> source) {
+        Objects.requireNonNull(source);
+        for (Enum<?> n : source.getEnumConstants()) {
+            candidates.add(new Candidate(n.name().toLowerCase()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.LineReader.Option;
+import jdk.internal.org.jline.reader.ParsedLine;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.AttributedStringBuilder;
+import jdk.internal.org.jline.utils.AttributedStyle;
+
+/**
+ * A file name completer takes the buffer and issues a list of
+ * potential completions.
+ * <p>
+ * This completer tries to behave as similar as possible to
+ * <i>bash</i>'s file name completion (using GNU readline)
+ * with the following exceptions:
+ * <ul>
+ * <li>Candidates that are directories will end with "/"</li>
+ * <li>Wildcard regular expressions are not evaluated or replaced</li>
+ * <li>The "~" character can be used to represent the user's home,
+ * but it cannot complete to other users' homes, since java does
+ * not provide any way of determining that easily</li>
+ * </ul>
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ * @deprecated use <code>org.jline.builtins.Completers$FileNameCompleter</code> instead
+ */
+@Deprecated
+public class FileNameCompleter implements Completer
+{
+
+    public void complete(LineReader reader, ParsedLine commandLine, final List<Candidate> candidates) {
+        assert commandLine != null;
+        assert candidates != null;
+
+        String buffer = commandLine.word().substring(0, commandLine.wordCursor());
+
+        Path current;
+        String curBuf;
+        String sep = getUserDir().getFileSystem().getSeparator();
+        int lastSep = buffer.lastIndexOf(sep);
+        if (lastSep >= 0) {
+            curBuf = buffer.substring(0, lastSep + 1);
+            if (curBuf.startsWith("~")) {
+                if (curBuf.startsWith("~" + sep)) {
+                    current = getUserHome().resolve(curBuf.substring(2));
+                } else {
+                    current = getUserHome().getParent().resolve(curBuf.substring(1));
+                }
+            } else {
+                current = getUserDir().resolve(curBuf);
+            }
+        } else {
+            curBuf = "";
+            current = getUserDir();
+        }
+        try {
+            Files.newDirectoryStream(current, this::accept).forEach(p -> {
+                String value = curBuf + p.getFileName().toString();
+                if (Files.isDirectory(p)) {
+                    candidates.add(new Candidate(
+                            value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""),
+                            getDisplay(reader.getTerminal(), p),
+                            null, null,
+                            reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null,
+                            null,
+                            false));
+                } else {
+                    candidates.add(new Candidate(value, getDisplay(reader.getTerminal(), p),
+                            null, null, null, null, true));
+                }
+            });
+        } catch (IOException e) {
+            // Ignore
+        }
+    }
+
+    protected boolean accept(Path path) {
+        try {
+            return !Files.isHidden(path);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    protected Path getUserDir() {
+        return Paths.get(System.getProperty("user.dir"));
+    }
+
+    protected Path getUserHome() {
+        return Paths.get(System.getProperty("user.home"));
+    }
+
+    protected String getDisplay(Terminal terminal, Path p) {
+        // TODO: use $LS_COLORS for output
+        String name = p.getFileName().toString();
+        if (Files.isDirectory(p)) {
+            AttributedStringBuilder sb = new AttributedStringBuilder();
+            sb.styled(AttributedStyle.BOLD.foreground(AttributedStyle.RED), name);
+            sb.append("/");
+            name = sb.toAnsi(terminal);
+        } else if (Files.isSymbolicLink(p)) {
+            AttributedStringBuilder sb = new AttributedStringBuilder();
+            sb.styled(AttributedStyle.BOLD.foreground(AttributedStyle.RED), name);
+            sb.append("@");
+            name = sb.toAnsi(terminal);
+        }
+        return name;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.util.List;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.ParsedLine;
+
+/**
+ * Null completer.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public final class NullCompleter
+    implements Completer
+{
+    public static final NullCompleter INSTANCE = new NullCompleter();
+
+    public void complete(LineReader reader, final ParsedLine line, final List<Candidate> candidates) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.completer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.ParsedLine;
+import jdk.internal.org.jline.utils.AttributedString;
+
+/**
+ * Completer for a set of strings.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class StringsCompleter implements Completer
+{
+    protected final Collection<Candidate> candidates = new ArrayList<>();
+
+    public StringsCompleter() {
+    }
+
+    public StringsCompleter(String... strings) {
+        this(Arrays.asList(strings));
+    }
+
+    public StringsCompleter(Iterable<String> strings) {
+        assert strings != null;
+        for (String string : strings) {
+            candidates.add(new Candidate(AttributedString.stripAnsi(string), string, null, null, null, null, true));
+        }
+    }
+
+    public void complete(LineReader reader, final ParsedLine commandLine, final List<Candidate> candidates) {
+        assert commandLine != null;
+        assert candidates != null;
+        candidates.addAll(this.candidates);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 3.
+ *
+ * @since 3.0
+ */
+package jdk.internal.org.jline.reader.impl.completer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.reader.impl.history;
+
+import java.io.*;
+import java.nio.file.*;
+import java.time.Instant;
+import java.util.*;
+
+import jdk.internal.org.jline.reader.History;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.utils.Log;
+
+import static jdk.internal.org.jline.reader.LineReader.HISTORY_IGNORE;
+import static jdk.internal.org.jline.reader.impl.ReaderUtils.*;
+
+/**
+ * {@link History} using a file for persistent backing.
+ * <p>
+ * Implementers should install shutdown hook to call {@link DefaultHistory#save}
+ * to save history to disk.
+ * </p>
+ */
+public class DefaultHistory implements History {
+
+    public static final int DEFAULT_HISTORY_SIZE = 500;
+    public static final int DEFAULT_HISTORY_FILE_SIZE = 10000;
+
+    private final LinkedList<Entry> items = new LinkedList<>();
+
+    private LineReader reader;
+
+    private int lastLoaded = 0;
+    private int nbEntriesInFile = 0;
+    private int offset = 0;
+    private int index = 0;
+
+    public DefaultHistory() {
+    }
+
+    public DefaultHistory(LineReader reader) {
+        attach(reader);
+    }
+
+    private Path getPath() {
+        Object obj = reader != null ? reader.getVariables().get(LineReader.HISTORY_FILE) : null;
+        if (obj instanceof Path) {
+            return (Path) obj;
+        } else if (obj instanceof File) {
+            return ((File) obj).toPath();
+        } else if (obj != null) {
+            return Paths.get(obj.toString());
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void attach(LineReader reader) {
+        if (this.reader != reader) {
+            this.reader = reader;
+            try {
+                load();
+            }
+            catch (IOException e) {
+                Log.warn("Failed to load history", e);
+            }
+        }
+    }
+
+    @Override
+    public void load() throws IOException {
+        Path path = getPath();
+        if (path != null) {
+            try {
+                if (Files.exists(path)) {
+                    Log.trace("Loading history from: ", path);
+                    try (BufferedReader reader = Files.newBufferedReader(path)) {
+                        internalClear();
+                        reader.lines().forEach(line -> addHistoryLine(path, line));
+                        lastLoaded = items.size();
+                        nbEntriesInFile = lastLoaded;
+                        maybeResize();
+                    }
+                }
+            } catch (IOException e) {
+                Log.debug("Failed to load history; clearing", e);
+                internalClear();
+                throw e;
+            }
+        }
+    }
+
+    protected void addHistoryLine(Path path, String line) {
+        if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
+            int idx = line.indexOf(':');
+            if (idx < 0) {
+                throw new IllegalArgumentException("Bad history file syntax! " +
+                        "The history file `" + path + "` may be an older history: " +
+                        "please remove it or use a different history file.");
+            }
+            Instant time = Instant.ofEpochMilli(Long.parseLong(line.substring(0, idx)));
+            String unescaped = unescape(line.substring(idx + 1));
+            internalAdd(time, unescaped);
+        }
+        else {
+            internalAdd(Instant.now(), unescape(line));
+        }
+    }
+
+    @Override
+    public void purge() throws IOException {
+        internalClear();
+        Path path = getPath();
+        if (path != null) {
+            Log.trace("Purging history from: ", path);
+            Files.deleteIfExists(path);
+        }
+    }
+
+    @Override
+    public void save() throws IOException {
+        Path path = getPath();
+        if (path != null) {
+            Log.trace("Saving history to: ", path);
+            Files.createDirectories(path.toAbsolutePath().getParent());
+            // Append new items to the history file
+            try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(),
+              StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
+                for (Entry entry : items.subList(lastLoaded, items.size())) {
+                    if (isPersistable(entry)) {
+                        writer.append(format(entry));
+                    }
+                }
+            }
+            nbEntriesInFile += items.size() - lastLoaded;
+            // If we are over 25% max size, trim history file
+            int max = getInt(reader, LineReader.HISTORY_FILE_SIZE, DEFAULT_HISTORY_FILE_SIZE);
+            if (nbEntriesInFile > max + max / 4) {
+                trimHistory(path, max);
+            }
+        }
+        lastLoaded = items.size();
+    }
+
+    protected void trimHistory(Path path, int max) throws IOException {
+        Log.trace("Trimming history path: ", path);
+        // Load all history entries
+        LinkedList<Entry> allItems = new LinkedList<>();
+        try (BufferedReader reader = Files.newBufferedReader(path)) {
+            reader.lines().forEach(l -> {
+                int idx = l.indexOf(':');
+                Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx)));
+                String line = unescape(l.substring(idx + 1));
+                allItems.add(createEntry(allItems.size(), time, line));
+            });
+        }
+        // Remove duplicates
+        doTrimHistory(allItems, max);
+        // Write history
+        Path temp = Files.createTempFile(path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp");
+        try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) {
+            for (Entry entry : allItems) {
+                writer.append(format(entry));
+            }
+        }
+        Files.move(temp, path, StandardCopyOption.REPLACE_EXISTING);
+        // Keep items in memory
+        internalClear();
+        offset = allItems.get(0).index();
+        items.addAll(allItems);
+        lastLoaded = items.size();
+        nbEntriesInFile = items.size();
+        maybeResize();
+    }
+
+    /**
+     * Create a history entry. Subclasses may override to use their own entry implementations.
+     * @param index index of history entry
+     * @param time entry creation time
+     * @param line the entry text
+     * @return entry object
+     */
+    protected EntryImpl createEntry(int index, Instant time, String line) {
+        return new EntryImpl(index, time, line);
+    }
+
+    private void internalClear() {
+        offset = 0;
+        index = 0;
+        lastLoaded = 0;
+        nbEntriesInFile = 0;
+        items.clear();
+    }
+
+    static void doTrimHistory(List<Entry> allItems, int max) {
+        int idx = 0;
+        while (idx < allItems.size()) {
+            int ridx = allItems.size() - idx - 1;
+            String line = allItems.get(ridx).line().trim();
+            ListIterator<Entry> iterator = allItems.listIterator(ridx);
+            while (iterator.hasPrevious()) {
+                String l = iterator.previous().line();
+                if (line.equals(l.trim())) {
+                    iterator.remove();
+                }
+            }
+            idx++;
+        }
+        while (allItems.size() > max) {
+            allItems.remove(0);
+        }
+    }
+
+    public int size() {
+        return items.size();
+    }
+
+    public boolean isEmpty() {
+        return items.isEmpty();
+    }
+
+    public int index() {
+        return offset + index;
+    }
+
+    public int first() {
+        return offset;
+    }
+
+    public int last() {
+        return offset + items.size() - 1;
+    }
+
+    private String format(Entry entry) {
+        if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
+            return Long.toString(entry.time().toEpochMilli()) + ":" + escape(entry.line()) + "\n";
+        }
+        return escape(entry.line()) + "\n";
+    }
+
+    public String get(final int index) {
+        return items.get(index - offset).line();
+    }
+
+    @Override
+    public void add(Instant time, String line) {
+        Objects.requireNonNull(time);
+        Objects.requireNonNull(line);
+
+        if (getBoolean(reader, LineReader.DISABLE_HISTORY, false)) {
+            return;
+        }
+        if (isSet(reader, LineReader.Option.HISTORY_IGNORE_SPACE) && line.startsWith(" ")) {
+            return;
+        }
+        if (isSet(reader, LineReader.Option.HISTORY_REDUCE_BLANKS)) {
+            line = line.trim();
+        }
+        if (isSet(reader, LineReader.Option.HISTORY_IGNORE_DUPS)) {
+            if (!items.isEmpty() && line.equals(items.getLast().line())) {
+                return;
+            }
+        }
+        if (matchPatterns(getString(reader, HISTORY_IGNORE, ""), line)) {
+            return;
+        }
+        internalAdd(time, line);
+        if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) {
+            try {
+                save();
+            }
+            catch (IOException e) {
+                Log.warn("Failed to save history", e);
+            }
+        }
+    }
+
+    protected boolean matchPatterns(String patterns, String line) {
+        if (patterns == null || patterns.isEmpty()) {
+            return false;
+        }
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < patterns.length(); i++) {
+            char ch = patterns.charAt(i);
+            if (ch == '\\') {
+                ch = patterns.charAt(++i);
+                sb.append(ch);
+            } else if (ch == ':') {
+                sb.append('|');
+            } else if (ch == '*') {
+                sb.append('.').append('*');
+            }
+        }
+        return line.matches(sb.toString());
+    }
+
+    protected void internalAdd(Instant time, String line) {
+        Entry entry = new EntryImpl(offset + items.size(), time, line);
+        items.add(entry);
+        maybeResize();
+    }
+
+    private void maybeResize() {
+        while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) {
+            items.removeFirst();
+            lastLoaded--;
+            offset++;
+        }
+        index = size();
+    }
+
+    public ListIterator<Entry> iterator(int index) {
+        return items.listIterator(index - offset);
+    }
+
+    @Override
+    public Spliterator<Entry> spliterator() {
+        return items.spliterator();
+    }
+
+    protected static class EntryImpl implements Entry {
+
+        private final int index;
+        private final Instant time;
+        private final String line;
+
+        public EntryImpl(int index, Instant time, String line) {
+            this.index = index;
+            this.time = time;
+            this.line = line;
+        }
+
+        public int index() {
+            return index;
+        }
+
+        public Instant time() {
+            return time;
+        }
+
+        public String line() {
+            return line;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%d: %s", index, line);
+        }
+    }
+
+    //
+    // Navigation
+    //
+
+    /**
+     * This moves the history to the last entry. This entry is one position
+     * before the moveToEnd() position.
+     *
+     * @return Returns false if there were no history iterator or the history
+     * index was already at the last entry.
+     */
+    public boolean moveToLast() {
+        int lastEntry = size() - 1;
+        if (lastEntry >= 0 && lastEntry != index) {
+            index = size() - 1;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Move to the specified index in the history
+     */
+    public boolean moveTo(int index) {
+        index -= offset;
+        if (index >= 0 && index < size()) {
+            this.index = index;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Moves the history index to the first entry.
+     *
+     * @return Return false if there are no iterator in the history or if the
+     * history is already at the beginning.
+     */
+    public boolean moveToFirst() {
+        if (size() > 0 && index != 0) {
+            index = 0;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Move to the end of the history buffer. This will be a blank entry, after
+     * all of the other iterator.
+     */
+    public void moveToEnd() {
+        index = size();
+    }
+
+    /**
+     * Return the content of the current buffer.
+     */
+    public String current() {
+        if (index >= size()) {
+            return "";
+        }
+        return items.get(index).line();
+    }
+
+    /**
+     * Move the pointer to the previous element in the buffer.
+     *
+     * @return true if we successfully went to the previous element
+     */
+    public boolean previous() {
+        if (index <= 0) {
+            return false;
+        }
+        index--;
+        return true;
+    }
+
+    /**
+     * Move the pointer to the next element in the buffer.
+     *
+     * @return true if we successfully went to the next element
+     */
+    public boolean next() {
+        if (index >= size()) {
+            return false;
+        }
+        index++;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (Entry e : this) {
+            sb.append(e.toString()).append("\n");
+        }
+        return sb.toString();
+    }
+
+    private static String escape(String s) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                case '\n':
+                    sb.append('\\');
+                    sb.append('n');
+                    break;
+                case '\r':
+                    sb.append('\\');
+                    sb.append('r');
+                    break;
+                case '\\':
+                    sb.append('\\');
+                    sb.append('\\');
+                    break;
+                default:
+                    sb.append(ch);
+                    break;
+            }
+        }
+        return sb.toString();
+    }
+
+    static String unescape(String s) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                case '\\':
+                    ch = s.charAt(++i);
+                    if (ch == 'n') {
+                        sb.append('\n');
+                    } else if (ch == 'r') {
+                        sb.append('\r');
+                    } else {
+                        sb.append(ch);
+                    }
+                    break;
+                default:
+                    sb.append(ch);
+                    break;
+            }
+        }
+        return sb.toString();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 3.
+ *
+ * @since 3.0
+ */
+package jdk.internal.org.jline.reader.impl.history;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 3.
+ *
+ * @since 3.0
+ */
+package jdk.internal.org.jline.reader;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class Attributes {
+
+    /**
+     * Control characters
+     */
+    public enum ControlChar {
+        VEOF,
+        VEOL,
+        VEOL2,
+        VERASE,
+        VWERASE,
+        VKILL,
+        VREPRINT,
+        VINTR,
+        VQUIT,
+        VSUSP,
+        VDSUSP,
+        VSTART,
+        VSTOP,
+        VLNEXT,
+        VDISCARD,
+        VMIN,
+        VTIME,
+        VSTATUS
+    }
+
+    /**
+     * Input flags - software input processing
+     */
+    public enum InputFlag {
+        IGNBRK,       /* ignore BREAK condition */
+        BRKINT,       /* map BREAK to SIGINTR */
+        IGNPAR,       /* ignore (discard) parity errors */
+        PARMRK,       /* mark parity and framing errors */
+        INPCK,        /* enable checking of parity errors */
+        ISTRIP,       /* strip 8th bit off chars */
+        INLCR,        /* map NL into CR */
+        IGNCR,        /* ignore CR */
+        ICRNL,        /* map CR to NL (ala CRMOD) */
+        IXON,         /* enable output flow control */
+        IXOFF,        /* enable input flow control */
+        IXANY,        /* any char will restart after stop */
+        IMAXBEL,      /* ring bell on input queue full */
+        IUTF8         /* maintain state for UTF-8 VERASE */
+    }
+
+    /*
+     * Output flags - software output processing
+     */
+    public enum OutputFlag {
+        OPOST,       /* enable following output processing */
+        ONLCR,       /* map NL to CR-NL (ala CRMOD) */
+        OXTABS,      /* expand tabs to spaces */
+        ONOEOT,      /* discard EOT's (^D) on output) */
+        OCRNL,       /* map CR to NL on output */
+        ONOCR,       /* no CR output at column 0 */
+        ONLRET,      /* NL performs CR function */
+        OFILL,       /* use fill characters for delay */
+        NLDLY,       /* \n delay */
+        TABDLY,      /* horizontal tab delay */
+        CRDLY,       /* \r delay */
+        FFDLY,       /* form feed delay */
+        BSDLY,       /* \b delay */
+        VTDLY,       /* vertical tab delay */
+        OFDEL        /* fill is DEL, else NUL */
+    }
+
+    /*
+     * Control flags - hardware control of terminal
+     */
+    public enum ControlFlag {
+        CIGNORE,          /* ignore control flags */
+        CS5,              /* 5 bits    (pseudo) */
+        CS6,              /* 6 bits */
+        CS7,              /* 7 bits */
+        CS8,              /* 8 bits */
+        CSTOPB,           /* send 2 stop bits */
+        CREAD,            /* enable receiver */
+        PARENB,           /* parity enable */
+        PARODD,           /* odd parity, else even */
+        HUPCL,            /* hang up on last close */
+        CLOCAL,           /* ignore modem status lines */
+        CCTS_OFLOW,       /* CTS flow control of output */
+        CRTS_IFLOW,       /* RTS flow control of input */
+        CDTR_IFLOW,       /* DTR flow control of input */
+        CDSR_OFLOW,       /* DSR flow control of output */
+        CCAR_OFLOW        /* DCD flow control of output */
+    }
+
+    /*
+     * "Local" flags - dumping ground for other state
+     *
+     * Warning: some flags in this structure begin with
+     * the letter "I" and look like they belong in the
+     * input flag.
+     */
+    public enum LocalFlag {
+        ECHOKE,           /* visual erase for line kill */
+        ECHOE,            /* visually erase chars */
+        ECHOK,            /* echo NL after line kill */
+        ECHO,             /* enable echoing */
+        ECHONL,           /* echo NL even if ECHO is off */
+        ECHOPRT,          /* visual erase mode for hardcopy */
+        ECHOCTL,          /* echo control chars as ^(Char) */
+        ISIG,             /* enable signals INTR, QUIT, [D]SUSP */
+        ICANON,           /* canonicalize input lines */
+        ALTWERASE,        /* use alternate WERASE algorithm */
+        IEXTEN,           /* enable DISCARD and LNEXT */
+        EXTPROC,          /* external processing */
+        TOSTOP,           /* stop background jobs from output */
+        FLUSHO,           /* output being flushed (state) */
+        NOKERNINFO,       /* no kernel output from VSTATUS */
+        PENDIN,           /* XXX retype pending input (state) */
+        NOFLSH            /* don't flush after interrupt */
+    }
+
+    final EnumSet<InputFlag> iflag = EnumSet.noneOf(InputFlag.class);
+    final EnumSet<OutputFlag> oflag = EnumSet.noneOf(OutputFlag.class);
+    final EnumSet<ControlFlag> cflag = EnumSet.noneOf(ControlFlag.class);
+    final EnumSet<LocalFlag> lflag = EnumSet.noneOf(LocalFlag.class);
+    final EnumMap<ControlChar, Integer> cchars = new EnumMap<>(ControlChar.class);
+
+    public Attributes() {
+    }
+
+    public Attributes(Attributes attr) {
+        copy(attr);
+    }
+
+    //
+    // Input flags
+    //
+
+    public EnumSet<InputFlag> getInputFlags() {
+        return iflag;
+    }
+
+    public void setInputFlags(EnumSet<InputFlag> flags) {
+        iflag.clear();
+        iflag.addAll(flags);
+    }
+
+    public boolean getInputFlag(InputFlag flag) {
+        return iflag.contains(flag);
+    }
+
+    public void setInputFlags(EnumSet<InputFlag> flags, boolean value) {
+        if (value) {
+            iflag.addAll(flags);
+        } else {
+            iflag.removeAll(flags);
+        }
+    }
+
+    public void setInputFlag(InputFlag flag, boolean value) {
+        if (value) {
+            iflag.add(flag);
+        } else {
+            iflag.remove(flag);
+        }
+    }
+
+    //
+    // Output flags
+    //
+
+    public EnumSet<OutputFlag> getOutputFlags() {
+        return oflag;
+    }
+
+    public void setOutputFlags(EnumSet<OutputFlag> flags) {
+        oflag.clear();
+        oflag.addAll(flags);
+    }
+
+    public boolean getOutputFlag(OutputFlag flag) {
+        return oflag.contains(flag);
+    }
+
+    public void setOutputFlags(EnumSet<OutputFlag> flags, boolean value) {
+        if (value) {
+            oflag.addAll(flags);
+        } else {
+            oflag.removeAll(flags);
+        }
+    }
+
+    public void setOutputFlag(OutputFlag flag, boolean value) {
+        if (value) {
+            oflag.add(flag);
+        } else {
+            oflag.remove(flag);
+        }
+    }
+
+    //
+    // Control flags
+    //
+
+    public EnumSet<ControlFlag> getControlFlags() {
+        return cflag;
+    }
+
+    public void setControlFlags(EnumSet<ControlFlag> flags) {
+        cflag.clear();
+        cflag.addAll(flags);
+    }
+
+    public boolean getControlFlag(ControlFlag flag) {
+        return cflag.contains(flag);
+    }
+
+    public void setControlFlags(EnumSet<ControlFlag> flags, boolean value) {
+        if (value) {
+            cflag.addAll(flags);
+        } else {
+            cflag.removeAll(flags);
+        }
+    }
+
+    public void setControlFlag(ControlFlag flag, boolean value) {
+        if (value) {
+            cflag.add(flag);
+        } else {
+            cflag.remove(flag);
+        }
+    }
+
+    //
+    // Local flags
+    //
+
+    public EnumSet<LocalFlag> getLocalFlags() {
+        return lflag;
+    }
+
+    public void setLocalFlags(EnumSet<LocalFlag> flags) {
+        lflag.clear();
+        lflag.addAll(flags);
+    }
+
+    public boolean getLocalFlag(LocalFlag flag) {
+        return lflag.contains(flag);
+    }
+
+    public void setLocalFlags(EnumSet<LocalFlag> flags, boolean value) {
+        if (value) {
+            lflag.addAll(flags);
+        } else {
+            lflag.removeAll(flags);
+        }
+    }
+
+    public void setLocalFlag(LocalFlag flag, boolean value) {
+        if (value) {
+            lflag.add(flag);
+        } else {
+            lflag.remove(flag);
+        }
+    }
+
+    //
+    // Control chars
+    //
+
+    public EnumMap<ControlChar, Integer> getControlChars() {
+        return cchars;
+    }
+
+    public void setControlChars(EnumMap<ControlChar, Integer> chars) {
+        cchars.clear();
+        cchars.putAll(chars);
+    }
+
+    public int getControlChar(ControlChar c) {
+        Integer v = cchars.get(c);
+        return v != null ? v : -1;
+    }
+
+    public void setControlChar(ControlChar c, int value) {
+        cchars.put(c, value);
+    }
+
+    //
+    // Miscellaneous methods
+    //
+
+    public void copy(Attributes attributes) {
+        setControlFlags(attributes.getControlFlags());
+        setInputFlags(attributes.getInputFlags());
+        setLocalFlags(attributes.getLocalFlags());
+        setOutputFlags(attributes.getOutputFlags());
+        setControlChars(attributes.getControlChars());
+    }
+
+    @Override
+    public String toString() {
+        return "Attributes[" +
+                "lflags: " + append(lflag) + ", " +
+                "iflags: " + append(iflag) + ", " +
+                "oflags: " + append(oflag) + ", " +
+                "cflags: " + append(cflag) + ", " +
+                "cchars: " + append(EnumSet.allOf(ControlChar.class), this::display) +
+                "]";
+    }
+
+    private String display(ControlChar c) {
+        String value;
+        int ch = getControlChar(c);
+        if (c == ControlChar.VMIN || c == ControlChar.VTIME) {
+            value = Integer.toString(ch);
+        } else if (ch < 0) {
+            value = "<undef>";
+        } else if (ch < 32) {
+            value = "^" + (char) (ch + 'A' - 1);
+        } else if (ch == 127) {
+            value = "^?";
+        } else if (ch >= 128) {
+            value = String.format("\\u%04x", ch);
+        } else {
+            value = String.valueOf((char) ch);
+        }
+        return c.name().toLowerCase().substring(1) + "=" + value;
+    }
+
+    private <T extends Enum<T>> String append(EnumSet<T> set) {
+        return append(set, e -> e.name().toLowerCase());
+    }
+
+    private <T extends Enum<T>> String append(EnumSet<T> set, Function<T, String> toString) {
+        return set.stream().map(toString).collect(Collectors.joining(" "));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+/**
+ * Class holding the cursor position.
+ *
+ * @see Terminal#getCursorPosition(java.util.function.IntConsumer)
+ */
+public class Cursor {
+
+    private final int x;
+    private final int y;
+
+    public Cursor(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof Cursor) {
+            Cursor c = (Cursor) o;
+            return x == c.x && y == c.y;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return x * 31 + y;
+    }
+
+    @Override
+    public String toString() {
+        return "Cursor[" + "x=" + x + ", y=" + y + ']';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+import java.util.EnumSet;
+
+public class MouseEvent {
+
+    public enum Type {
+        Released,
+        Pressed,
+        Wheel,
+        Moved,
+        Dragged
+    }
+
+    public enum Button {
+        NoButton,
+        Button1,
+        Button2,
+        Button3,
+        WheelUp,
+        WheelDown
+    }
+
+    public enum Modifier {
+        Shift,
+        Alt,
+        Control
+    }
+
+    private final Type type;
+    private final Button button;
+    private final EnumSet<Modifier> modifiers;
+    private final int x;
+    private final int y;
+
+    public MouseEvent(Type type, Button button, EnumSet<Modifier> modifiers, int x, int y) {
+        this.type = type;
+        this.button = button;
+        this.modifiers = modifiers;
+        this.x = x;
+        this.y = y;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public Button getButton() {
+        return button;
+    }
+
+    public EnumSet<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    @Override
+    public String toString() {
+        return "MouseEvent[" +
+                "type=" + type +
+                ", button=" + button +
+                ", modifiers=" + modifiers +
+                ", x=" + x +
+                ", y=" + y +
+                ']';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+public class Size {
+
+    private int rows;
+    private int cols;
+
+    public Size() {
+    }
+
+    public Size(int columns, int rows) {
+        this();
+        setColumns(columns);
+        setRows(rows);
+    }
+
+    public int getColumns() {
+        return cols;
+    }
+
+    public void setColumns(int columns) {
+        cols = (short) columns;
+    }
+
+    public int getRows() {
+        return rows;
+    }
+
+    public void setRows(int rows) {
+        this.rows = (short) rows;
+    }
+
+    /**
+     * A cursor position combines a row number with a column position.
+     * <p>
+     * Note each row has {@code col+1} different column positions,
+     * including the right margin.
+     * </p>
+     *
+     * @param col the new column
+     * @param row the new row
+     * @return the cursor position
+     */
+    public int cursorPos(int row, int col) {
+        return row * (cols+1) + col;
+    }
+
+    public void copy(Size size) {
+        setColumns(size.getColumns());
+        setRows(size.getRows());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof Size) {
+            Size size = (Size) o;
+            return rows == size.rows && cols == size.cols;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return rows * 31 + cols;
+    }
+
+    @Override
+    public String toString() {
+        return "Size[" + "cols=" + cols + ", rows=" + rows + ']';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import jdk.internal.org.jline.terminal.impl.NativeSignalHandler;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+
+/**
+ * A terminal representing a virtual terminal on the computer.
+ *
+ * Terminals should be closed by calling the {@link #close()} method
+ * in order to restore their original state.
+ */
+public interface Terminal extends Closeable, Flushable {
+
+    /**
+     * Type used for dumb terminals.
+     */
+    String TYPE_DUMB = "dumb";
+    String TYPE_DUMB_COLOR = "dumb-color";
+
+    String getName();
+
+    //
+    // Signal support
+    //
+
+    enum Signal {
+        INT,
+        QUIT,
+        TSTP,
+        CONT,
+        INFO,
+        WINCH
+    }
+
+    interface SignalHandler {
+
+        SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL;
+        SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN;
+
+        void handle(Signal signal);
+    }
+
+    SignalHandler handle(Signal signal, SignalHandler handler);
+
+    void raise(Signal signal);
+
+    //
+    // Input / output
+    //
+
+    /**
+     * Retrieve the <code>Reader</code> for this terminal.
+     * This is the standard way to read input from this terminal.
+     * The reader is non blocking.
+     *
+     * @return The non blocking reader
+     */
+    NonBlockingReader reader();
+
+    /**
+     * Retrieve the <code>Writer</code> for this terminal.
+     * This is the standard way to write to this terminal.
+     *
+     * @return The writer
+     */
+    PrintWriter writer();
+
+    /**
+     * Returns the {@link Charset} that should be used to encode characters
+     * for {@link #input()} and {@link #output()}.
+     *
+     * @return The terminal encoding
+     */
+    Charset encoding();
+
+    /**
+     * Retrieve the input stream for this terminal.
+     * In some rare cases, there may be a need to access the
+     * terminal input stream directly. In the usual cases,
+     * use the {@link #reader()} instead.
+     *
+     * @return The input stream
+     *
+     * @see #reader()
+     */
+    InputStream input();
+
+    /**
+     * Retrieve the output stream for this terminal.
+     * In some rare cases, there may be a need to access the
+     * terminal output stream directly. In the usual cases,
+     * use the {@link #writer()} instead.
+     *
+     * @return The output stream
+     *
+     * @see #writer();
+     */
+    OutputStream output();
+
+    //
+    // Input control
+    //
+
+    /**
+     * Whether this terminal supports {@link #pause()} and {@link #resume()} calls.
+     *
+     * @return whether this terminal supports {@link #pause()} and {@link #resume()} calls.
+     * @see #paused()
+     * @see #pause()
+     * @see #resume()
+     */
+    boolean canPauseResume();
+
+    /**
+     * Stop reading the input stream.
+     *
+     * @see #resume()
+     * @see #paused()
+     */
+    void pause();
+
+    /**
+     * Stop reading the input stream and optionally wait for the underlying threads to finish.
+     *
+     * @param wait <code>true</code> to wait until the terminal is actually paused
+     * @throws InterruptedException if the call has been interrupted
+     */
+    void pause(boolean wait) throws InterruptedException;
+
+    /**
+     * Resume reading the input stream.
+     *
+     * @see #pause()
+     * @see #paused()
+     */
+    void resume();
+
+    /**
+     * Check whether the terminal is currently reading the input stream or not.
+     * In order to process signal as quickly as possible, the terminal need to read
+     * the input stream and buffer it internally so that it can detect specific
+     * characters in the input stream (Ctrl+C, Ctrl+D, etc...) and raise the
+     * appropriate signals.
+     * However, there are some cases where this processing should be disabled, for
+     * example when handing the terminal control to a subprocess.
+     *
+     * @return whether the terminal is currently reading the input stream or not
+     *
+     * @see #pause()
+     * @see #resume()
+     */
+    boolean paused();
+
+    //
+    // Pty settings
+    //
+
+    Attributes enterRawMode();
+
+    boolean echo();
+
+    boolean echo(boolean echo);
+
+    Attributes getAttributes();
+
+    void setAttributes(Attributes attr);
+
+    Size getSize();
+
+    void setSize(Size size);
+
+    default int getWidth() {
+        return getSize().getColumns();
+    }
+
+    default int getHeight() {
+        return getSize().getRows();
+    }
+
+    void flush();
+
+    //
+    // Infocmp capabilities
+    //
+
+    String getType();
+
+    boolean puts(Capability capability, Object... params);
+
+    boolean getBooleanCapability(Capability capability);
+
+    Integer getNumericCapability(Capability capability);
+
+    String getStringCapability(Capability capability);
+
+    //
+    // Cursor support
+    //
+
+    /**
+     * Query the terminal to report the cursor position.
+     *
+     * As the response is read from the input stream, some
+     * characters may be read before the cursor position is actually
+     * read. Those characters can be given back using
+     * <code>org.jline.keymap.BindingReader#runMacro(String)</code>
+     *
+     * @param discarded a consumer receiving discarded characters
+     * @return <code>null</code> if cursor position reporting
+     *                  is not supported or a valid cursor position
+     */
+    Cursor getCursorPosition(IntConsumer discarded);
+
+    //
+    // Mouse support
+    //
+
+    enum MouseTracking {
+        /**
+         * Disable mouse tracking
+         */
+        Off,
+        /**
+         * Track button press and release.
+         */
+        Normal,
+        /**
+         * Also report button-motion events.  Mouse movements are reported if the mouse pointer
+         * has moved to a different character cell.
+         */
+        Button,
+        /**
+         * Report all motions events, even if no mouse button is down.
+         */
+        Any
+    }
+
+    /**
+     * Returns <code>true</code> if the terminal has support for mouse.
+     * @return whether mouse is supported by the terminal
+     * @see #trackMouse(MouseTracking)
+     */
+    boolean hasMouseSupport();
+
+    /**
+     * Change the mouse tracking mouse.
+     * To start mouse tracking, this method must be called with a valid mouse tracking mode.
+     * Mouse events will be reported by writing the {@link Capability#key_mouse} to the input stream.
+     * When this character sequence is detected, the {@link #readMouseEvent()} method can be
+     * called to actually read the corresponding mouse event.
+     *
+     * @param tracking the mouse tracking mode
+     * @return <code>true</code> if mouse tracking is supported
+     */
+    boolean trackMouse(MouseTracking tracking);
+
+    /**
+     * Read a MouseEvent from the terminal input stream.
+     * Such an event must have been detected by scanning the terminal's {@link Capability#key_mouse}
+     * in the stream immediately before reading the event.
+     *
+     * @return the decoded mouse event.
+     * @see #trackMouse(MouseTracking)
+     */
+    MouseEvent readMouseEvent();
+
+    /**
+     * Read a MouseEvent from the given input stream.
+     *
+     * @param reader the input supplier
+     * @return the decoded mouse event
+     */
+    MouseEvent readMouseEvent(IntSupplier reader);
+
+    /**
+     * Returns <code>true</code> if the terminal has support for focus tracking.
+     * @return whether focus tracking is supported by the terminal
+     * @see #trackFocus(boolean)
+     */
+    boolean hasFocusSupport();
+
+    /**
+     * Enable or disable focus tracking mode.
+     * When focus tracking has been activated, each time the terminal grabs the focus,
+     * the string "\33[I" will be sent to the input stream and each time the focus is lost,
+     * the string "\33[O" will be sent to the input stream.
+     *
+     * @param tracking whether the focus tracking mode should be enabled or not
+     * @return <code>true</code> if focus tracking is supported
+     */
+    boolean trackFocus(boolean tracking);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.function.Function;
+
+import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal;
+import jdk.internal.org.jline.terminal.impl.DumbTerminal;
+import jdk.internal.org.jline.terminal.impl.ExecPty;
+import jdk.internal.org.jline.terminal.impl.ExternalTerminal;
+import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
+import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
+import jdk.internal.org.jline.terminal.spi.JansiSupport;
+import jdk.internal.org.jline.terminal.spi.JnaSupport;
+import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.utils.Log;
+import jdk.internal.org.jline.utils.OSUtils;
+
+import static jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal.TYPE_WINDOWS;
+import static jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal.TYPE_WINDOWS_256_COLOR;
+
+/**
+ * Builder class to create terminals.
+ */
+public final class TerminalBuilder {
+
+    //
+    // System properties
+    //
+
+    public static final String PROP_ENCODING = "org.jline.terminal.encoding";
+    public static final String PROP_CODEPAGE = "org.jline.terminal.codepage";
+    public static final String PROP_TYPE = "org.jline.terminal.type";
+    public static final String PROP_JNA = "org.jline.terminal.jna";
+    public static final String PROP_JANSI = "org.jline.terminal.jansi";
+    public static final String PROP_EXEC = "org.jline.terminal.exec";
+    public static final String PROP_DUMB = "org.jline.terminal.dumb";
+    public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color";
+
+    //
+    // Other system properties controlling various jline parts
+    //
+
+    public static final String PROP_NON_BLOCKING_READS = "org.jline.terminal.pty.nonBlockingReads";
+    public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance";
+    public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset";
+
+    /**
+     * Returns the default system terminal.
+     * Terminals should be closed properly using the {@link Terminal#close()}
+     * method in order to restore the original terminal state.
+     *
+     * <p>
+     * This call is equivalent to:
+     * <code>builder().build()</code>
+     * </p>
+     *
+     * @return the default system terminal
+     * @throws IOException if an error occurs
+     */
+    public static Terminal terminal() throws IOException {
+        return builder().build();
+    }
+
+    /**
+     * Creates a new terminal builder instance.
+     *
+     * @return a builder
+     */
+    public static TerminalBuilder builder() {
+        return new TerminalBuilder();
+    }
+
+    private String name;
+    private InputStream in;
+    private OutputStream out;
+    private String type;
+    private Charset encoding;
+    private int codepage;
+    private Boolean system;
+    private Boolean jna;
+    private Boolean jansi;
+    private Boolean exec;
+    private Boolean dumb;
+    private Attributes attributes;
+    private Size size;
+    private boolean nativeSignals = false;
+    private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL;
+    private boolean paused = false;
+    private Function<InputStream, InputStream> inputStreamWrapper = in -> in;
+
+    private TerminalBuilder() {
+    }
+
+    public TerminalBuilder name(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public TerminalBuilder streams(InputStream in, OutputStream out) {
+        this.in = in;
+        this.out = out;
+        return this;
+    }
+
+    public TerminalBuilder system(boolean system) {
+        this.system = system;
+        return this;
+    }
+
+    public TerminalBuilder jna(boolean jna) {
+        this.jna = jna;
+        return this;
+    }
+
+    public TerminalBuilder jansi(boolean jansi) {
+        this.jansi = jansi;
+        return this;
+    }
+
+    public TerminalBuilder exec(boolean exec) {
+        this.exec = exec;
+        return this;
+    }
+
+    public TerminalBuilder dumb(boolean dumb) {
+        this.dumb = dumb;
+        return this;
+    }
+
+    public TerminalBuilder type(String type) {
+        this.type = type;
+        return this;
+    }
+
+    /**
+     * Set the encoding to use for reading/writing from the console.
+     * If {@code null} (the default value), JLine will automatically select
+     * a {@link Charset}, usually the default system encoding. However,
+     * on some platforms (e.g. Windows) it may use a different one depending
+     * on the {@link Terminal} implementation.
+     *
+     * <p>Use {@link Terminal#encoding()} to get the {@link Charset} that
+     * should be used for a {@link Terminal}.</p>
+     *
+     * @param encoding The encoding to use or null to automatically select one
+     * @return The builder
+     * @throws UnsupportedCharsetException If the given encoding is not supported
+     * @see Terminal#encoding()
+     */
+    public TerminalBuilder encoding(String encoding) throws UnsupportedCharsetException {
+        return encoding(encoding != null ? Charset.forName(encoding) : null);
+    }
+
+    /**
+     * Set the {@link Charset} to use for reading/writing from the console.
+     * If {@code null} (the default value), JLine will automatically select
+     * a {@link Charset}, usually the default system encoding. However,
+     * on some platforms (e.g. Windows) it may use a different one depending
+     * on the {@link Terminal} implementation.
+     *
+     * <p>Use {@link Terminal#encoding()} to get the {@link Charset} that
+     * should be used to read/write from a {@link Terminal}.</p>
+     *
+     * @param encoding The encoding to use or null to automatically select one
+     * @return The builder
+     * @see Terminal#encoding()
+     */
+    public TerminalBuilder encoding(Charset encoding) {
+        this.encoding = encoding;
+        return this;
+    }
+
+    /**
+     * @param codepage the codepage
+     * @return The builder
+     * @deprecated JLine now writes Unicode output independently from the selected
+     *   code page. Using this option will only make it emulate the selected code
+     *   page for {@link Terminal#input()} and {@link Terminal#output()}.
+     */
+    @Deprecated
+    public TerminalBuilder codepage(int codepage) {
+        this.codepage = codepage;
+        return this;
+    }
+
+    /**
+     * Attributes to use when creating a non system terminal,
+     * i.e. when the builder has been given the input and
+     * outut streams using the {@link #streams(InputStream, OutputStream)} method
+     * or when {@link #system(boolean)} has been explicitely called with
+     * <code>false</code>.
+     *
+     * @param attributes the attributes to use
+     * @return The builder
+     * @see #size(Size)
+     * @see #system(boolean)
+     */
+    public TerminalBuilder attributes(Attributes attributes) {
+        this.attributes = attributes;
+        return this;
+    }
+
+    /**
+     * Initial size to use when creating a non system terminal,
+     * i.e. when the builder has been given the input and
+     * outut streams using the {@link #streams(InputStream, OutputStream)} method
+     * or when {@link #system(boolean)} has been explicitely called with
+     * <code>false</code>.
+     *
+     * @param size the initial size
+     * @return The builder
+     * @see #attributes(Attributes)
+     * @see #system(boolean)
+     */
+    public TerminalBuilder size(Size size) {
+        this.size = size;
+        return this;
+    }
+
+    public TerminalBuilder nativeSignals(boolean nativeSignals) {
+        this.nativeSignals = nativeSignals;
+        return this;
+    }
+
+    public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) {
+        this.signalHandler = signalHandler;
+        return this;
+    }
+
+    /**
+     * Initial paused state of the terminal (defaults to false).
+     * By default, the terminal is started, but in some cases,
+     * one might want to make sure the input stream is not consumed
+     * before needed, in which case the terminal needs to be created
+     * in a paused state.
+     * @param paused the initial paused state
+     * @return The builder
+     * @see Terminal#pause()
+     */
+    public TerminalBuilder paused(boolean paused) {
+        this.paused = paused;
+        return this;
+    }
+
+    public TerminalBuilder inputStreamWrapper(Function<InputStream, InputStream> wrapper) {
+        this.inputStreamWrapper = wrapper;
+        return this;
+    }
+
+    public Terminal build() throws IOException {
+        Terminal terminal = doBuild();
+        Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName());
+        if (terminal instanceof AbstractPosixTerminal) {
+            Log.debug(() -> "Using pty " + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName());
+        }
+        return terminal;
+    }
+
+    private Terminal doBuild() throws IOException {
+        String name = this.name;
+        if (name == null) {
+            name = "JLine terminal";
+        }
+        Charset encoding = this.encoding;
+        if (encoding == null) {
+            String charsetName = System.getProperty(PROP_ENCODING);
+            if (charsetName != null && Charset.isSupported(charsetName)) {
+                encoding = Charset.forName(charsetName);
+            }
+        }
+        int codepage = this.codepage;
+        if (codepage <= 0) {
+            String str = System.getProperty(PROP_CODEPAGE);
+            if (str != null) {
+                codepage = Integer.parseInt(str);
+            }
+        }
+        String type = this.type;
+        if (type == null) {
+            type = System.getProperty(PROP_TYPE);
+        }
+        if (type == null) {
+            type = System.getenv("TERM");
+        }
+        Boolean jna = this.jna;
+        if (jna == null) {
+            jna = getBoolean(PROP_JNA, true);
+        }
+        Boolean jansi = this.jansi;
+        if (jansi == null) {
+            jansi = getBoolean(PROP_JANSI, true);
+        }
+        Boolean exec = this.exec;
+        if (exec == null) {
+            exec = getBoolean(PROP_EXEC, true);
+        }
+        Boolean dumb = this.dumb;
+        if (dumb == null) {
+            dumb = getBoolean(PROP_DUMB, null);
+        }
+        if ((system != null && system) || (system == null && in == null && out == null)) {
+            if (attributes != null || size != null) {
+                Log.warn("Attributes and size fields are ignored when creating a system terminal");
+            }
+            IllegalStateException exception = new IllegalStateException("Unable to create a system terminal");
+            if (OSUtils.IS_WINDOWS) {
+                boolean cygwinTerm = "cygwin".equals(System.getenv("TERM"));
+                boolean ansiPassThrough = OSUtils.IS_CONEMU;
+                //
+                // Cygwin support
+                //
+                if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && exec && !cygwinTerm) {
+                    try {
+                        Pty pty = ExecPty.current();
+                        // Cygwin defaults to XTERM, but actually supports 256 colors,
+                        // so if the value comes from the environment, change it to xterm-256color
+                        if ("xterm".equals(type) && this.type == null && System.getProperty(PROP_TYPE) == null) {
+                            type = "xterm-256color";
+                        }
+                        return new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler);
+                    } catch (IOException e) {
+                        // Ignore if not a tty
+                        Log.debug("Error creating EXEC based terminal: ", e.getMessage(), e);
+                        exception.addSuppressed(e);
+                    }
+                }
+                if (jna) {
+                    try {
+                        return load(JnaSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused, inputStreamWrapper);
+                    } catch (Throwable t) {
+                        Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
+                        exception.addSuppressed(t);
+                    }
+                }
+                if (jansi) {
+                    try {
+                        return load(JansiSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
+                    } catch (Throwable t) {
+                        Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
+                        exception.addSuppressed(t);
+                    }
+                }
+            } else {
+                if (jna) {
+                    try {
+                        Pty pty = load(JnaSupport.class).current();
+                        return new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler);
+                    } catch (Throwable t) {
+                        // ignore
+                        Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
+                        exception.addSuppressed(t);
+                    }
+                }
+                if (jansi) {
+                    try {
+                        Pty pty = load(JansiSupport.class).current();
+                        return new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler);
+                    } catch (Throwable t) {
+                        Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
+                        exception.addSuppressed(t);
+                    }
+                }
+                if (exec) {
+                    try {
+                        Pty pty = ExecPty.current();
+                        return new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler);
+                    } catch (Throwable t) {
+                        // Ignore if not a tty
+                        Log.debug("Error creating EXEC based terminal: ", t.getMessage(), t);
+                        exception.addSuppressed(t);
+                    }
+                }
+            }
+            if (dumb == null || dumb) {
+                // forced colored dumb terminal
+                boolean color = getBoolean(PROP_DUMB_COLOR, false);
+                // detect emacs using the env variable
+                if (!color) {
+                    color = System.getenv("INSIDE_EMACS") != null;
+                }
+                // detect Intellij Idea
+                if (!color) {
+                    String command = getParentProcessCommand();
+                    color = command != null && command.contains("idea");
+                }
+                if (!color && dumb == null) {
+                    if (Log.isDebugEnabled()) {
+                        Log.warn("Creating a dumb terminal", exception);
+                    } else {
+                        Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)");
+                    }
+                }
+                return new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB,
+                        new FileInputStream(FileDescriptor.in),
+                        new FileOutputStream(FileDescriptor.out),
+                        encoding, signalHandler);
+            } else {
+                throw exception;
+            }
+        } else {
+            if (jna) {
+                try {
+                    Pty pty = load(JnaSupport.class).open(attributes, size);
+                    return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
+                } catch (Throwable t) {
+                    Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
+                }
+            }
+            if (jansi) {
+                try {
+                    Pty pty = load(JansiSupport.class).open(attributes, size);
+                    return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
+                } catch (Throwable t) {
+                    Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
+                }
+            }
+            Terminal terminal = new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused);
+            if (attributes != null) {
+                terminal.setAttributes(attributes);
+            }
+            if (size != null) {
+                terminal.setSize(size);
+            }
+            return terminal;
+        }
+    }
+
+    private static String getParentProcessCommand() {
+        try {
+            Class<?> phClass = Class.forName("java.lang.ProcessHandle");
+            Object current = phClass.getMethod("current").invoke(null);
+            Object parent = ((Optional<?>) phClass.getMethod("parent").invoke(current)).orElse(null);
+            Method infoMethod = phClass.getMethod("info");
+            Object info = infoMethod.invoke(parent);
+            Object command = ((Optional<?>) infoMethod.getReturnType().getMethod("command").invoke(info)).orElse(null);
+            return (String) command;
+        } catch (Throwable t) {
+            return null;
+        }
+    }
+
+    private static Boolean getBoolean(String name, Boolean def) {
+        try {
+            String str = System.getProperty(name);
+            if (str != null) {
+                return Boolean.parseBoolean(str);
+            }
+        } catch (IllegalArgumentException | NullPointerException e) {
+        }
+        return def;
+    }
+
+    private <S> S load(Class<S> clazz) {
+        return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Objects;
+import java.util.function.IntConsumer;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Cursor;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.spi.Pty;
+
+public abstract class AbstractPosixTerminal extends AbstractTerminal {
+
+    protected final Pty pty;
+    protected final Attributes originalAttributes;
+
+    public AbstractPosixTerminal(String name, String type, Pty pty) throws IOException {
+        this(name, type, pty, null, SignalHandler.SIG_DFL);
+    }
+
+    public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) throws IOException {
+        super(name, type, encoding, signalHandler);
+        Objects.requireNonNull(pty);
+        this.pty = pty;
+        this.originalAttributes = this.pty.getAttr();
+    }
+
+    public Pty getPty() {
+        return pty;
+    }
+
+    public Attributes getAttributes() {
+        try {
+            return pty.getAttr();
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public void setAttributes(Attributes attr) {
+        try {
+            pty.setAttr(attr);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public Size getSize() {
+        try {
+            return pty.getSize();
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public void setSize(Size size) {
+        try {
+            pty.setSize(size);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public void close() throws IOException {
+        super.close();
+        pty.setAttr(originalAttributes);
+        pty.close();
+    }
+
+    @Override
+    public Cursor getCursorPosition(IntConsumer discarded) {
+        return CursorSupport.getCursorPosition(this, discarded);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,97 @@
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.utils.NonBlockingInputStream;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS;
+
+public abstract class AbstractPty implements Pty {
+
+    private Attributes current;
+
+    @Override
+    public void setAttr(Attributes attr) throws IOException {
+        current = new Attributes(attr);
+        doSetAttr(attr);
+    }
+
+    @Override
+    public InputStream getSlaveInput() throws IOException {
+        InputStream si = doGetSlaveInput();
+        if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) {
+            return new PtyInputStream(si);
+        } else {
+            return si;
+        }
+    }
+
+    protected abstract void doSetAttr(Attributes attr) throws IOException;
+
+    protected abstract InputStream doGetSlaveInput() throws IOException;
+
+    protected void checkInterrupted() throws InterruptedIOException {
+        if (Thread.interrupted()) {
+            throw new InterruptedIOException();
+        }
+    }
+
+    class PtyInputStream extends NonBlockingInputStream {
+        final InputStream in;
+        int c = 0;
+
+        PtyInputStream(InputStream in) {
+            this.in = in;
+        }
+
+        @Override
+        public int read(long timeout, boolean isPeek) throws IOException {
+            checkInterrupted();
+            if (c != 0) {
+                int r = c;
+                if (!isPeek) {
+                    c = 0;
+                }
+                return r;
+            } else {
+                setNonBlocking();
+                long start = System.currentTimeMillis();
+                while (true) {
+                    int r = in.read();
+                    if (r >= 0) {
+                        if (isPeek) {
+                            c = r;
+                        }
+                        return r;
+                    }
+                    checkInterrupted();
+                    long cur = System.currentTimeMillis();
+                    if (timeout > 0 && cur - start > timeout) {
+                        return NonBlockingInputStream.READ_EXPIRED;
+                    }
+                }
+            }
+        }
+
+        private void setNonBlocking() {
+            if (current == null
+                    || current.getControlChar(Attributes.ControlChar.VMIN) != 0
+                    || current.getControlChar(Attributes.ControlChar.VTIME) != 1) {
+                try {
+                    Attributes attr = getAttr();
+                    attr.setControlChar(Attributes.ControlChar.VMIN, 0);
+                    attr.setControlChar(Attributes.ControlChar.VTIME, 1);
+                    setAttr(attr);
+                } catch (IOException e) {
+                    throw new IOError(e);
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.nio.charset.Charset;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Attributes.InputFlag;
+import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
+import jdk.internal.org.jline.terminal.Cursor;
+import jdk.internal.org.jline.terminal.MouseEvent;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.Curses;
+import jdk.internal.org.jline.utils.InfoCmp;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+import jdk.internal.org.jline.utils.Log;
+import jdk.internal.org.jline.utils.Status;
+
+public abstract class AbstractTerminal implements Terminal {
+
+    protected final String name;
+    protected final String type;
+    protected final Charset encoding;
+    protected final Map<Signal, SignalHandler> handlers = new HashMap<>();
+    protected final Set<Capability> bools = new HashSet<>();
+    protected final Map<Capability, Integer> ints = new HashMap<>();
+    protected final Map<Capability, String> strings = new HashMap<>();
+    protected Status status;
+
+    public AbstractTerminal(String name, String type) throws IOException {
+        this(name, type, null, SignalHandler.SIG_DFL);
+    }
+
+    public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException {
+        this.name = name;
+        this.type = type;
+        this.encoding = encoding != null ? encoding : Charset.defaultCharset();
+        for (Signal signal : Signal.values()) {
+            handlers.put(signal, signalHandler);
+        }
+    }
+
+    public Status getStatus() {
+        return getStatus(true);
+    }
+
+    public Status getStatus(boolean create) {
+        if (status == null && create) {
+            status = new Status(this);
+        }
+        return status;
+    }
+
+    public SignalHandler handle(Signal signal, SignalHandler handler) {
+        Objects.requireNonNull(signal);
+        Objects.requireNonNull(handler);
+        return handlers.put(signal, handler);
+    }
+
+    public void raise(Signal signal) {
+        Objects.requireNonNull(signal);
+        SignalHandler handler = handlers.get(signal);
+        if (handler != SignalHandler.SIG_DFL && handler != SignalHandler.SIG_IGN) {
+            handler.handle(signal);
+        }
+        if (status != null && signal == Signal.WINCH) {
+            status.resize();
+        }
+    }
+
+    public void close() throws IOException {
+        if (status != null) {
+            status.update(null);
+            flush();
+        }
+    }
+
+    protected void echoSignal(Signal signal) {
+        ControlChar cc = null;
+        switch (signal) {
+            case INT:
+                cc = ControlChar.VINTR;
+                break;
+            case QUIT:
+                cc = ControlChar.VQUIT;
+                break;
+            case TSTP:
+                cc = ControlChar.VSUSP;
+                break;
+        }
+        if (cc != null) {
+            int vcc = getAttributes().getControlChar(cc);
+            if (vcc > 0 && vcc < 32) {
+                writer().write(new char[]{'^', (char) (vcc + '@')}, 0, 2);
+            }
+        }
+    }
+
+    public Attributes enterRawMode() {
+        Attributes prvAttr = getAttributes();
+        Attributes newAttr = new Attributes(prvAttr);
+        newAttr.setLocalFlags(EnumSet.of(LocalFlag.ICANON, LocalFlag.ECHO, LocalFlag.IEXTEN), false);
+        newAttr.setInputFlags(EnumSet.of(InputFlag.IXON, InputFlag.ICRNL, InputFlag.INLCR), false);
+        newAttr.setControlChar(ControlChar.VMIN, 0);
+        newAttr.setControlChar(ControlChar.VTIME, 1);
+        setAttributes(newAttr);
+        return prvAttr;
+    }
+
+    public boolean echo() {
+        return getAttributes().getLocalFlag(LocalFlag.ECHO);
+    }
+
+    public boolean echo(boolean echo) {
+        Attributes attr = getAttributes();
+        boolean prev = attr.getLocalFlag(LocalFlag.ECHO);
+        if (prev != echo) {
+            attr.setLocalFlag(LocalFlag.ECHO, echo);
+            setAttributes(attr);
+        }
+        return prev;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getKind() {
+        return getClass().getSimpleName();
+    }
+
+    @Override
+    public Charset encoding() {
+        return this.encoding;
+    }
+
+    public void flush() {
+        writer().flush();
+    }
+
+    public boolean puts(Capability capability, Object... params) {
+        String str = getStringCapability(capability);
+        if (str == null) {
+            return false;
+        }
+        Curses.tputs(writer(), str, params);
+        return true;
+    }
+
+    public boolean getBooleanCapability(Capability capability) {
+        return bools.contains(capability);
+    }
+
+    public Integer getNumericCapability(Capability capability) {
+        return ints.get(capability);
+    }
+
+    public String getStringCapability(Capability capability) {
+        return strings.get(capability);
+    }
+
+    protected void parseInfoCmp() {
+        String capabilities = null;
+        if (type != null) {
+            try {
+                capabilities = InfoCmp.getInfoCmp(type);
+            } catch (Exception e) {
+                Log.warn("Unable to retrieve infocmp for type " + type, e);
+            }
+        }
+        if (capabilities == null) {
+            capabilities = InfoCmp.getLoadedInfoCmp("ansi");
+        }
+        InfoCmp.parseInfoCmp(capabilities, bools, ints, strings);
+    }
+
+    @Override
+    public Cursor getCursorPosition(IntConsumer discarded) {
+        return null;
+    }
+
+    private MouseEvent lastMouseEvent = new MouseEvent(
+                MouseEvent.Type.Moved, MouseEvent.Button.NoButton,
+                EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0);
+
+    @Override
+    public boolean hasMouseSupport() {
+        return MouseSupport.hasMouseSupport(this);
+    }
+
+    @Override
+    public boolean trackMouse(MouseTracking tracking) {
+        return MouseSupport.trackMouse(this, tracking);
+    }
+
+    @Override
+    public MouseEvent readMouseEvent() {
+        return lastMouseEvent = MouseSupport.readMouse(this, lastMouseEvent);
+    }
+
+    @Override
+    public MouseEvent readMouseEvent(IntSupplier reader) {
+        return lastMouseEvent = MouseSupport.readMouse(reader, lastMouseEvent);
+    }
+
+    @Override
+    public boolean hasFocusSupport() {
+        return type != null && type.startsWith("xterm");
+    }
+
+    @Override
+    public boolean trackFocus(boolean tracking) {
+        if (hasFocusSupport()) {
+            writer().write(tracking ? "\033[?1004h" : "\033[?1004l");
+            writer().flush();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected void checkInterrupted() throws InterruptedIOException {
+        if (Thread.interrupted()) {
+            throw new InterruptedIOException();
+        }
+    }
+
+    @Override
+    public boolean canPauseResume() {
+        return false;
+    }
+
+    @Override
+    public void pause() {
+    }
+
+    @Override
+    public void pause(boolean wait) throws InterruptedException {
+    }
+
+    @Override
+    public void resume() {
+    }
+
+    @Override
+    public boolean paused() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public abstract class AbstractWindowsConsoleWriter extends Writer {
+
+    protected abstract void writeConsole(char[] text, int len) throws IOException;
+
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        char[] text = cbuf;
+        if (off != 0) {
+            text = new char[len];
+            System.arraycopy(cbuf, off, text, 0, len);
+        }
+
+        synchronized (this.lock) {
+            writeConsole(text, len);
+        }
+    }
+
+    @Override
+    public void flush() {
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.utils.Curses;
+import jdk.internal.org.jline.utils.InfoCmp;
+import jdk.internal.org.jline.utils.Log;
+import jdk.internal.org.jline.utils.NonBlocking;
+import jdk.internal.org.jline.utils.NonBlockingInputStream;
+import jdk.internal.org.jline.utils.NonBlockingPumpReader;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+import jdk.internal.org.jline.utils.ShutdownHooks;
+import jdk.internal.org.jline.utils.Signals;
+import jdk.internal.org.jline.utils.WriterOutputStream;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * The AbstractWindowsTerminal is used as the base class for windows terminal.
+ * Due to windows limitations, mostly the missing support for ansi sequences,
+ * the only way to create a correct terminal is to use the windows api to set
+ * character attributes, move the cursor, erasing, etc...
+ *
+ * UTF-8 support is also lacking in windows and the code page supposed to
+ * emulate UTF-8 is a bit broken. In order to work around this broken
+ * code page, windows api WriteConsoleW is used directly.  This means that
+ * the writer() becomes the primary output, while the output() is bridged
+ * to the writer() using a WriterOutputStream wrapper.
+ */
+public abstract class AbstractWindowsTerminal extends AbstractTerminal {
+
+    public static final String TYPE_WINDOWS = "windows";
+    public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
+    public static final String TYPE_WINDOWS_VTP = "windows-vtp";
+
+    public static final int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
+
+    private static final int UTF8_CODE_PAGE = 65001;
+
+    protected static final int ENABLE_PROCESSED_INPUT = 0x0001;
+    protected static final int ENABLE_LINE_INPUT      = 0x0002;
+    protected static final int ENABLE_ECHO_INPUT      = 0x0004;
+    protected static final int ENABLE_WINDOW_INPUT    = 0x0008;
+    protected static final int ENABLE_MOUSE_INPUT     = 0x0010;
+    protected static final int ENABLE_INSERT_MODE     = 0x0020;
+    protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040;
+
+    protected final Writer slaveInputPipe;
+    protected final InputStream input;
+    protected final OutputStream output;
+    protected final NonBlockingReader reader;
+    protected final PrintWriter writer;
+    protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
+    protected final ShutdownHooks.Task closer;
+    protected final Attributes attributes = new Attributes();
+    protected final int originalConsoleMode;
+
+    protected final Object lock = new Object();
+    protected boolean paused = true;
+    protected Thread pump;
+
+    protected MouseTracking tracking = MouseTracking.Off;
+    protected boolean focusTracking = false;
+    private volatile boolean closing;
+
+    public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
+        super(name, type, selectCharset(encoding, codepage), signalHandler);
+        NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
+        this.slaveInputPipe = reader.getWriter();
+        this.reader = reader;
+        this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding()));
+        this.writer = new PrintWriter(writer);
+        this.output = new WriterOutputStream(writer, encoding());
+        parseInfoCmp();
+        // Attributes
+        originalConsoleMode = getConsoleMode();
+        attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
+        attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C'));
+        attributes.setControlChar(Attributes.ControlChar.VEOF,  ctrl('D'));
+        attributes.setControlChar(Attributes.ControlChar.VSUSP, ctrl('Z'));
+        // Handle signals
+        if (nativeSignals) {
+            for (final Signal signal : Signal.values()) {
+                if (signalHandler == SignalHandler.SIG_DFL) {
+                    nativeHandlers.put(signal, Signals.registerDefault(signal.name()));
+                } else {
+                    nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
+                }
+            }
+        }
+        closer = this::close;
+        ShutdownHooks.add(closer);
+        // ConEMU extended fonts support
+        if (TYPE_WINDOWS_256_COLOR.equals(getType())
+                && !Boolean.getBoolean("org.jline.terminal.conemu.disable-activate")) {
+            writer.write("\u001b[9999E");
+            writer.flush();
+        }
+    }
+
+    private static Charset selectCharset(Charset encoding, int codepage) {
+        if (encoding != null) {
+            return encoding;
+        }
+
+        if (codepage >= 0) {
+            return getCodepageCharset(codepage);
+        }
+
+        // Use UTF-8 as default
+        return StandardCharsets.UTF_8;
+    }
+
+    private static Charset getCodepageCharset(int codepage) {
+        //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
+        if (codepage == UTF8_CODE_PAGE) {
+            return StandardCharsets.UTF_8;
+        }
+        String charsetMS = "ms" + codepage;
+        if (Charset.isSupported(charsetMS)) {
+            return Charset.forName(charsetMS);
+        }
+        String charsetCP = "cp" + codepage;
+        if (Charset.isSupported(charsetCP)) {
+            return Charset.forName(charsetCP);
+        }
+        return Charset.defaultCharset();
+    }
+
+    @Override
+    public SignalHandler handle(Signal signal, SignalHandler handler) {
+        SignalHandler prev = super.handle(signal, handler);
+        if (prev != handler) {
+            if (handler == SignalHandler.SIG_DFL) {
+                Signals.registerDefault(signal.name());
+            } else {
+                Signals.register(signal.name(), () -> raise(signal));
+            }
+        }
+        return prev;
+    }
+
+    public NonBlockingReader reader() {
+        return reader;
+    }
+
+    public PrintWriter writer() {
+        return writer;
+    }
+
+    @Override
+    public InputStream input() {
+        return input;
+    }
+
+    @Override
+    public OutputStream output() {
+        return output;
+    }
+
+    public Attributes getAttributes() {
+        int mode = getConsoleMode();
+        if ((mode & ENABLE_ECHO_INPUT) != 0) {
+            attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true);
+        }
+        if ((mode & ENABLE_LINE_INPUT) != 0) {
+            attributes.setLocalFlag(Attributes.LocalFlag.ICANON, true);
+        }
+        return new Attributes(attributes);
+    }
+
+    public void setAttributes(Attributes attr) {
+        attributes.copy(attr);
+        updateConsoleMode();
+    }
+
+    protected void updateConsoleMode() {
+        int mode = ENABLE_WINDOW_INPUT;
+        if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) {
+            mode |= ENABLE_ECHO_INPUT;
+        }
+        if (attributes.getLocalFlag(Attributes.LocalFlag.ICANON)) {
+            mode |= ENABLE_LINE_INPUT;
+        }
+        if (tracking != MouseTracking.Off) {
+            mode |= ENABLE_MOUSE_INPUT;
+        }
+        setConsoleMode(mode);
+    }
+
+    protected int ctrl(char key) {
+        return (Character.toUpperCase(key) & 0x1f);
+    }
+
+    public void setSize(Size size) {
+        throw new UnsupportedOperationException("Can not resize windows terminal");
+    }
+
+    public void close() throws IOException {
+        super.close();
+        closing = true;
+        pump.interrupt();
+        ShutdownHooks.remove(closer);
+        for (Map.Entry<Signal, Object> entry : nativeHandlers.entrySet()) {
+            Signals.unregister(entry.getKey().name(), entry.getValue());
+        }
+        reader.close();
+        writer.close();
+        setConsoleMode(originalConsoleMode);
+    }
+
+    static final int SHIFT_FLAG = 0x01;
+    static final int ALT_FLAG =   0x02;
+    static final int CTRL_FLAG =  0x04;
+
+    static final int RIGHT_ALT_PRESSED =   0x0001;
+    static final int LEFT_ALT_PRESSED =    0x0002;
+    static final int RIGHT_CTRL_PRESSED =  0x0004;
+    static final int LEFT_CTRL_PRESSED =   0x0008;
+    static final int SHIFT_PRESSED =       0x0010;
+    static final int NUMLOCK_ON =          0x0020;
+    static final int SCROLLLOCK_ON =       0x0040;
+    static final int CAPSLOCK_ON =         0x0080;
+
+    protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) throws IOException {
+        final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0;
+        final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0;
+        final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0;
+        // key down event
+        if (isKeyDown && ch != '\3') {
+            // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
+            // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
+            if (ch != 0
+                    && (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED))
+                        == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) {
+                processInputChar(ch);
+            } else {
+                final String keySeq = getEscapeSequence(virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0));
+                if (keySeq != null) {
+                    for (char c : keySeq.toCharArray()) {
+                        processInputChar(c);
+                    }
+                    return;
+                }
+                /* uchar value in Windows when CTRL is pressed:
+                 * 1). Ctrl +  <0x41 to 0x5e>      : uchar=<keyCode> - 'A' + 1
+                 * 2). Ctrl + Backspace(0x08)      : uchar=0x7f
+                 * 3). Ctrl + Enter(0x0d)          : uchar=0x0a
+                 * 4). Ctrl + Space(0x20)          : uchar=0x20
+                 * 5). Ctrl + <Other key>          : uchar=0
+                 * 6). Ctrl + Alt + <Any key>      : uchar=0
+                */
+                if (ch > 0) {
+                    if (isAlt) {
+                        processInputChar('\033');
+                    }
+                    if (isCtrl && ch != ' ' && ch != '\n' && ch != 0x7f) {
+                        processInputChar((char) (ch == '?' ? 0x7f : Character.toUpperCase(ch) & 0x1f));
+                    } else if (isCtrl && ch == '\n') {
+                        //simulate Alt-Enter:
+                        processInputChar('\033');
+                        processInputChar('\r');
+                    } else {
+                        processInputChar(ch);
+                    }
+                } else if (isCtrl) { //Handles the ctrl key events(uchar=0)
+                    if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') {
+                        ch = (char) (virtualKeyCode - 0x40);
+                    } else if (virtualKeyCode == 191) { //?
+                        ch = 127;
+                    }
+                    if (ch > 0) {
+                        if (isAlt) {
+                            processInputChar('\033');
+                        }
+                        processInputChar(ch);
+                    }
+                }
+            }
+        } else if (isKeyDown && ch == '\3') {
+            processInputChar('\3');
+        }
+        // key up event
+        else {
+            // support ALT+NumPad input method
+            if (virtualKeyCode == 0x12 /*VK_MENU ALT key*/ && ch > 0) {
+                processInputChar(ch);  // no such combination in Windows
+            }
+        }
+    }
+
+    protected String getEscapeSequence(short keyCode, int keyState) {
+        // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
+        // TODO: numpad keys, modifiers
+        String escapeSequence = null;
+        switch (keyCode) {
+            case 0x08: // VK_BACK BackSpace
+                escapeSequence = (keyState & ALT_FLAG) > 0 ? "\\E^H" : getRawSequence(InfoCmp.Capability.key_backspace);
+                break;
+            case 0x09:
+                escapeSequence = (keyState & SHIFT_FLAG) > 0 ? getRawSequence(InfoCmp.Capability.key_btab) : null;
+                break;
+            case 0x21: // VK_PRIOR PageUp
+                escapeSequence = getRawSequence(InfoCmp.Capability.key_ppage);
+                break;
+            case 0x22: // VK_NEXT PageDown
+                escapeSequence = getRawSequence(InfoCmp.Capability.key_npage);
+                break;
+            case 0x23: // VK_END
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dF" : getRawSequence(InfoCmp.Capability.key_end);
+                break;
+            case 0x24: // VK_HOME
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dH" : getRawSequence(InfoCmp.Capability.key_home);
+                break;
+            case 0x25: // VK_LEFT
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dD" : getRawSequence(InfoCmp.Capability.key_left);
+                break;
+            case 0x26: // VK_UP
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dA" : getRawSequence(InfoCmp.Capability.key_up);
+                break;
+            case 0x27: // VK_RIGHT
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dC" : getRawSequence(InfoCmp.Capability.key_right);
+                break;
+            case 0x28: // VK_DOWN
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dB" : getRawSequence(InfoCmp.Capability.key_down);
+                break;
+            case 0x2D: // VK_INSERT
+                escapeSequence = getRawSequence(InfoCmp.Capability.key_ic);
+                break;
+            case 0x2E: // VK_DELETE
+                escapeSequence = getRawSequence(InfoCmp.Capability.key_dc);
+                break;
+            case 0x70: // VK_F1
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dP" : getRawSequence(InfoCmp.Capability.key_f1);
+                break;
+            case 0x71: // VK_F2
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dQ" : getRawSequence(InfoCmp.Capability.key_f2);
+                break;
+            case 0x72: // VK_F3
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dR" : getRawSequence(InfoCmp.Capability.key_f3);
+                break;
+            case 0x73: // VK_F4
+                escapeSequence = keyState > 0 ? "\\E[1;%p1%dS" : getRawSequence(InfoCmp.Capability.key_f4);
+                break;
+            case 0x74: // VK_F5
+                escapeSequence = keyState > 0 ? "\\E[15;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f5);
+                break;
+            case 0x75: // VK_F6
+                escapeSequence = keyState > 0 ? "\\E[17;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f6);
+                break;
+            case 0x76: // VK_F7
+                escapeSequence = keyState > 0 ? "\\E[18;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f7);
+                break;
+            case 0x77: // VK_F8
+                escapeSequence = keyState > 0 ? "\\E[19;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f8);
+                break;
+            case 0x78: // VK_F9
+                escapeSequence = keyState > 0 ? "\\E[20;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f9);
+                break;
+            case 0x79: // VK_F10
+                escapeSequence = keyState > 0 ? "\\E[21;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f10);
+                break;
+            case 0x7A: // VK_F11
+                escapeSequence = keyState > 0 ? "\\E[23;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f11);
+                break;
+            case 0x7B: // VK_F12
+                escapeSequence = keyState > 0 ? "\\E[24;%p1%d~" : getRawSequence(InfoCmp.Capability.key_f12);
+                break;
+            case 0x5D: // VK_CLOSE_BRACKET(Menu key)
+            case 0x5B: // VK_OPEN_BRACKET(Window key)
+            default:
+                return null;
+        }
+        return Curses.tputs(escapeSequence, keyState + 1);
+    }
+
+    protected String getRawSequence(InfoCmp.Capability cap) {
+        return strings.get(cap);
+    }
+
+    @Override
+    public boolean hasFocusSupport() {
+        return true;
+    }
+
+    @Override
+    public boolean trackFocus(boolean tracking) {
+        focusTracking = tracking;
+        return true;
+    }
+
+    @Override
+    public boolean canPauseResume() {
+        return true;
+    }
+
+    @Override
+    public void pause() {
+        synchronized (lock) {
+            paused = true;
+        }
+    }
+
+    @Override
+    public void pause(boolean wait) throws InterruptedException {
+        Thread p;
+        synchronized (lock) {
+            paused = true;
+            p = pump;
+        }
+        if (p != null) {
+            p.interrupt();
+            p.join();
+        }
+    }
+
+    @Override
+    public void resume() {
+        synchronized (lock) {
+            paused = false;
+            if (pump == null) {
+                pump = new Thread(this::pump, "WindowsStreamPump");
+                pump.setDaemon(true);
+                pump.start();
+            }
+        }
+    }
+
+    @Override
+    public boolean paused() {
+        synchronized (lock) {
+            return paused;
+        }
+    }
+
+    protected void pump() {
+        try {
+            while (!closing) {
+                synchronized (lock) {
+                    if (paused) {
+                        pump = null;
+                        break;
+                    }
+                }
+                if (processConsoleInput()) {
+                    slaveInputPipe.flush();
+                }
+            }
+        } catch (IOException e) {
+            if (!closing) {
+                Log.warn("Error in WindowsStreamPump", e);
+                try {
+                    close();
+                } catch (IOException e1) {
+                    Log.warn("Error closing terminal", e);
+                }
+            }
+        } finally {
+            synchronized (lock) {
+                pump = null;
+            }
+        }
+    }
+
+    public void processInputChar(char c) throws IOException {
+        if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) {
+            if (c == attributes.getControlChar(Attributes.ControlChar.VINTR)) {
+                raise(Signal.INT);
+                return;
+            } else if (c == attributes.getControlChar(Attributes.ControlChar.VQUIT)) {
+                raise(Signal.QUIT);
+                return;
+            } else if (c == attributes.getControlChar(Attributes.ControlChar.VSUSP)) {
+                raise(Signal.TSTP);
+                return;
+            } else if (c == attributes.getControlChar(Attributes.ControlChar.VSTATUS)) {
+                raise(Signal.INFO);
+            }
+        }
+        if (c == '\r') {
+            if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
+                return;
+            }
+            if (attributes.getInputFlag(Attributes.InputFlag.ICRNL)) {
+                c = '\n';
+            }
+        } else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) {
+            c = '\r';
+        }
+//        if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) {
+//            processOutputByte(c);
+//            masterOutput.flush();
+//        }
+        slaveInputPipe.write(c);
+    }
+
+    @Override
+    public boolean trackMouse(MouseTracking tracking) {
+        this.tracking = tracking;
+        updateConsoleMode();
+        return true;
+    }
+
+    protected abstract int getConsoleOutputCP();
+
+    protected abstract int getConsoleMode();
+
+    protected abstract void setConsoleMode(int mode);
+
+    /**
+     * Read a single input event from the input buffer and process it.
+     *
+     * @return true if new input was generated from the event
+     * @throws IOException if anything wrong happens
+     */
+    protected abstract boolean processConsoleInput() throws IOException;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.Cursor;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.Curses;
+import jdk.internal.org.jline.utils.InfoCmp;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CursorSupport {
+
+    public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) {
+        try {
+            String u6 = terminal.getStringCapability(InfoCmp.Capability.user6);
+            String u7 = terminal.getStringCapability(InfoCmp.Capability.user7);
+            if (u6 == null || u7 == null) {
+                return null;
+            }
+            // Prepare parser
+            boolean inc1 = false;
+            StringBuilder patb = new StringBuilder();
+            int index = 0;
+            while (index < u6.length()) {
+                char ch;
+                switch (ch = u6.charAt(index++)) {
+                    case '\\':
+                        switch (u6.charAt(index++)) {
+                            case 'e':
+                            case 'E':
+                                patb.append("\\x1b");
+                                break;
+                            default:
+                                throw new IllegalArgumentException();
+                        }
+                        break;
+                    case '%':
+                        ch = u6.charAt(index++);
+                        switch (ch) {
+                            case '%':
+                                patb.append('%');
+                                break;
+                            case 'i':
+                                inc1 = true;
+                                break;
+                            case 'd':
+                                patb.append("([0-9]+)");
+                                break;
+                            default:
+                                throw new IllegalArgumentException();
+                        }
+                        break;
+                    default:
+                        switch (ch) {
+                            case '[':
+                                patb.append('\\');
+                                break;
+                        }
+                        patb.append(ch);
+                        break;
+                }
+            }
+            Pattern pattern = Pattern.compile(patb.toString());
+            // Output cursor position request
+            Curses.tputs(terminal.writer(), u7);
+            terminal.flush();
+            StringBuilder sb = new StringBuilder();
+            int start = 0;
+            while (true) {
+                int c = terminal.reader().read();
+                if (c < 0) {
+                    return null;
+                }
+                sb.append((char) c);
+                Matcher matcher = pattern.matcher(sb.substring(start));
+                if (matcher.matches()) {
+                    int y = Integer.parseInt(matcher.group(1));
+                    int x = Integer.parseInt(matcher.group(2));
+                    if (inc1) {
+                        x--;
+                        y--;
+                    }
+                    if (discarded != null) {
+                        for (int i = 0; i < start; i++) {
+                            discarded.accept(sb.charAt(i));
+                        }
+                    }
+                    return new Cursor(x, y);
+                } else if (!matcher.hitEnd()) {
+                    start++;
+                }
+            }
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.utils.NonBlocking;
+import jdk.internal.org.jline.utils.NonBlockingInputStream;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+
+public class DumbTerminal extends AbstractTerminal {
+
+    private final NonBlockingInputStream input;
+    private final OutputStream output;
+    private final NonBlockingReader reader;
+    private final PrintWriter writer;
+    private final Attributes attributes;
+    private final Size size;
+
+    public DumbTerminal(InputStream in, OutputStream out) throws IOException {
+        this(TYPE_DUMB, TYPE_DUMB, in, out, null);
+    }
+
+    public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding) throws IOException {
+        this(name, type, in, out, encoding, SignalHandler.SIG_DFL);
+    }
+
+    public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException {
+        super(name, type, encoding, signalHandler);
+        NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), in);
+        this.input = new NonBlockingInputStream() {
+            @Override
+            public int read(long timeout, boolean isPeek) throws IOException {
+                for (;;) {
+                    int c = nbis.read(timeout, isPeek);
+                    if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) {
+                        if (c == attributes.getControlChar(ControlChar.VINTR)) {
+                            raise(Signal.INT);
+                            continue;
+                        } else if (c == attributes.getControlChar(ControlChar.VQUIT)) {
+                            raise(Signal.QUIT);
+                            continue;
+                        } else if (c == attributes.getControlChar(ControlChar.VSUSP)) {
+                            raise(Signal.TSTP);
+                            continue;
+                        } else if (c == attributes.getControlChar(ControlChar.VSTATUS)) {
+                            raise(Signal.INFO);
+                            continue;
+                        }
+                    }
+                    if (c == '\r') {
+                        if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
+                            continue;
+                        }
+                        if (attributes.getInputFlag(Attributes.InputFlag.ICRNL)) {
+                            c = '\n';
+                        }
+                    } else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) {
+                        c = '\r';
+                    }
+                    return c;
+                }
+            }
+        };
+        this.output = out;
+        this.reader = NonBlocking.nonBlocking(getName(), input, encoding());
+        this.writer = new PrintWriter(new OutputStreamWriter(output, encoding()));
+        this.attributes = new Attributes();
+        this.attributes.setControlChar(ControlChar.VERASE,  (char) 127);
+        this.attributes.setControlChar(ControlChar.VWERASE, (char) 23);
+        this.attributes.setControlChar(ControlChar.VKILL,   (char) 21);
+        this.attributes.setControlChar(ControlChar.VLNEXT,  (char) 22);
+        this.size = new Size();
+        parseInfoCmp();
+    }
+
+    public NonBlockingReader reader() {
+        return reader;
+    }
+
+    public PrintWriter writer() {
+        return writer;
+    }
+
+    @Override
+    public InputStream input() {
+        return input;
+    }
+
+    @Override
+    public OutputStream output() {
+        return output;
+    }
+
+    public Attributes getAttributes() {
+        Attributes attr = new Attributes();
+        attr.copy(attributes);
+        return attr;
+    }
+
+    public void setAttributes(Attributes attr) {
+        attributes.copy(attr);
+    }
+
+    public Size getSize() {
+        Size sz = new Size();
+        sz.copy(size);
+        return sz;
+    }
+
+    public void setSize(Size sz) {
+        size.copy(sz);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileDescriptor;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Attributes.ControlFlag;
+import jdk.internal.org.jline.terminal.Attributes.InputFlag;
+import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
+import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.utils.OSUtils;
+
+import static jdk.internal.org.jline.utils.ExecHelper.exec;
+
+public class ExecPty extends AbstractPty implements Pty {
+
+    private final String name;
+    private final boolean system;
+
+    public static Pty current() throws IOException {
+        try {
+            String result = exec(true, OSUtils.TTY_COMMAND);
+            return new ExecPty(result.trim(), true);
+        } catch (IOException e) {
+            throw new IOException("Not a tty", e);
+        }
+    }
+
+    protected ExecPty(String name, boolean system) {
+        this.name = name;
+        this.system = system;
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public InputStream getMasterInput() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public OutputStream getMasterOutput() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected InputStream doGetSlaveInput() throws IOException {
+        return system
+                ? new FileInputStream(FileDescriptor.in)
+                : new FileInputStream(getName());
+    }
+
+    @Override
+    public OutputStream getSlaveOutput() throws IOException {
+        return system
+                ? new FileOutputStream(FileDescriptor.out)
+                : new FileOutputStream(getName());
+    }
+
+    @Override
+    public Attributes getAttr() throws IOException {
+        String cfg = doGetConfig();
+        return doGetAttr(cfg);
+    }
+
+    @Override
+    protected void doSetAttr(Attributes attr) throws IOException {
+        List<String> commands = getFlagsToSet(attr, getAttr());
+        if (!commands.isEmpty()) {
+            commands.add(0, OSUtils.STTY_COMMAND);
+            if (!system) {
+                commands.add(1, OSUtils.STTY_F_OPTION);
+                commands.add(2, getName());
+            }
+            try {
+                exec(system, commands.toArray(new String[commands.size()]));
+            } catch (IOException e) {
+                // Handle partial failures with GNU stty, see #97
+                if (e.toString().contains("unable to perform all requested operations")) {
+                    commands = getFlagsToSet(attr, getAttr());
+                    if (!commands.isEmpty()) {
+                        throw new IOException("Could not set the following flags: " + String.join(", ", commands), e);
+                    }
+                } else {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    protected List<String> getFlagsToSet(Attributes attr, Attributes current) {
+        List<String> commands = new ArrayList<>();
+        for (InputFlag flag : InputFlag.values()) {
+            if (attr.getInputFlag(flag) != current.getInputFlag(flag)) {
+                commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
+            }
+        }
+        for (OutputFlag flag : OutputFlag.values()) {
+            if (attr.getOutputFlag(flag) != current.getOutputFlag(flag)) {
+                commands.add((attr.getOutputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
+            }
+        }
+        for (ControlFlag flag : ControlFlag.values()) {
+            if (attr.getControlFlag(flag) != current.getControlFlag(flag)) {
+                commands.add((attr.getControlFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
+            }
+        }
+        for (LocalFlag flag : LocalFlag.values()) {
+            if (attr.getLocalFlag(flag) != current.getLocalFlag(flag)) {
+                commands.add((attr.getLocalFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
+            }
+        }
+        String undef = System.getProperty("os.name").toLowerCase().startsWith("hp") ? "^-" : "undef";
+        for (ControlChar cchar : ControlChar.values()) {
+            if (attr.getControlChar(cchar) != current.getControlChar(cchar)) {
+                String str = "";
+                int v = attr.getControlChar(cchar);
+                commands.add(cchar.name().toLowerCase().substring(1));
+                if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) {
+                    commands.add(Integer.toBinaryString(v));
+                }
+                else if (v == 0) {
+                    commands.add(undef);
+                }
+                else {
+                    if (v >= 128) {
+                        v -= 128;
+                        str += "M-";
+                    }
+                    if (v < 32 || v == 127) {
+                        v ^= 0x40;
+                        str += "^";
+                    }
+                    str += (char) v;
+                    commands.add(str);
+                }
+            }
+        }
+        return commands;
+    }
+
+    @Override
+    public Size getSize() throws IOException {
+        String cfg = doGetConfig();
+        return doGetSize(cfg);
+    }
+
+    protected String doGetConfig() throws IOException {
+        return system
+                ? exec(true,  OSUtils.STTY_COMMAND, "-a")
+                : exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a");
+    }
+
+    static Attributes doGetAttr(String cfg) throws IOException {
+        Attributes attributes = new Attributes();
+        for (InputFlag flag : InputFlag.values()) {
+            Boolean value = doGetFlag(cfg, flag);
+            if (value != null) {
+                attributes.setInputFlag(flag, value);
+            }
+        }
+        for (OutputFlag flag : OutputFlag.values()) {
+            Boolean value = doGetFlag(cfg, flag);
+            if (value != null) {
+                attributes.setOutputFlag(flag, value);
+            }
+        }
+        for (ControlFlag flag : ControlFlag.values()) {
+            Boolean value = doGetFlag(cfg, flag);
+            if (value != null) {
+                attributes.setControlFlag(flag, value);
+            }
+        }
+        for (LocalFlag flag : LocalFlag.values()) {
+            Boolean value = doGetFlag(cfg, flag);
+            if (value != null) {
+                attributes.setLocalFlag(flag, value);
+            }
+        }
+        for (ControlChar cchar : ControlChar.values()) {
+            String name = cchar.name().toLowerCase().substring(1);
+            if ("reprint".endsWith(name)) {
+                name = "(?:reprint|rprnt)";
+            }
+            Matcher matcher = Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg);
+            if (matcher.find()) {
+                attributes.setControlChar(cchar, parseControlChar(matcher.group(1).toUpperCase()));
+            }
+        }
+        return attributes;
+    }
+
+    private static Boolean doGetFlag(String cfg, Enum<?> flag) {
+        Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)").matcher(cfg);
+        return matcher.find() ? !matcher.group(1).startsWith("-") : null;
+    }
+
+    static int parseControlChar(String str) {
+        // undef
+        if ("<UNDEF>".equals(str)) {
+            return -1;
+        }
+        // del
+        if ("DEL".equalsIgnoreCase(str)) {
+            return 127;
+        }
+        // octal
+        if (str.charAt(0) == '0') {
+            return Integer.parseInt(str, 8);
+        }
+        // decimal
+        if (str.charAt(0) >= '1' && str.charAt(0) <= '9') {
+            return Integer.parseInt(str, 10);
+        }
+        // control char
+        if (str.charAt(0) == '^') {
+            if (str.charAt(1) == '?') {
+                return 127;
+            } else {
+                return str.charAt(1) - 64;
+            }
+        } else if (str.charAt(0) == 'M' && str.charAt(1) == '-') {
+            if (str.charAt(2) == '^') {
+                if (str.charAt(3) == '?') {
+                    return 127 + 128;
+                } else {
+                    return str.charAt(3) - 64 + 128;
+                }
+            } else {
+                return str.charAt(2) + 128;
+            }
+        } else {
+            return str.charAt(0);
+        }
+    }
+
+    static Size doGetSize(String cfg) throws IOException {
+        return new Size(doGetInt("columns", cfg), doGetInt("rows", cfg));
+    }
+
+    static int doGetInt(String name, String cfg) throws IOException {
+        String[] patterns = new String[] {
+                "\\b([0-9]+)\\s+" + name + "\\b",
+                "\\b" + name + "\\s+([0-9]+)\\b",
+                "\\b" + name + "\\s*=\\s*([0-9]+)\\b"
+        };
+        for (String pattern : patterns) {
+            Matcher matcher = Pattern.compile(pattern).matcher(cfg);
+            if (matcher.find()) {
+                return Integer.parseInt(matcher.group(1));
+            }
+        }
+        throw new IOException("Unable to parse " + name);
+    }
+
+    @Override
+    public void setSize(Size size) throws IOException {
+        if (system) {
+            exec(true,
+                 OSUtils.STTY_COMMAND,
+                 "columns", Integer.toString(size.getColumns()),
+                 "rows", Integer.toString(size.getRows()));
+        } else {
+            exec(false,
+                 OSUtils.STTY_COMMAND,
+                 OSUtils.STTY_F_OPTION, getName(),
+                 "columns", Integer.toString(size.getColumns()),
+                 "rows", Integer.toString(size.getRows()));
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ExecPty[" + getName() + (system ? ", system]" : "]");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.Cursor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.IntConsumer;
+
+/**
+ * Console implementation with embedded line disciplined.
+ *
+ * This terminal is well-suited for supporting incoming external
+ * connections, such as from the network (through telnet, ssh,
+ * or any kind of protocol).
+ * The terminal will start consuming the input in a separate thread
+ * to generate interruption events.
+ *
+ * @see LineDisciplineTerminal
+ */
+public class ExternalTerminal extends LineDisciplineTerminal {
+
+    protected final AtomicBoolean closed = new AtomicBoolean();
+    protected final InputStream masterInput;
+    protected final Object lock = new Object();
+    protected boolean paused = true;
+    protected Thread pumpThread;
+
+    public ExternalTerminal(String name, String type,
+                            InputStream masterInput,
+                            OutputStream masterOutput,
+                            Charset encoding) throws IOException {
+        this(name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL);
+    }
+
+    public ExternalTerminal(String name, String type,
+                            InputStream masterInput,
+                            OutputStream masterOutput,
+                            Charset encoding,
+                            SignalHandler signalHandler) throws IOException {
+        this(name, type, masterInput, masterOutput, encoding, signalHandler, false);
+    }
+
+    public ExternalTerminal(String name, String type,
+                            InputStream masterInput,
+                            OutputStream masterOutput,
+                            Charset encoding,
+                            SignalHandler signalHandler,
+                            boolean paused) throws IOException {
+        super(name, type, masterOutput, encoding, signalHandler);
+        this.masterInput = masterInput;
+        if (!paused) {
+            resume();
+        }
+    }
+
+    public void close() throws IOException {
+        if (closed.compareAndSet(false, true)) {
+            pause();
+            super.close();
+        }
+    }
+
+    @Override
+    public boolean canPauseResume() {
+        return true;
+    }
+
+    @Override
+    public void pause() {
+        synchronized (lock) {
+            paused = true;
+        }
+    }
+
+    @Override
+    public void pause(boolean wait) throws InterruptedException {
+        Thread p;
+        synchronized (lock) {
+            paused = true;
+            p = pumpThread;
+        }
+        if (p != null) {
+            p.interrupt();
+            p.join();
+        }
+    }
+
+    @Override
+    public void resume() {
+        synchronized (lock) {
+            paused = false;
+            if (pumpThread == null) {
+                pumpThread = new Thread(this::pump, toString() + " input pump thread");
+                pumpThread.setDaemon(true);
+                pumpThread.start();
+            }
+        }
+    }
+
+    @Override
+    public boolean paused() {
+        synchronized (lock) {
+            return paused;
+        }
+    }
+
+    public void pump() {
+        try {
+            byte[] buf = new byte[1024];
+            while (true) {
+                int c = masterInput.read(buf);
+                if (c >= 0) {
+                    processInputBytes(buf, 0, c);
+                }
+                if (c < 0 || closed.get()) {
+                    break;
+                }
+                synchronized (lock) {
+                    if (paused) {
+                        pumpThread = null;
+                        return;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            processIOException(e);
+        } finally {
+            synchronized (lock) {
+                pumpThread = null;
+            }
+        }
+        try {
+            slaveInput.close();
+        } catch (IOException e) {
+            // ignore
+        }
+    }
+
+    @Override
+    public Cursor getCursorPosition(IntConsumer discarded) {
+        return CursorSupport.getCursorPosition(this, discarded);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.util.Objects;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Attributes.InputFlag;
+import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
+import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.NonBlocking;
+import jdk.internal.org.jline.utils.NonBlockingPumpInputStream;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+
+/**
+ * Abstract terminal with support for line discipline.
+ * The {@link Terminal} interface represents the slave
+ * side of a PTY, but implementations derived from this class
+ * will handle both the slave and master side of things.
+ *
+ * In order to correctly handle line discipline, the terminal
+ * needs to read the input in advance in order to raise the
+ * signals as fast as possible.
+ * For example, when the user hits Ctrl+C, we can't wait until
+ * the application consumes all the read events.
+ * The same applies to echoing, when enabled, as the echoing
+ * has to happen as soon as the user hit the keyboard, and not
+ * only when the application running in the terminal processes
+ * the input.
+ */
+public class LineDisciplineTerminal extends AbstractTerminal {
+
+    private static final String DEFAULT_TERMINAL_ATTRIBUTES =
+                    "speed 9600 baud; 24 rows; 80 columns;\n" +
+                    "lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl\n" +
+                    "\t-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo\n" +
+                    "\t-extproc\n" +
+                    "iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8\n" +
+                    "\t-ignbrk brkint -inpck -ignpar -parmrk\n" +
+                    "oflags: opost onlcr -oxtabs -onocr -onlret\n" +
+                    "cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow\n" +
+                    "\t-dtrflow -mdmbuf\n" +
+                    "cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;\n" +
+                    "\teol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;\n" +
+                    "\tmin = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;\n" +
+                    "\tstop = ^S; susp = ^Z; time = 0; werase = ^W;\n";
+
+    private static final int PIPE_SIZE = 1024;
+
+    /*
+     * Master output stream
+     */
+    protected final OutputStream masterOutput;
+
+    /*
+     * Slave input pipe write side
+     */
+    protected final OutputStream slaveInputPipe;
+
+    /*
+     * Slave streams
+     */
+    protected final NonBlockingPumpInputStream slaveInput;
+    protected final NonBlockingReader slaveReader;
+    protected final PrintWriter slaveWriter;
+    protected final OutputStream slaveOutput;
+
+    /**
+     * Console data
+     */
+    protected final Attributes attributes;
+    protected final Size size;
+
+    public LineDisciplineTerminal(String name,
+                                  String type,
+                                  OutputStream masterOutput,
+                                  Charset encoding) throws IOException {
+        this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL);
+    }
+
+    public LineDisciplineTerminal(String name,
+                                  String type,
+                                  OutputStream masterOutput,
+                                  Charset encoding,
+                                  SignalHandler signalHandler) throws IOException {
+        super(name, type, encoding, signalHandler);
+        NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE);
+        this.slaveInputPipe = input.getOutputStream();
+        this.slaveInput = input;
+        this.slaveReader = NonBlocking.nonBlocking(getName(), slaveInput, encoding());
+        this.slaveOutput = new FilteringOutputStream();
+        this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding()));
+        this.masterOutput = masterOutput;
+        this.attributes = ExecPty.doGetAttr(DEFAULT_TERMINAL_ATTRIBUTES);
+        this.size = new Size(160, 50);
+        parseInfoCmp();
+    }
+
+    public NonBlockingReader reader() {
+        return slaveReader;
+    }
+
+    public PrintWriter writer() {
+        return slaveWriter;
+    }
+
+    @Override
+    public InputStream input() {
+        return slaveInput;
+    }
+
+    @Override
+    public OutputStream output() {
+        return slaveOutput;
+    }
+
+    public Attributes getAttributes() {
+        Attributes attr = new Attributes();
+        attr.copy(attributes);
+        return attr;
+    }
+
+    public void setAttributes(Attributes attr) {
+        attributes.copy(attr);
+    }
+
+    public Size getSize() {
+        Size sz = new Size();
+        sz.copy(size);
+        return sz;
+    }
+
+    public void setSize(Size sz) {
+        size.copy(sz);
+    }
+
+   @Override
+    public void raise(Signal signal) {
+       Objects.requireNonNull(signal);
+        // Do not call clear() atm as this can cause
+        // deadlock between reading / writing threads
+        // TODO: any way to fix that ?
+        /*
+        if (!attributes.getLocalFlag(LocalFlag.NOFLSH)) {
+            try {
+                slaveReader.clear();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+        */
+        echoSignal(signal);
+        super.raise(signal);
+    }
+
+    /**
+     * Master input processing.
+     * All data coming to the terminal should be provided
+     * using this method.
+     *
+     * @param c the input byte
+     * @throws IOException if anything wrong happens
+     */
+    public void processInputByte(int c) throws IOException {
+        boolean flushOut = doProcessInputByte(c);
+        slaveInputPipe.flush();
+        if (flushOut) {
+            masterOutput.flush();
+        }
+    }
+
+    public void processInputBytes(byte[] input) throws IOException {
+        processInputBytes(input, 0, input.length);
+    }
+
+    public void processInputBytes(byte[] input, int offset, int length) throws IOException {
+        boolean flushOut = false;
+        for (int i = 0; i < length; i++) {
+            flushOut |= doProcessInputByte(input[offset + i]);
+        }
+        slaveInputPipe.flush();
+        if (flushOut) {
+            masterOutput.flush();
+        }
+    }
+
+    protected boolean doProcessInputByte(int c) throws IOException {
+        if (attributes.getLocalFlag(LocalFlag.ISIG)) {
+            if (c == attributes.getControlChar(ControlChar.VINTR)) {
+                raise(Signal.INT);
+                return false;
+            } else if (c == attributes.getControlChar(ControlChar.VQUIT)) {
+                raise(Signal.QUIT);
+                return false;
+            } else if (c == attributes.getControlChar(ControlChar.VSUSP)) {
+                raise(Signal.TSTP);
+                return false;
+            } else if (c == attributes.getControlChar(ControlChar.VSTATUS)) {
+                raise(Signal.INFO);
+            }
+        }
+        if (c == '\r') {
+            if (attributes.getInputFlag(InputFlag.IGNCR)) {
+                return false;
+            }
+            if (attributes.getInputFlag(InputFlag.ICRNL)) {
+                c = '\n';
+            }
+        } else if (c == '\n' && attributes.getInputFlag(InputFlag.INLCR)) {
+            c = '\r';
+        }
+        boolean flushOut = false;
+        if (attributes.getLocalFlag(LocalFlag.ECHO)) {
+            processOutputByte(c);
+            flushOut = true;
+        }
+        slaveInputPipe.write(c);
+        return flushOut;
+    }
+
+    /**
+     * Master output processing.
+     * All data going to the master should be provided by this method.
+     *
+     * @param c the output byte
+     * @throws IOException if anything wrong happens
+     */
+    protected void processOutputByte(int c) throws IOException {
+        if (attributes.getOutputFlag(OutputFlag.OPOST)) {
+            if (c == '\n') {
+                if (attributes.getOutputFlag(OutputFlag.ONLCR)) {
+                    masterOutput.write('\r');
+                    masterOutput.write('\n');
+                    return;
+                }
+            }
+        }
+        masterOutput.write(c);
+    }
+
+    protected void processIOException(IOException ioException) {
+        this.slaveInput.setIoException(ioException);
+    }
+
+    public void close() throws IOException {
+        super.close();
+        try {
+            slaveReader.close();
+        } finally {
+            try {
+                slaveInputPipe.close();
+            } finally {
+                try {
+                } finally {
+                    slaveWriter.close();
+                }
+            }
+        }
+    }
+
+    private class FilteringOutputStream extends OutputStream {
+        @Override
+        public void write(int b) throws IOException {
+            processOutputByte(b);
+            flush();
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            if (b == null) {
+                throw new NullPointerException();
+            } else if ((off < 0) || (off > b.length) || (len < 0) ||
+                    ((off + len) > b.length) || ((off + len) < 0)) {
+                throw new IndexOutOfBoundsException();
+            } else if (len == 0) {
+                return;
+            }
+            for (int i = 0 ; i < len ; i++) {
+                processOutputByte(b[off + i]);
+            }
+            flush();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            masterOutput.flush();
+        }
+
+        @Override
+        public void close() throws IOException {
+            masterOutput.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.MouseEvent;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.InfoCmp;
+import jdk.internal.org.jline.utils.InputStreamReader;
+
+import java.io.EOFException;
+import java.io.IOError;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.EnumSet;
+import java.util.function.IntSupplier;
+
+public class MouseSupport {
+
+    public static boolean hasMouseSupport(Terminal terminal) {
+        return terminal.getStringCapability(InfoCmp.Capability.key_mouse) != null;
+    }
+
+    public static boolean trackMouse(Terminal terminal, Terminal.MouseTracking tracking) {
+        if (hasMouseSupport(terminal)) {
+            switch (tracking) {
+                case Off:
+                    terminal.writer().write("\033[?1000l");
+                    break;
+                case Normal:
+                    terminal.writer().write("\033[?1005h\033[?1000h");
+                    break;
+                case Button:
+                    terminal.writer().write("\033[?1005h\033[?1002h");
+                    break;
+                case Any:
+                    terminal.writer().write("\033[?1005h\033[?1003h");
+                    break;
+            }
+            terminal.flush();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static MouseEvent readMouse(Terminal terminal, MouseEvent last) {
+        return readMouse(() -> readExt(terminal), last);
+    }
+
+    public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) {
+        int cb = reader.getAsInt() - ' ';
+        int cx = reader.getAsInt() - ' ' - 1;
+        int cy = reader.getAsInt() - ' ' - 1;
+        MouseEvent.Type type;
+        MouseEvent.Button button;
+        EnumSet<MouseEvent.Modifier> modifiers = EnumSet.noneOf(MouseEvent.Modifier.class);
+        if ((cb & 4) == 4) {
+            modifiers.add(MouseEvent.Modifier.Shift);
+        }
+        if ((cb & 8) == 8) {
+            modifiers.add(MouseEvent.Modifier.Alt);
+        }
+        if ((cb & 16) == 16) {
+            modifiers.add(MouseEvent.Modifier.Control);
+        }
+        if ((cb & 64) == 64) {
+            type = MouseEvent.Type.Wheel;
+            button = (cb & 1) == 1 ? MouseEvent.Button.WheelDown : MouseEvent.Button.WheelUp;
+        } else {
+            int b = (cb & 3);
+            switch (b) {
+                case 0:
+                    button = MouseEvent.Button.Button1;
+                    if (last.getButton() == button
+                            && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
+                        type = MouseEvent.Type.Dragged;
+                    } else {
+                        type = MouseEvent.Type.Pressed;
+                    }
+                    break;
+                case 1:
+                    button = MouseEvent.Button.Button2;
+                    if (last.getButton() == button
+                            && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
+                        type = MouseEvent.Type.Dragged;
+                    } else {
+                        type = MouseEvent.Type.Pressed;
+                    }
+                    break;
+                case 2:
+                    button = MouseEvent.Button.Button3;
+                    if (last.getButton() == button
+                            && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
+                        type = MouseEvent.Type.Dragged;
+                    } else {
+                        type = MouseEvent.Type.Pressed;
+                    }
+                    break;
+                default:
+                    if (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged) {
+                        button = last.getButton();
+                        type = MouseEvent.Type.Released;
+                    } else {
+                        button = MouseEvent.Button.NoButton;
+                        type = MouseEvent.Type.Moved;
+                    }
+                    break;
+            }
+        }
+        return new MouseEvent(type, button, modifiers, cx, cy);
+    }
+
+    private static int readExt(Terminal terminal) {
+        try {
+            // The coordinates are encoded in UTF-8, so if that's not the input encoding,
+            // we need to get around
+            int c;
+            if (terminal.encoding() != StandardCharsets.UTF_8) {
+                c = new InputStreamReader(terminal.input(), StandardCharsets.UTF_8).read();
+            } else {
+                c = terminal.reader().read();
+            }
+            if (c < 0) {
+                throw new EOFException();
+            }
+            return c;
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import jdk.internal.org.jline.terminal.Terminal.Signal;
+import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
+
+public final class NativeSignalHandler implements SignalHandler {
+
+    public static final NativeSignalHandler SIG_DFL = new NativeSignalHandler();
+
+    public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler();
+
+    private NativeSignalHandler() {
+    }
+
+    public void handle(Signal signal) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.utils.ClosedException;
+import jdk.internal.org.jline.utils.NonBlocking;
+import jdk.internal.org.jline.utils.NonBlockingInputStream;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+
+public class PosixPtyTerminal extends AbstractPosixTerminal {
+
+    private final InputStream in;
+    private final OutputStream out;
+    private final InputStream masterInput;
+    private final OutputStream masterOutput;
+    private final NonBlockingInputStream input;
+    private final OutputStream output;
+    private final NonBlockingReader reader;
+    private final PrintWriter writer;
+
+    private final Object lock = new Object();
+    private Thread inputPumpThread;
+    private Thread outputPumpThread;
+    private boolean paused = true;
+
+    public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) throws IOException {
+        this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL);
+    }
+
+    public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException {
+        this(name, type, pty, in, out, encoding, signalHandler, false);
+    }
+
+    public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler, boolean paused) throws IOException {
+        super(name, type, pty, encoding, signalHandler);
+        this.in = Objects.requireNonNull(in);
+        this.out = Objects.requireNonNull(out);
+        this.masterInput = pty.getMasterInput();
+        this.masterOutput = pty.getMasterOutput();
+        this.input = new InputStreamWrapper(NonBlocking.nonBlocking(name, pty.getSlaveInput()));
+        this.output = pty.getSlaveOutput();
+        this.reader = NonBlocking.nonBlocking(name, input, encoding());
+        this.writer = new PrintWriter(new OutputStreamWriter(output, encoding()));
+        parseInfoCmp();
+        if (!paused) {
+            resume();
+        }
+    }
+
+    public InputStream input() {
+        return input;
+    }
+
+    public NonBlockingReader reader() {
+        return reader;
+    }
+
+    public OutputStream output() {
+        return output;
+    }
+
+    public PrintWriter writer() {
+        return writer;
+    }
+
+    @Override
+    public void close() throws IOException {
+        super.close();
+        reader.close();
+    }
+
+    @Override
+    public boolean canPauseResume() {
+        return true;
+    }
+
+    @Override
+    public void pause() {
+        synchronized (lock) {
+            paused = true;
+        }
+    }
+
+    @Override
+    public void pause(boolean wait) throws InterruptedException {
+        Thread p1, p2;
+        synchronized (lock) {
+            paused = true;
+            p1 = inputPumpThread;
+            p2 = outputPumpThread;
+        }
+        if (p1 != null) {
+            p1.interrupt();
+        }
+        if (p2 != null) {
+            p2.interrupt();
+        }
+        if (p1 != null) {
+            p1.join();
+        }
+        if (p2 !=null) {
+            p2.join();
+        }
+    }
+
+    @Override
+    public void resume() {
+        synchronized (lock) {
+            paused = false;
+            if (inputPumpThread == null) {
+                inputPumpThread = new Thread(this::pumpIn, toString() + " input pump thread");
+                inputPumpThread.setDaemon(true);
+                inputPumpThread.start();
+            }
+            if (outputPumpThread == null) {
+                outputPumpThread = new Thread(this::pumpOut, toString() + " output pump thread");
+                outputPumpThread.setDaemon(true);
+                outputPumpThread.start();
+            }
+        }
+    }
+
+    @Override
+    public boolean paused() {
+        synchronized (lock) {
+            return paused;
+        }
+    }
+
+    private class InputStreamWrapper extends NonBlockingInputStream {
+
+        private final NonBlockingInputStream in;
+        private final AtomicBoolean closed = new AtomicBoolean();
+
+        protected InputStreamWrapper(NonBlockingInputStream in) {
+            this.in = in;
+        }
+
+        @Override
+        public int read(long timeout, boolean isPeek) throws IOException {
+            if (closed.get()) {
+                throw new ClosedException();
+            }
+            return in.read(timeout, isPeek);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed.set(true);
+        }
+    }
+
+    private void pumpIn() {
+        try {
+            for (;;) {
+                synchronized (lock) {
+                    if (paused) {
+                        inputPumpThread = null;
+                        return;
+                    }
+                }
+                int b = in.read();
+                if (b < 0) {
+                    input.close();
+                    break;
+                }
+                masterOutput.write(b);
+                masterOutput.flush();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            synchronized (lock) {
+                inputPumpThread = null;
+            }
+        }
+    }
+
+    private void pumpOut() {
+        try {
+            for (;;) {
+                synchronized (lock) {
+                    if (paused) {
+                        outputPumpThread = null;
+                        return;
+                    }
+                }
+                int b = masterInput.read();
+                if (b < 0) {
+                    input.close();
+                    break;
+                }
+                out.write(b);
+                out.flush();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            synchronized (lock) {
+                outputPumpThread = null;
+            }
+        }
+        try {
+            close();
+        } catch (Throwable t) {
+            // Ignore
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.internal.org.jline.utils.NonBlocking;
+import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.utils.NonBlockingInputStream;
+import jdk.internal.org.jline.utils.NonBlockingReader;
+import jdk.internal.org.jline.utils.ShutdownHooks;
+import jdk.internal.org.jline.utils.ShutdownHooks.Task;
+import jdk.internal.org.jline.utils.Signals;
+
+public class PosixSysTerminal extends AbstractPosixTerminal {
+
+    protected final NonBlockingInputStream input;
+    protected final OutputStream output;
+    protected final NonBlockingReader reader;
+    protected final PrintWriter writer;
+    protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
+    protected final Task closer;
+
+    public PosixSysTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding,
+                            boolean nativeSignals, SignalHandler signalHandler) throws IOException {
+        super(name, type, pty, encoding, signalHandler);
+        this.input = NonBlocking.nonBlocking(getName(), in);
+        this.output = out;
+        this.reader = NonBlocking.nonBlocking(getName(), input, encoding());
+        this.writer = new PrintWriter(new OutputStreamWriter(output, encoding()));
+        parseInfoCmp();
+        if (nativeSignals) {
+            for (final Signal signal : Signal.values()) {
+                if (signalHandler == SignalHandler.SIG_DFL) {
+                    nativeHandlers.put(signal, Signals.registerDefault(signal.name()));
+                } else {
+                    nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
+                }
+            }
+        }
+        closer = PosixSysTerminal.this::close;
+        ShutdownHooks.add(closer);
+    }
+
+    @Override
+    public SignalHandler handle(Signal signal, SignalHandler handler) {
+        SignalHandler prev = super.handle(signal, handler);
+        if (prev != handler) {
+            if (handler == SignalHandler.SIG_DFL) {
+                Signals.registerDefault(signal.name());
+            } else {
+                Signals.register(signal.name(), () -> raise(signal));
+            }
+        }
+        return prev;
+    }
+
+    public NonBlockingReader reader() {
+        return reader;
+    }
+
+    public PrintWriter writer() {
+        return writer;
+    }
+
+    @Override
+    public InputStream input() {
+        return input;
+    }
+
+    @Override
+    public OutputStream output() {
+        return output;
+    }
+
+    @Override
+    public void close() throws IOException {
+        ShutdownHooks.remove(closer);
+        for (Map.Entry<Signal, Object> entry : nativeHandlers.entrySet()) {
+            Signals.unregister(entry.getKey().name(), entry.getValue());
+        }
+        super.close();
+        // Do not call reader.close()
+        reader.shutdown();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 3.
+ *
+ * @since 3.0
+ */
+package jdk.internal.org.jline.terminal.impl;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,20 @@
+package jdk.internal.org.jline.terminal.spi;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+public interface JansiSupport {
+
+    Pty current() throws IOException;
+
+    Pty open(Attributes attributes, Size size) throws IOException;
+
+    Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException;
+
+    Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,24 @@
+package jdk.internal.org.jline.terminal.spi;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.function.Function;
+
+public interface JnaSupport {
+
+    Pty current() throws IOException;
+
+    Pty open(Attributes attributes, Size size) throws IOException;
+
+    Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException;
+
+    Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException;
+
+    Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, Function<InputStream, InputStream> inputStreamWrapper) throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.spi;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Size;
+
+public interface Pty extends Closeable {
+
+    InputStream getMasterInput() throws IOException;
+
+    OutputStream getMasterOutput() throws IOException;
+
+    InputStream getSlaveInput() throws IOException;
+
+    OutputStream getSlaveOutput() throws IOException;
+
+    Attributes getAttr() throws IOException;
+
+    void setAttr(Attributes attr) throws IOException;
+
+    Size getSize() throws IOException;
+
+    void setSize(Size size) throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,832 @@
+/*
+ * Copyright (C) 2009-2018 the original author(s).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * A ANSI writer extracts ANSI escape codes written to
+ * a {@link Writer} and calls corresponding <code>process*</code> methods.
+ *
+ * For more information about ANSI escape codes, see:
+ * http://en.wikipedia.org/wiki/ANSI_escape_code
+ *
+ * This class just filters out the escape codes so that they are not
+ * sent out to the underlying {@link Writer}: <code>process*</code> methods
+ * are empty. Subclasses should actually perform the ANSI escape behaviors
+ * by implementing active code in <code>process*</code> methods.
+ *
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ * @author Joris Kuipers
+ * @since 1.0
+ */
+public class AnsiWriter extends FilterWriter {
+
+    private static final char[] RESET_CODE = "\033[0m".toCharArray();
+
+    public AnsiWriter(Writer out) {
+        super(out);
+    }
+
+    private final static int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
+    private final char[] buffer = new char[MAX_ESCAPE_SEQUENCE_LENGTH];
+    private int pos = 0;
+    private int startOfValue;
+    private final ArrayList<Object> options = new ArrayList<>();
+
+    private static final int LOOKING_FOR_FIRST_ESC_CHAR = 0;
+    private static final int LOOKING_FOR_SECOND_ESC_CHAR = 1;
+    private static final int LOOKING_FOR_NEXT_ARG = 2;
+    private static final int LOOKING_FOR_STR_ARG_END = 3;
+    private static final int LOOKING_FOR_INT_ARG_END = 4;
+    private static final int LOOKING_FOR_OSC_COMMAND = 5;
+    private static final int LOOKING_FOR_OSC_COMMAND_END = 6;
+    private static final int LOOKING_FOR_OSC_PARAM = 7;
+    private static final int LOOKING_FOR_ST = 8;
+    private static final int LOOKING_FOR_CHARSET = 9;
+
+    int state = LOOKING_FOR_FIRST_ESC_CHAR;
+
+    private static final int FIRST_ESC_CHAR = 27;
+    private static final int SECOND_ESC_CHAR = '[';
+    private static final int SECOND_OSC_CHAR = ']';
+    private static final int BEL = 7;
+    private static final int SECOND_ST_CHAR = '\\';
+    private static final int SECOND_CHARSET0_CHAR = '(';
+    private static final int SECOND_CHARSET1_CHAR = ')';
+
+    @Override
+    public synchronized void write(int data) throws IOException {
+        switch (state) {
+            case LOOKING_FOR_FIRST_ESC_CHAR:
+                if (data == FIRST_ESC_CHAR) {
+                    buffer[pos++] = (char) data;
+                    state = LOOKING_FOR_SECOND_ESC_CHAR;
+                } else {
+                    out.write(data);
+                }
+                break;
+
+            case LOOKING_FOR_SECOND_ESC_CHAR:
+                buffer[pos++] = (char) data;
+                if (data == SECOND_ESC_CHAR) {
+                    state = LOOKING_FOR_NEXT_ARG;
+                } else if (data == SECOND_OSC_CHAR) {
+                    state = LOOKING_FOR_OSC_COMMAND;
+                } else if (data == SECOND_CHARSET0_CHAR) {
+                    options.add((int) '0');
+                    state = LOOKING_FOR_CHARSET;
+                } else if (data == SECOND_CHARSET1_CHAR) {
+                    options.add((int) '1');
+                    state = LOOKING_FOR_CHARSET;
+                } else {
+                    reset(false);
+                }
+                break;
+
+            case LOOKING_FOR_NEXT_ARG:
+                buffer[pos++] = (char) data;
+                if ('"' == data) {
+                    startOfValue = pos - 1;
+                    state = LOOKING_FOR_STR_ARG_END;
+                } else if ('0' <= data && data <= '9') {
+                    startOfValue = pos - 1;
+                    state = LOOKING_FOR_INT_ARG_END;
+                } else if (';' == data) {
+                    options.add(null);
+                } else if ('?' == data) {
+                    options.add('?');
+                } else if ('=' == data) {
+                    options.add('=');
+                } else {
+                    boolean skip = true;
+                    try {
+                        skip = processEscapeCommand(options, data);
+                    } finally {
+                        reset(skip);
+                    }
+                }
+                break;
+            default:
+                break;
+
+            case LOOKING_FOR_INT_ARG_END:
+                buffer[pos++] = (char) data;
+                if (!('0' <= data && data <= '9')) {
+                    String strValue = new String(buffer, startOfValue, (pos - 1) - startOfValue);
+                    Integer value = Integer.valueOf(strValue);
+                    options.add(value);
+                    if (data == ';') {
+                        state = LOOKING_FOR_NEXT_ARG;
+                    } else {
+                        boolean skip = true;
+                        try {
+                            skip = processEscapeCommand(options, data);
+                        } finally {
+                            reset(skip);
+                        }
+                    }
+                }
+                break;
+
+            case LOOKING_FOR_STR_ARG_END:
+                buffer[pos++] = (char) data;
+                if ('"' != data) {
+                    String value = new String(buffer, startOfValue, (pos - 1) - startOfValue);
+                    options.add(value);
+                    if (data == ';') {
+                        state = LOOKING_FOR_NEXT_ARG;
+                    } else {
+                        reset(processEscapeCommand(options, data));
+                    }
+                }
+                break;
+
+            case LOOKING_FOR_OSC_COMMAND:
+                buffer[pos++] = (char) data;
+                if ('0' <= data && data <= '9') {
+                    startOfValue = pos - 1;
+                    state = LOOKING_FOR_OSC_COMMAND_END;
+                } else {
+                    reset(false);
+                }
+                break;
+
+            case LOOKING_FOR_OSC_COMMAND_END:
+                buffer[pos++] = (char) data;
+                if (';' == data) {
+                    String strValue = new String(buffer, startOfValue, (pos - 1) - startOfValue);
+                    Integer value = Integer.valueOf(strValue);
+                    options.add(value);
+                    startOfValue = pos;
+                    state = LOOKING_FOR_OSC_PARAM;
+                } else if ('0' <= data && data <= '9') {
+                    // already pushed digit to buffer, just keep looking
+                } else {
+                    // oops, did not expect this
+                    reset(false);
+                }
+                break;
+
+            case LOOKING_FOR_OSC_PARAM:
+                buffer[pos++] = (char) data;
+                if (BEL == data) {
+                    String value = new String(buffer, startOfValue, (pos - 1) - startOfValue);
+                    options.add(value);
+                    boolean skip = true;
+                    try {
+                        skip = processOperatingSystemCommand(options);
+                    } finally {
+                        reset(skip);
+                    }
+                } else if (FIRST_ESC_CHAR == data) {
+                    state = LOOKING_FOR_ST;
+                } else {
+                    // just keep looking while adding text
+                }
+                break;
+
+            case LOOKING_FOR_ST:
+                buffer[pos++] = (char) data;
+                if (SECOND_ST_CHAR == data) {
+                    String value = new String(buffer, startOfValue, (pos - 2) - startOfValue);
+                    options.add(value);
+                    boolean skip = true;
+                    try {
+                        skip = processOperatingSystemCommand(options);
+                    } finally {
+                        reset(skip);
+                    }
+                } else {
+                    state = LOOKING_FOR_OSC_PARAM;
+                }
+                break;
+
+            case LOOKING_FOR_CHARSET:
+                options.add((char) data);
+                reset(processCharsetSelect(options));
+                break;
+        }
+
+        // Is it just too long?
+        if (pos >= buffer.length) {
+            reset(false);
+        }
+    }
+
+    /**
+     * Resets all state to continue with regular parsing
+     * @param skipBuffer if current buffer should be skipped or written to out
+     * @throws IOException if an error occurs
+     */
+    private void reset(boolean skipBuffer) throws IOException {
+        if (!skipBuffer) {
+            out.write(buffer, 0, pos);
+        }
+        pos = 0;
+        startOfValue = 0;
+        options.clear();
+        state = LOOKING_FOR_FIRST_ESC_CHAR;
+    }
+
+    /**
+     * Helper for processEscapeCommand() to iterate over integer options
+     * @param  optionsIterator  the underlying iterator
+     * @throws IOException      if no more non-null values left
+     */
+    private int getNextOptionInt(Iterator<Object> optionsIterator) throws IOException {
+        for (;;) {
+            if (!optionsIterator.hasNext())
+                throw new IllegalArgumentException();
+            Object arg = optionsIterator.next();
+            if (arg != null)
+                return (Integer) arg;
+        }
+    }
+
+    /**
+     * Process escape command
+     * @param options the list of options
+     * @param command the command
+     * @throws IOException if an error occurs
+     * @return true if the escape command was processed.
+     */
+    private boolean processEscapeCommand(ArrayList<Object> options, int command) throws IOException {
+        try {
+            switch (command) {
+                case 'A':
+                    processCursorUp(optionInt(options, 0, 1));
+                    return true;
+                case 'B':
+                    processCursorDown(optionInt(options, 0, 1));
+                    return true;
+                case 'C':
+                    processCursorRight(optionInt(options, 0, 1));
+                    return true;
+                case 'D':
+                    processCursorLeft(optionInt(options, 0, 1));
+                    return true;
+                case 'E':
+                    processCursorDownLine(optionInt(options, 0, 1));
+                    return true;
+                case 'F':
+                    processCursorUpLine(optionInt(options, 0, 1));
+                    return true;
+                case 'G':
+                    processCursorToColumn(optionInt(options, 0));
+                    return true;
+                case 'H':
+                case 'f':
+                    processCursorTo(optionInt(options, 0, 1), optionInt(options, 1, 1));
+                    return true;
+                case 'J':
+                    processEraseScreen(optionInt(options, 0, 0));
+                    return true;
+                case 'K':
+                    processEraseLine(optionInt(options, 0, 0));
+                    return true;
+                case 'L':
+                    processInsertLine(optionInt(options, 0, 1));
+                    return true;
+                case 'M':
+                    processDeleteLine(optionInt(options, 0, 1));
+                    return true;
+                case 'S':
+                    processScrollUp(optionInt(options, 0, 1));
+                    return true;
+                case 'T':
+                    processScrollDown(optionInt(options, 0, 1));
+                    return true;
+                case 'm':
+                    // Validate all options are ints...
+                    for (Object next : options) {
+                        if (next != null && next.getClass() != Integer.class) {
+                            throw new IllegalArgumentException();
+                        }
+                    }
+
+                    int count = 0;
+                    Iterator<Object> optionsIterator = options.iterator();
+                    while (optionsIterator.hasNext()) {
+                        Object next = optionsIterator.next();
+                        if (next != null) {
+                            count++;
+                            int value = (Integer) next;
+                            if (30 <= value && value <= 37) {
+                                processSetForegroundColor(value - 30);
+                            } else if (40 <= value && value <= 47) {
+                                processSetBackgroundColor(value - 40);
+                            } else if (90 <= value && value <= 97) {
+                                processSetForegroundColor(value - 90, true);
+                            } else if (100 <= value && value <= 107) {
+                                processSetBackgroundColor(value - 100, true);
+                            } else if (value == 38 || value == 48) {
+                                // extended color like `esc[38;5;<index>m` or `esc[38;2;<r>;<g>;<b>m`
+                                int arg2or5 = getNextOptionInt(optionsIterator);
+                                if (arg2or5 == 2) {
+                                    // 24 bit color style like `esc[38;2;<r>;<g>;<b>m`
+                                    int r = getNextOptionInt(optionsIterator);
+                                    int g = getNextOptionInt(optionsIterator);
+                                    int b = getNextOptionInt(optionsIterator);
+                                    if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
+                                        if (value == 38)
+                                            processSetForegroundColorExt(r, g, b);
+                                        else
+                                            processSetBackgroundColorExt(r, g, b);
+                                    } else {
+                                        throw new IllegalArgumentException();
+                                    }
+                                }
+                                else if (arg2or5 == 5) {
+                                    // 256 color style like `esc[38;5;<index>m`
+                                    int paletteIndex = getNextOptionInt(optionsIterator);
+                                    if (paletteIndex >= 0 && paletteIndex <= 255) {
+                                        if (value == 38)
+                                            processSetForegroundColorExt(paletteIndex);
+                                        else
+                                            processSetBackgroundColorExt(paletteIndex);
+                                    } else {
+                                        throw new IllegalArgumentException();
+                                    }
+                                }
+                                else {
+                                    throw new IllegalArgumentException();
+                                }
+                            } else {
+                                switch (value) {
+                                    case 39:
+                                        processDefaultTextColor();
+                                        break;
+                                    case 49:
+                                        processDefaultBackgroundColor();
+                                        break;
+                                    case 0:
+                                        processAttributeRest();
+                                        break;
+                                    default:
+                                        processSetAttribute(value);
+                                }
+                            }
+                        }
+                    }
+                    if (count == 0) {
+                        processAttributeRest();
+                    }
+                    return true;
+                case 's':
+                    processSaveCursorPosition();
+                    return true;
+                case 'u':
+                    processRestoreCursorPosition();
+                    return true;
+
+                default:
+                    if ('a' <= command && 'z' <= command) {
+                        processUnknownExtension(options, command);
+                        return true;
+                    }
+                    if ('A' <= command && 'Z' <= command) {
+                        processUnknownExtension(options, command);
+                        return true;
+                    }
+                    return false;
+            }
+        } catch (IllegalArgumentException ignore) {
+        }
+        return false;
+    }
+
+    /**
+     * Process operating system command.
+     * @param options the options list
+     * @return true if the operating system command was processed.
+     */
+    private boolean processOperatingSystemCommand(ArrayList<Object> options) throws IOException {
+        int command = optionInt(options, 0);
+        String label = (String) options.get(1);
+        // for command > 2 label could be composed (i.e. contain ';'), but we'll leave
+        // it to processUnknownOperatingSystemCommand implementations to handle that
+        try {
+            switch (command) {
+                case 0:
+                    processChangeIconNameAndWindowTitle(label);
+                    return true;
+                case 1:
+                    processChangeIconName(label);
+                    return true;
+                case 2:
+                    processChangeWindowTitle(label);
+                    return true;
+
+                default:
+                    // not exactly unknown, but not supported through dedicated process methods:
+                    processUnknownOperatingSystemCommand(command, label);
+                    return true;
+            }
+        } catch (IllegalArgumentException ignore) {
+        }
+        return false;
+    }
+
+    /**
+     * Process <code>CSI u</code> ANSI code, corresponding to <code>RCP \u2013 Restore Cursor Position</code>
+     * @throws IOException if an error occurs
+     */
+    protected void processRestoreCursorPosition() throws IOException {
+    }
+
+    /**
+     * Process <code>CSI s</code> ANSI code, corresponding to <code>SCP \u2013 Save Cursor Position</code>
+     * @throws IOException if an error occurs
+     */
+    protected void processSaveCursorPosition() throws IOException {
+    }
+
+    /**
+     * Process <code>CSI s</code> ANSI code, corresponding to <code>IL \u2013 Insert Line</code>
+     * @param optionInt the option
+     * @throws IOException if an error occurs
+     */
+    protected void processInsertLine(int optionInt) throws IOException {
+    }
+
+    /**
+     * Process <code>CSI s</code> ANSI code, corresponding to <code>DL \u2013 Delete Line</code>
+     * @param optionInt the option
+     * @throws IOException if an error occurs
+     */
+    protected void processDeleteLine(int optionInt) throws IOException {
+    }
+
+    /**
+     * Process <code>CSI n T</code> ANSI code, corresponding to <code>SD \u2013 Scroll Down</code>
+     * @param optionInt the option
+     * @throws IOException if an error occurs
+     */
+    protected void processScrollDown(int optionInt) throws IOException {
+    }
+
+    /**
+     * Process <code>CSI n U</code> ANSI code, corresponding to <code>SU \u2013 Scroll Up</code>
+     * @param optionInt the option
+     * @throws IOException if an error occurs
+     */
+    protected void processScrollUp(int optionInt) throws IOException {
+    }
+
+    protected static final int ERASE_SCREEN_TO_END = 0;
+    protected static final int ERASE_SCREEN_TO_BEGINING = 1;
+    protected static final int ERASE_SCREEN = 2;
+
+    /**
+     * Process <code>CSI n J</code> ANSI code, corresponding to <code>ED \u2013 Erase in Display</code>
+     * @param eraseOption the erase option
+     * @throws IOException if an error occurs
+     */
+    protected void processEraseScreen(int eraseOption) throws IOException {
+    }
+
+    protected static final int ERASE_LINE_TO_END = 0;
+    protected static final int ERASE_LINE_TO_BEGINING = 1;
+    protected static final int ERASE_LINE = 2;
+
+    /**
+     * Process <code>CSI n K</code> ANSI code, corresponding to <code>ED \u2013 Erase in Line</code>
+     * @param eraseOption the erase option
+     * @throws IOException if an error occurs
+     */
+    protected void processEraseLine(int eraseOption) throws IOException {
+    }
+
+    protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; //         Intensity: Bold
+    protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; //        Intensity; Faint        not widely supported
+    protected static final int ATTRIBUTE_ITALIC = 3; //         Italic; on      not widely supported. Sometimes treated as inverse.
+    protected static final int ATTRIBUTE_UNDERLINE = 4; //      Underline; Single
+    protected static final int ATTRIBUTE_BLINK_SLOW = 5; //     Blink; Slow     less than 150 per minute
+    protected static final int ATTRIBUTE_BLINK_FAST = 6; //     Blink; Rapid    MS-DOS ANSI.SYS; 150 per minute or more
+    protected static final int ATTRIBUTE_NEGATIVE_ON = 7; //    Image; Negative         inverse or reverse; swap foreground and background
+    protected static final int ATTRIBUTE_CONCEAL_ON = 8; //     Conceal on
+    protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; //      Underline; Double       not widely supported
+    protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; //      Intensity; Normal       not bold and not faint
+    protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; //         Underline; None
+    protected static final int ATTRIBUTE_BLINK_OFF = 25; //     Blink; off
+    @Deprecated
+    protected static final int ATTRIBUTE_NEGATIVE_Off = 27; //  Image; Positive
+    protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; //  Image; Positive
+    protected static final int ATTRIBUTE_CONCEAL_OFF = 28; //   Reveal  conceal off
+
+    /**
+     * process <code>SGR</code> other than <code>0</code> (reset), <code>30-39</code> (foreground),
+     * <code>40-49</code> (background), <code>90-97</code> (foreground high intensity) or
+     * <code>100-107</code> (background high intensity)
+     * @param attribute the attribute to set
+     * @throws IOException if an error occurs
+     * @see #processAttributeRest()
+     * @see #processSetForegroundColor(int)
+     * @see #processSetForegroundColor(int, boolean)
+     * @see #processSetForegroundColorExt(int)
+     * @see #processSetForegroundColorExt(int, int, int)
+     * @see #processDefaultTextColor()
+     * @see #processDefaultBackgroundColor()
+     */
+    protected void processSetAttribute(int attribute) throws IOException {
+    }
+
+    protected static final int BLACK = 0;
+    protected static final int RED = 1;
+    protected static final int GREEN = 2;
+    protected static final int YELLOW = 3;
+    protected static final int BLUE = 4;
+    protected static final int MAGENTA = 5;
+    protected static final int CYAN = 6;
+    protected static final int WHITE = 7;
+
+    /**
+     * process <code>SGR 30-37</code> corresponding to <code>Set text color (foreground)</code>.
+     * @param color the text color
+     * @throws IOException if an error occurs
+     */
+    protected void processSetForegroundColor(int color) throws IOException {
+        processSetForegroundColor(color, false);
+    }
+
+    /**
+     * process <code>SGR 30-37</code> or <code>SGR 90-97</code> corresponding to
+     * <code>Set text color (foreground)</code> either in normal mode or high intensity.
+     * @param color the text color
+     * @param bright is high intensity?
+     * @throws IOException if an error occurs
+     */
+    protected void processSetForegroundColor(int color, boolean bright) throws IOException {
+        processSetForegroundColorExt(bright ? color + 8 : color);
+    }
+
+    /**
+     * process <code>SGR 38</code> corresponding to <code>extended set text color (foreground)</code>
+     * with a palette of 255 colors.
+     * @param paletteIndex the text color in the palette
+     * @throws IOException if an error occurs
+     */
+    protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
+    }
+
+    /**
+     * process <code>SGR 38</code> corresponding to <code>extended set text color (foreground)</code>
+     * with a 24 bits RGB definition of the color.
+     * @param r red
+     * @param g green
+     * @param b blue
+     * @throws IOException if an error occurs
+     */
+    protected void processSetForegroundColorExt(int r, int g, int b) throws IOException {
+        processSetForegroundColorExt(Colors.roundRgbColor(r, g, b, 16));
+    }
+
+    /**
+     * process <code>SGR 40-47</code> corresponding to <code>Set background color</code>.
+     * @param color the background color
+     * @throws IOException if an error occurs
+     */
+    protected void processSetBackgroundColor(int color) throws IOException {
+        processSetBackgroundColor(color, false);
+    }
+
+    /**
+     * process <code>SGR 40-47</code> or <code>SGR 100-107</code> corresponding to
+     * <code>Set background color</code> either in normal mode or high intensity.
+     * @param color the background color
+     * @param bright is high intensity?
+     * @throws IOException if an error occurs
+     */
+    protected void processSetBackgroundColor(int color, boolean bright) throws IOException {
+        processSetBackgroundColorExt(bright ? color + 8 : color);
+    }
+
+    /**
+     * process <code>SGR 48</code> corresponding to <code>extended set background color</code>
+     * with a palette of 255 colors.
+     * @param paletteIndex the background color in the palette
+     * @throws IOException if an error occurs
+     */
+    protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
+    }
+
+    /**
+     * process <code>SGR 48</code> corresponding to <code>extended set background color</code>
+     * with a 24 bits RGB definition of the color.
+     * @param r red
+     * @param g green
+     * @param b blue
+     * @throws IOException if an error occurs
+     */
+    protected void processSetBackgroundColorExt(int r, int g, int b) throws IOException {
+        processSetBackgroundColorExt(Colors.roundRgbColor(r, g, b, 16));
+    }
+
+    /**
+     * process <code>SGR 39</code> corresponding to <code>Default text color (foreground)</code>
+     * @throws IOException if an error occurs
+     */
+    protected void processDefaultTextColor() throws IOException {
+    }
+
+    /**
+     * process <code>SGR 49</code> corresponding to <code>Default background color</code>
+     * @throws IOException if an error occurs
+     */
+    protected void processDefaultBackgroundColor() throws IOException {
+    }
+
+    /**
+     * process <code>SGR 0</code> corresponding to <code>Reset / Normal</code>
+     * @throws IOException if an error occurs
+     */
+    protected void processAttributeRest() throws IOException {
+    }
+
+    /**
+     * process <code>CSI n ; m H</code> corresponding to <code>CUP \u2013 Cursor Position</code> or
+     * <code>CSI n ; m f</code> corresponding to <code>HVP \u2013 Horizontal and Vertical Position</code>
+     * @param row the row
+     * @param col the column
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorTo(int row, int col) throws IOException {
+    }
+
+    /**
+     * process <code>CSI n G</code> corresponding to <code>CHA \u2013 Cursor Horizontal Absolute</code>
+     * @param x the column
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorToColumn(int x) throws IOException {
+    }
+
+    /**
+     * process <code>CSI n F</code> corresponding to <code>CPL \u2013 Cursor Previous Line</code>
+     * @param count line count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorUpLine(int count) throws IOException {
+    }
+
+    /**
+     * process <code>CSI n E</code> corresponding to <code>CNL \u2013 Cursor Next Line</code>
+     * @param count line count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorDownLine(int count) throws IOException {
+        // Poor mans impl..
+        for (int i = 0; i < count; i++) {
+            out.write('\n');
+        }
+    }
+
+    /**
+     * process <code>CSI n D</code> corresponding to <code>CUB \u2013 Cursor Back</code>
+     * @param count the count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorLeft(int count) throws IOException {
+    }
+
+    /**
+     * process <code>CSI n C</code> corresponding to <code>CUF \u2013 Cursor Forward</code>
+     * @param count the count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorRight(int count) throws IOException {
+        // Poor mans impl..
+        for (int i = 0; i < count; i++) {
+            out.write(' ');
+        }
+    }
+
+    /**
+     * process <code>CSI n B</code> corresponding to <code>CUD \u2013 Cursor Down</code>
+     * @param count the count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorDown(int count) throws IOException {
+    }
+
+    /**
+     * process <code>CSI n A</code> corresponding to <code>CUU \u2013 Cursor Up</code>
+     * @param count the count
+     * @throws IOException if an error occurs
+     */
+    protected void processCursorUp(int count) throws IOException {
+    }
+
+    protected void processUnknownExtension(ArrayList<Object> options, int command) {
+    }
+
+    /**
+     * process <code>OSC 0;text BEL</code> corresponding to <code>Change Window and Icon label</code>
+     * @param label the label
+     */
+    protected void processChangeIconNameAndWindowTitle(String label) {
+        processChangeIconName(label);
+        processChangeWindowTitle(label);
+    }
+
+    /**
+     * process <code>OSC 1;text BEL</code> corresponding to <code>Change Icon label</code>
+     * @param name the icon name
+     */
+    protected void processChangeIconName(String name) {
+    }
+
+    /**
+     * process <code>OSC 2;text BEL</code> corresponding to <code>Change Window title</code>
+     * @param title the title
+     */
+    protected void processChangeWindowTitle(String title) {
+    }
+
+    /**
+     * Process unknown <code>OSC</code> command.
+     * @param command the command
+     * @param param the param
+     */
+    protected void processUnknownOperatingSystemCommand(int command, String param) {
+    }
+
+    /**
+     * Process character set sequence.
+     * @param options
+     * @return true if the charcter set select command was processed.
+     */
+    private boolean processCharsetSelect(ArrayList<Object> options) throws IOException {
+        int set = optionInt(options, 0);
+        char seq = (Character) options.get(1);
+        processCharsetSelect(set, seq);
+        return true;
+    }
+
+    protected void processCharsetSelect(int set, char seq) {
+    }
+
+    private int optionInt(ArrayList<Object> options, int index) {
+        if (options.size() <= index)
+            throw new IllegalArgumentException();
+        Object value = options.get(index);
+        if (value == null)
+            throw new IllegalArgumentException();
+        if (!value.getClass().equals(Integer.class))
+            throw new IllegalArgumentException();
+        return (Integer) value;
+    }
+
+    private int optionInt(ArrayList<Object> options, int index, int defaultValue) {
+        if (options.size() > index) {
+            Object value = options.get(index);
+            if (value == null) {
+                return defaultValue;
+            }
+            return (Integer) value;
+        }
+        return defaultValue;
+    }
+
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        // TODO: Optimize this
+        for (int i = 0; i < len; i++) {
+            write(cbuf[off + i]);
+        }
+    }
+
+    @Override
+    public void write(String str, int off, int len) throws IOException {
+        // TODO: Optimize this
+        for (int i = 0; i < len; i++) {
+            write(str.charAt(off + i));
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        write(RESET_CODE);
+        flush();
+        super.close();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+
+import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR;
+import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP;
+import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR;
+import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR_EXP;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_BACKGROUND;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_BLINK;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_BOLD;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_CONCEAL;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_CROSSED_OUT;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_FAINT;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE;
+import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN;
+import static jdk.internal.org.jline.utils.AttributedStyle.MASK;
+import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET;
+
+public abstract class AttributedCharSequence implements CharSequence {
+
+    // cache the value here as we can't afford to get it each time
+    static final boolean DISABLE_ALTERNATE_CHARSET = Boolean.getBoolean(PROP_DISABLE_ALTERNATE_CHARSET);
+
+    public String toAnsi() {
+        return toAnsi(null);
+    }
+
+    public String toAnsi(Terminal terminal) {
+        if (terminal != null && Terminal.TYPE_DUMB.equals(terminal.getType())) {
+            return toString();
+        }
+        int colors = 256;
+        boolean force256colors = false;
+        String alternateIn = null, alternateOut = null;
+        if (terminal != null) {
+            Integer max_colors = terminal.getNumericCapability(Capability.max_colors);
+            if (max_colors != null) {
+                colors = max_colors;
+            }
+            force256colors = AbstractWindowsTerminal.TYPE_WINDOWS_256_COLOR.equals(terminal.getType());
+            if (!DISABLE_ALTERNATE_CHARSET) {
+                alternateIn = Curses.tputs(terminal.getStringCapability(Capability.enter_alt_charset_mode));
+                alternateOut = Curses.tputs(terminal.getStringCapability(Capability.exit_alt_charset_mode));
+            }
+        }
+        return toAnsi(colors, force256colors, alternateIn, alternateOut);
+    }
+
+    public String toAnsi(int colors, boolean force256colors) {
+        return toAnsi(colors, force256colors, null, null);
+    }
+
+    public String toAnsi(int colors, boolean force256colors, String altIn, String altOut) {
+        StringBuilder sb = new StringBuilder();
+        int style = 0;
+        int foreground = -1;
+        int background = -1;
+        boolean alt = false;
+        for (int i = 0; i < length(); i++) {
+            char c = charAt(i);
+            if (altIn != null && altOut != null) {
+                char pc = c;
+                switch (c) {
+                    case '\u2518': c = 'j'; break;
+                    case '\u2510': c = 'k'; break;
+                    case '\u250C': c = 'l'; break;
+                    case '\u2514': c = 'm'; break;
+                    case '\u253C': c = 'n'; break;
+                    case '\u2500': c = 'q'; break;
+                    case '\u251C': c = 't'; break;
+                    case '\u2524': c = 'u'; break;
+                    case '\u2534': c = 'v'; break;
+                    case '\u252C': c = 'w'; break;
+                    case '\u2502': c = 'x'; break;
+                }
+                boolean oldalt = alt;
+                alt = c != pc;
+                if (oldalt ^ alt) {
+                    sb.append(alt ? altIn : altOut);
+                }
+            }
+            int  s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles
+            if (style != s) {
+                int  d = (style ^ s) & MASK;
+                int fg = (s & F_FOREGROUND) != 0 ? (s & FG_COLOR) >>> FG_COLOR_EXP : -1;
+                int bg = (s & F_BACKGROUND) != 0 ? (s & BG_COLOR) >>> BG_COLOR_EXP : -1;
+                if (s == 0) {
+                    sb.append("\033[0m");
+                    foreground = background = -1;
+                } else {
+                    sb.append("\033[");
+                    boolean first = true;
+                    if ((d & F_ITALIC) != 0) {
+                        first = attr(sb, (s & F_ITALIC) != 0 ? "3" : "23", first);
+                    }
+                    if ((d & F_UNDERLINE) != 0) {
+                        first = attr(sb, (s & F_UNDERLINE) != 0 ? "4" : "24", first);
+                    }
+                    if ((d & F_BLINK) != 0) {
+                        first = attr(sb, (s & F_BLINK) != 0 ? "5" : "25", first);
+                    }
+                    if ((d & F_INVERSE) != 0) {
+                        first = attr(sb, (s & F_INVERSE) != 0 ? "7" : "27", first);
+                    }
+                    if ((d & F_CONCEAL) != 0) {
+                        first = attr(sb, (s & F_CONCEAL) != 0 ? "8" : "28", first);
+                    }
+                    if ((d & F_CROSSED_OUT) != 0) {
+                        first = attr(sb, (s & F_CROSSED_OUT) != 0 ? "9" : "29", first);
+                    }
+                    if (foreground != fg) {
+                        if (fg >= 0) {
+                            int rounded = Colors.roundColor(fg, colors);
+                            if (rounded < 8 && !force256colors) {
+                                first = attr(sb, "3" + Integer.toString(rounded), first);
+                                // small hack to force setting bold again after a foreground color change
+                                d |= (s & F_BOLD);
+                            } else if (rounded < 16 && !force256colors) {
+                                first = attr(sb, "9" + Integer.toString(rounded - 8), first);
+                                // small hack to force setting bold again after a foreground color change
+                                d |= (s & F_BOLD);
+                            } else {
+                                first = attr(sb, "38;5;" + Integer.toString(rounded), first);
+                            }
+                        } else {
+                            first = attr(sb, "39", first);
+                        }
+                        foreground = fg;
+                    }
+                    if (background != bg) {
+                        if (bg >= 0) {
+                            int rounded = Colors.roundColor(bg, colors);
+                            if (rounded < 8 && !force256colors) {
+                                first = attr(sb, "4" + Integer.toString(rounded), first);
+                            } else if (rounded < 16 && !force256colors) {
+                                first = attr(sb, "10" + Integer.toString(rounded - 8), first);
+                            } else {
+                                first = attr(sb, "48;5;" + Integer.toString(rounded), first);
+                            }
+                        } else {
+                            first = attr(sb, "49", first);
+                        }
+                        background = bg;
+                    }
+                    if ((d & (F_BOLD | F_FAINT)) != 0) {
+                        if (    (d & F_BOLD)  != 0 && (s & F_BOLD)  == 0
+                                || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) {
+                            first = attr(sb, "22", first);
+                        }
+                        if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) {
+                            first = attr(sb, "1", first);
+                        }
+                        if ((d & F_FAINT) != 0 && (s & F_FAINT) != 0) {
+                            first = attr(sb, "2", first);
+                        }
+                    }
+                    sb.append("m");
+                }
+                style = s;
+            }
+            sb.append(c);
+        }
+        if (alt) {
+            sb.append(altOut);
+        }
+        if (style != 0) {
+            sb.append("\033[0m");
+        }
+        return sb.toString();
+    }
+
+    @Deprecated
+    public static int rgbColor(int col) {
+        return Colors.rgbColor(col);
+    }
+
+    @Deprecated
+    public static int roundColor(int col, int max) {
+        return Colors.roundColor(col, max);
+    }
+
+    @Deprecated
+    public static int roundRgbColor(int r, int g, int b, int max) {
+        return Colors.roundRgbColor(r, g, b, max);
+    }
+
+    private static boolean attr(StringBuilder sb, String s, boolean first) {
+        if (!first) {
+            sb.append(";");
+        }
+        sb.append(s);
+        return false;
+    }
+
+    public abstract AttributedStyle styleAt(int index);
+
+    int styleCodeAt(int index) {
+        return styleAt(index).getStyle();
+    }
+
+    public boolean isHidden(int index) {
+        return (styleCodeAt(index) & F_HIDDEN) != 0;
+    }
+
+    public int runStart(int index) {
+        AttributedStyle style = styleAt(index);
+        while (index > 0 && styleAt(index - 1).equals(style)) {
+            index--;
+        }
+        return index;
+    }
+
+    public int runLimit(int index) {
+        AttributedStyle style = styleAt(index);
+        while (index < length() - 1 && styleAt(index + 1).equals(style)) {
+            index++;
+        }
+        return index + 1;
+    }
+
+    @Override
+    public abstract AttributedString subSequence(int start, int end);
+
+    public AttributedString substring(int start, int end) {
+        return subSequence(start, end);
+    }
+
+    protected abstract char[] buffer();
+
+    protected abstract int offset();
+
+    @Override
+    public char charAt(int index) {
+        return buffer()[offset() + index];
+    }
+
+    public int codePointAt(int index) {
+        return Character.codePointAt(buffer(), index + offset());
+    }
+
+    public boolean contains(char c) {
+        for (int i = 0; i < length(); i++) {
+            if (charAt(i) == c) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public int codePointBefore(int index) {
+        return Character.codePointBefore(buffer(), index + offset());
+    }
+
+    public int codePointCount(int index, int length) {
+        return Character.codePointCount(buffer(), index + offset(), length);
+    }
+
+    public int columnLength() {
+        int cols = 0;
+        int len = length();
+        for (int cur = 0; cur < len; ) {
+            int cp = codePointAt(cur);
+            if (!isHidden(cur))
+                cols += WCWidth.wcwidth(cp);
+            cur += Character.charCount(cp);
+        }
+        return cols;
+    }
+
+    public AttributedString columnSubSequence(int start, int stop) {
+        int begin = 0;
+        int col = 0;
+        while (begin < this.length()) {
+            int cp = codePointAt(begin);
+            int w = isHidden(begin) ? 0 : WCWidth.wcwidth(cp);
+            if (col + w > start) {
+                break;
+            }
+            begin++;
+            col += w;
+        }
+        int end = begin;
+        while (end < this.length()) {
+            int cp = codePointAt(end);
+            if (cp == '\n')
+                break;
+            int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp);
+            if (col + w > stop) {
+                break;
+            }
+            end++;
+            col += w;
+        }
+        return subSequence(begin, end);
+    }
+
+    public List<AttributedString> columnSplitLength(int columns) {
+        return columnSplitLength(columns, false, true);
+    }
+
+    public List<AttributedString> columnSplitLength(int columns, boolean includeNewlines, boolean delayLineWrap) {
+        List<AttributedString> strings = new ArrayList<>();
+        int cur = 0;
+        int beg = cur;
+        int col = 0;
+        while (cur < length()) {
+            int cp = codePointAt(cur);
+            int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp);
+            if (cp == '\n') {
+                strings.add(subSequence(beg, includeNewlines ? cur+1 : cur));
+                beg = cur + 1;
+                col = 0;
+            } else if ((col += w) > columns) {
+                strings.add(subSequence(beg, cur));
+                beg = cur;
+                col = w;
+            }
+            cur += Character.charCount(cp);
+        }
+        strings.add(subSequence(beg, cur));
+        return strings;
+    }
+
+    @Override
+    public String toString() {
+        return new String(buffer(), offset(), length());
+    }
+
+    public AttributedString toAttributedString() {
+        return substring(0, length());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Attributed string.
+ * Instances of this class are immutables.
+ * Substrings are created without any memory copy.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class AttributedString extends AttributedCharSequence {
+
+    final char[] buffer;
+    final int[] style;
+    final int start;
+    final int end;
+    public static final AttributedString EMPTY = new AttributedString("");
+    public static final AttributedString NEWLINE = new AttributedString("\n");
+
+    public AttributedString(CharSequence str) {
+        this(str, 0, str.length(), null);
+    }
+
+    public AttributedString(CharSequence str, int start, int end) {
+        this(str, start, end, null);
+    }
+
+    public AttributedString(CharSequence str, AttributedStyle s) {
+        this(str, 0, str.length(), s);
+    }
+
+    public AttributedString(CharSequence str, int start, int end, AttributedStyle s) {
+        if (end < start) {
+            throw new InvalidParameterException();
+        }
+        if (str instanceof AttributedString) {
+            AttributedString as = (AttributedString) str;
+            this.buffer = as.buffer;
+            if (s != null) {
+                this.style = as.style.clone();
+                for (int i = 0; i < style.length; i++) {
+                    this.style[i] = (this.style[i] & ~s.getMask()) | s.getStyle();
+                }
+            } else {
+                this.style = as.style;
+            }
+            this.start = as.start + start;
+            this.end = as.start + end;
+        } else if (str instanceof AttributedStringBuilder) {
+            AttributedStringBuilder asb = (AttributedStringBuilder) str;
+            AttributedString as = asb.subSequence(start, end);
+            this.buffer = as.buffer;
+            this.style = as.style;
+            if (s != null) {
+                for (int i = 0; i < style.length; i++) {
+                    this.style[i] = (this.style[i] & ~s.getMask()) | s.getStyle();
+                }
+            }
+            this.start = as.start;
+            this.end = as.end;
+        } else {
+            int l = end - start;
+            buffer = new char[l];
+            for (int i = 0; i < l; i++) {
+                buffer[i] = str.charAt(start + i);
+            }
+            style = new int[l];
+            if (s != null) {
+                Arrays.fill(style, s.getStyle());
+            }
+            this.start = 0;
+            this.end = l;
+        }
+    }
+
+    AttributedString(char[] buffer, int[] style, int start, int end) {
+        this.buffer = buffer;
+        this.style = style;
+        this.start = start;
+        this.end = end;
+    }
+
+    public static AttributedString fromAnsi(String ansi) {
+        return fromAnsi(ansi, 0);
+    }
+
+    public static AttributedString fromAnsi(String ansi, int tabs) {
+        if (ansi == null) {
+            return null;
+        }
+        return new AttributedStringBuilder(ansi.length())
+                .tabs(tabs)
+                .ansiAppend(ansi)
+                .toAttributedString();
+    }
+
+    public static String stripAnsi(String ansi) {
+        if (ansi == null) {
+            return null;
+        }
+        return new AttributedStringBuilder(ansi.length())
+                .ansiAppend(ansi)
+                .toString();
+    }
+
+    @Override
+    protected char[] buffer() {
+        return buffer;
+    }
+
+    @Override
+    protected int offset() {
+        return start;
+    }
+
+    @Override
+    public int length() {
+        return end - start;
+    }
+
+    @Override
+    public AttributedStyle styleAt(int index) {
+        return new AttributedStyle(style[start + index], style[start + index]);
+    }
+
+    @Override
+    int styleCodeAt(int index) {
+        return style[start + index];
+    }
+
+    @Override
+    public AttributedString subSequence(int start, int end) {
+        return new AttributedString(this, start, end);
+    }
+
+    public AttributedString styleMatches(Pattern pattern, AttributedStyle style) {
+        Matcher matcher = pattern.matcher(this);
+        boolean result = matcher.find();
+        if (result) {
+            int[] newstyle = this.style.clone();
+            do {
+                for (int i = matcher.start(); i < matcher.end(); i++) {
+                    newstyle[this.start + i] = (newstyle[this.start + i] & ~style.getMask()) | style.getStyle();
+                }
+                result = matcher.find();
+            } while (result);
+            return new AttributedString(buffer, newstyle, start , end);
+        }
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        AttributedString that = (AttributedString) o;
+        return end - start == that.end - that.start
+                && arrEq(buffer, that.buffer, start, that.start, end - start)
+                && arrEq(style, that.style, start, that.start, end - start);
+    }
+
+    private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) {
+        for (int i = 0; i < l; i++) {
+            if (a1[s1+i] != a2[s2+i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+    private boolean arrEq(int[] a1, int[] a2, int s1, int s2, int l) {
+        for (int i = 0; i < l; i++) {
+            if (a1[s1+i] != a2[s2+i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Arrays.hashCode(buffer);
+        result = 31 * result + Arrays.hashCode(style);
+        result = 31 * result + start;
+        result = 31 * result + end;
+        return result;
+    }
+
+    public static AttributedString join(AttributedString delimiter, AttributedString... elements) {
+        Objects.requireNonNull(delimiter);
+        Objects.requireNonNull(elements);
+        return join(delimiter, Arrays.asList(elements));
+    }
+
+    public static AttributedString join(AttributedString delimiter, Iterable<AttributedString> elements) {
+        Objects.requireNonNull(elements);
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        int i = 0;
+        for (AttributedString str : elements) {
+            if (i++ > 0 && delimiter != null) {
+                sb.append(delimiter);
+            }
+            sb.append(str);
+        }
+        return sb.toAttributedString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Attributed string builder
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class AttributedStringBuilder extends AttributedCharSequence implements Appendable {
+
+    private char[] buffer;
+    private int[] style;
+    private int length;
+    private int tabs = 0;
+    private int lastLineLength = 0;
+    private AttributedStyle current = AttributedStyle.DEFAULT;
+
+    public static AttributedString append(CharSequence... strings) {
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        for (CharSequence s : strings) {
+            sb.append(s);
+        }
+        return sb.toAttributedString();
+    }
+
+    public AttributedStringBuilder() {
+        this(64);
+    }
+
+    public AttributedStringBuilder(int capacity) {
+        buffer = new char[capacity];
+        style = new int[capacity];
+        length = 0;
+    }
+
+    @Override
+    public int length() {
+        return length;
+    }
+
+    @Override
+    public char charAt(int index) {
+        return buffer[index];
+    }
+
+    @Override
+    public AttributedStyle styleAt(int index) {
+        return new AttributedStyle(style[index], style[index]);
+    }
+
+    @Override
+    int styleCodeAt(int index) {
+        return style[index];
+    }
+
+    @Override
+    protected char[] buffer() {
+        return buffer;
+    }
+
+    @Override
+    protected int offset() {
+        return 0;
+    }
+
+    @Override
+    public AttributedString subSequence(int start, int end) {
+        return new AttributedString(
+                Arrays.copyOfRange(buffer, start, end),
+                Arrays.copyOfRange(style, start, end),
+                0,
+                end - start);
+    }
+
+    @Override
+    public AttributedStringBuilder append(CharSequence csq) {
+        return append(new AttributedString(csq, current));
+    }
+
+    @Override
+    public AttributedStringBuilder append(CharSequence csq, int start, int end) {
+        return append(csq.subSequence(start, end));
+    }
+
+    @Override
+    public AttributedStringBuilder append(char c) {
+        return append(Character.toString(c));
+    }
+
+    public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) {
+        return append(new AttributedString(csq, style));
+    }
+
+    public AttributedStringBuilder style(AttributedStyle style) {
+        current = style;
+        return this;
+    }
+
+    public AttributedStringBuilder style(Function<AttributedStyle,AttributedStyle> style) {
+        current = style.apply(current);
+        return this;
+    }
+
+    public AttributedStringBuilder styled(Function<AttributedStyle,AttributedStyle> style, CharSequence cs) {
+        return styled(style, sb -> sb.append(cs));
+    }
+
+    public AttributedStringBuilder styled(AttributedStyle style, CharSequence cs) {
+        return styled(s -> style, sb -> sb.append(cs));
+    }
+
+    public AttributedStringBuilder styled(Function<AttributedStyle,AttributedStyle> style, Consumer<AttributedStringBuilder> consumer) {
+        AttributedStyle prev = current;
+        current = style.apply(prev);
+        consumer.accept(this);
+        current = prev;
+        return this;
+    }
+
+    public AttributedStyle style() {
+        return current;
+    }
+
+    public AttributedStringBuilder append(AttributedString str) {
+        return append((AttributedCharSequence) str, 0, str.length());
+    }
+
+    public AttributedStringBuilder append(AttributedString str, int start, int end) {
+        return append((AttributedCharSequence) str, start, end);
+    }
+
+    public AttributedStringBuilder append(AttributedCharSequence str) {
+        return append(str, 0, str.length());
+    }
+
+    public AttributedStringBuilder append(AttributedCharSequence str, int start, int end) {
+        ensureCapacity(length + end - start);
+        for (int i = start; i < end; i++) {
+            char c = str.charAt(i);
+            int s = str.styleCodeAt(i) & ~current.getMask() | current.getStyle();
+            if (tabs > 0 && c == '\t') {
+                insertTab(new AttributedStyle(s, 0));
+            } else {
+                ensureCapacity(length + 1);
+                buffer[length] = c;
+                style[length] = s;
+                if (c == '\n') {
+                    lastLineLength = 0;
+                } else {
+                    lastLineLength++;
+                }
+                length++;
+            }
+        }
+        return this;
+    }
+
+    protected void ensureCapacity(int nl) {
+        if (nl > buffer.length) {
+            int s = Math.max(buffer.length, 1);
+            while (s <= nl) {
+                s *= 2;
+            }
+            buffer = Arrays.copyOf(buffer, s);
+            style = Arrays.copyOf(style, s);
+        }
+    }
+
+    public void appendAnsi(String ansi) {
+        ansiAppend(ansi);
+    }
+
+    public AttributedStringBuilder ansiAppend(String ansi) {
+        int ansiStart = 0;
+        int ansiState = 0;
+        ensureCapacity(length + ansi.length());
+        for (int i = 0; i < ansi.length(); i++) {
+            char c = ansi.charAt(i);
+            if (ansiState == 0 && c == 27) {
+                ansiState++;
+            } else if (ansiState == 1 && c == '[') {
+                ansiState++;
+                ansiStart = i + 1;
+            } else if (ansiState == 2) {
+                if (c == 'm') {
+                    String[] params = ansi.substring(ansiStart, i).split(";");
+                    int j = 0;
+                    while (j < params.length) {
+                        int ansiParam = params[j].isEmpty() ? 0 : Integer.parseInt(params[j]);
+                        switch (ansiParam) {
+                            case 0:
+                                current = AttributedStyle.DEFAULT;
+                                break;
+                            case 1:
+                                current = current.bold();
+                                break;
+                            case 2:
+                                current = current.faint();
+                                break;
+                            case 3:
+                                current = current.italic();
+                                break;
+                            case 4:
+                                current = current.underline();
+                                break;
+                            case 5:
+                                current = current.blink();
+                                break;
+                            case 7:
+                                current = current.inverse();
+                                break;
+                            case 8:
+                                current = current.conceal();
+                                break;
+                            case 9:
+                                current = current.crossedOut();
+                                break;
+                            case 22:
+                                current = current.boldOff().faintOff();
+                                break;
+                            case 23:
+                                current = current.italicOff();
+                                break;
+                            case 24:
+                                current = current.underlineOff();
+                                break;
+                            case 25:
+                                current = current.blinkOff();
+                                break;
+                            case 27:
+                                current = current.inverseOff();
+                                break;
+                            case 28:
+                                current = current.concealOff();
+                                break;
+                            case 29:
+                                current = current.crossedOutOff();
+                                break;
+                            case 30:
+                            case 31:
+                            case 32:
+                            case 33:
+                            case 34:
+                            case 35:
+                            case 36:
+                            case 37:
+                                current = current.foreground(ansiParam - 30);
+                                break;
+                            case 39:
+                                current = current.foregroundOff();
+                                break;
+                            case 40:
+                            case 41:
+                            case 42:
+                            case 43:
+                            case 44:
+                            case 45:
+                            case 46:
+                            case 47:
+                                current = current.background(ansiParam - 40);
+                                break;
+                            case 49:
+                                current = current.backgroundOff();
+                                break;
+                            case 38:
+                            case 48:
+                                if (j + 1 < params.length) {
+                                    int ansiParam2 = Integer.parseInt(params[++j]);
+                                    if (ansiParam2 == 2) {
+                                        if (j + 3 < params.length) {
+                                            int r = Integer.parseInt(params[++j]);
+                                            int g = Integer.parseInt(params[++j]);
+                                            int b = Integer.parseInt(params[++j]);
+                                            // convert to 256 colors
+                                            int col = 16 + (r >> 3) * 36 + (g >> 3) * 6 + (b >> 3);
+                                            if (ansiParam == 38) {
+                                                current = current.foreground(col);
+                                            } else {
+                                                current = current.background(col);
+                                            }
+                                        }
+                                    } else if (ansiParam2 == 5) {
+                                        if (j + 1 < params.length) {
+                                            int col = Integer.parseInt(params[++j]);
+                                            if (ansiParam == 38) {
+                                                current = current.foreground(col);
+                                            } else {
+                                                current = current.background(col);
+                                            }
+                                        }
+                                    }
+                                }
+                                break;
+                            case 90:
+                            case 91:
+                            case 92:
+                            case 93:
+                            case 94:
+                            case 95:
+                            case 96:
+                            case 97:
+                                current = current.foreground(ansiParam - 90 + 8);
+                                break;
+                            case 100:
+                            case 101:
+                            case 102:
+                            case 103:
+                            case 104:
+                            case 105:
+                            case 106:
+                            case 107:
+                                current = current.background(ansiParam - 100 + 8);
+                                break;
+                        }
+                        j++;
+                    }
+                    ansiState = 0;
+                } else if (!(c >= '0' && c <= '9' || c == ';')) {
+                    // This is not a SGR code, so ignore
+                    ansiState = 0;
+                }
+            } else if (c == '\t' && tabs > 0) {
+                insertTab(current);
+            } else {
+                ensureCapacity(length + 1);
+                buffer[length] = c;
+                style[length] = this.current.getStyle();
+                if (c == '\n') {
+                    lastLineLength = 0;
+                } else {
+                    lastLineLength++;
+                }
+                length++;
+            }
+        }
+        return this;
+    }
+
+    protected void insertTab(AttributedStyle s) {
+        int nb = tabs - lastLineLength % tabs;
+        ensureCapacity(length + nb);
+        for (int i = 0; i < nb; i++) {
+            buffer[length] = ' ';
+            style[length] = s.getStyle();
+            length++;
+        }
+        lastLineLength += nb;
+    }
+
+    public void setLength(int l) {
+        length = l;
+    }
+
+    /**
+     * Set the number of spaces a tab is expanded to. Tab size cannot be changed
+     * after text has been added to prevent inconsistent indentation.
+     *
+     * If tab size is set to 0, tabs are not expanded (the default).
+     * @param tabsize Spaces per tab or 0 for no tab expansion. Must be non-negative
+     * @return this
+     */
+    public AttributedStringBuilder tabs(int tabsize) {
+        if (length > 0) {
+            throw new IllegalStateException("Cannot change tab size after appending text");
+        }
+        if (tabsize < 0) {
+            throw new IllegalArgumentException("Tab size must be non negative");
+        }
+        this.tabs = tabsize;
+        return this;
+    }
+
+    public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) {
+        Matcher matcher = pattern.matcher(this);
+        while (matcher.find()) {
+            for (int i = matcher.start(); i < matcher.end(); i++) {
+                style[i] = (style[i] & ~s.getMask()) | s.getStyle();
+            }
+        }
+        return this;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+/**
+ * Text styling.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class AttributedStyle {
+
+    public static final int BLACK =     0;
+    public static final int RED =       1;
+    public static final int GREEN =     2;
+    public static final int YELLOW =    3;
+    public static final int BLUE =      4;
+    public static final int MAGENTA =   5;
+    public static final int CYAN =      6;
+    public static final int WHITE =     7;
+
+    public static final int BRIGHT =    8;
+
+    static final int F_BOLD         = 0x00000001;
+    static final int F_FAINT        = 0x00000002;
+    static final int F_ITALIC       = 0x00000004;
+    static final int F_UNDERLINE    = 0x00000008;
+    static final int F_BLINK        = 0x00000010;
+    static final int F_INVERSE      = 0x00000020;
+    static final int F_CONCEAL      = 0x00000040;
+    static final int F_CROSSED_OUT  = 0x00000080;
+    static final int F_FOREGROUND   = 0x00000100;
+    static final int F_BACKGROUND   = 0x00000200;
+    static final int F_HIDDEN       = 0x00000400;
+
+    static final int MASK           = 0x000007FF;
+
+    static final int FG_COLOR_EXP    = 16;
+    static final int BG_COLOR_EXP    = 24;
+    static final int FG_COLOR        = 0xFF << FG_COLOR_EXP;
+    static final int BG_COLOR        = 0xFF << BG_COLOR_EXP;
+
+    public static final AttributedStyle DEFAULT = new AttributedStyle();
+    public static final AttributedStyle BOLD = DEFAULT.bold();
+    public static final AttributedStyle BOLD_OFF = DEFAULT.boldOff();
+    public static final AttributedStyle INVERSE = DEFAULT.inverse();
+    public static final AttributedStyle INVERSE_OFF = DEFAULT.inverseOff();
+    public static final AttributedStyle HIDDEN = DEFAULT.hidden();
+    public static final AttributedStyle HIDDEN_OFF = DEFAULT.hiddenOff();
+
+    final int style;
+    final int mask;
+
+    public AttributedStyle() {
+        this(0, 0);
+    }
+
+    public AttributedStyle(AttributedStyle s) {
+        this(s.style, s.mask);
+    }
+
+    public AttributedStyle(int style, int mask) {
+        this.style = style;
+        this.mask = mask & MASK | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0)
+                                | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0);
+    }
+
+    public AttributedStyle bold() {
+        return new AttributedStyle(style | F_BOLD, mask | F_BOLD);
+    }
+
+    public AttributedStyle boldOff() {
+        return new AttributedStyle(style & ~F_BOLD, mask | F_BOLD);
+    }
+
+    public AttributedStyle boldDefault() {
+        return new AttributedStyle(style & ~F_BOLD, mask & ~F_BOLD);
+    }
+
+    public AttributedStyle faint() {
+        return new AttributedStyle(style | F_FAINT, mask | F_FAINT);
+    }
+
+    public AttributedStyle faintOff() {
+        return new AttributedStyle(style & ~F_FAINT, mask | F_FAINT);
+    }
+
+    public AttributedStyle faintDefault() {
+        return new AttributedStyle(style & ~F_FAINT, mask & ~F_FAINT);
+    }
+
+    public AttributedStyle italic() {
+        return new AttributedStyle(style | F_ITALIC, mask | F_ITALIC);
+    }
+
+    public AttributedStyle italicOff() {
+        return new AttributedStyle(style & ~F_ITALIC, mask | F_ITALIC);
+    }
+
+    public AttributedStyle italicDefault() {
+        return new AttributedStyle(style & ~F_ITALIC, mask & ~F_ITALIC);
+    }
+
+    public AttributedStyle underline() {
+        return new AttributedStyle(style | F_UNDERLINE, mask | F_UNDERLINE);
+    }
+
+    public AttributedStyle underlineOff() {
+        return new AttributedStyle(style & ~F_UNDERLINE, mask | F_UNDERLINE);
+    }
+
+    public AttributedStyle underlineDefault() {
+        return new AttributedStyle(style & ~F_UNDERLINE, mask & ~F_UNDERLINE);
+    }
+
+    public AttributedStyle blink() {
+        return new AttributedStyle(style | F_BLINK, mask | F_BLINK);
+    }
+
+    public AttributedStyle blinkOff() {
+        return new AttributedStyle(style & ~F_BLINK, mask | F_BLINK);
+    }
+
+    public AttributedStyle blinkDefault() {
+        return new AttributedStyle(style & ~F_BLINK, mask & ~F_BLINK);
+    }
+
+    public AttributedStyle inverse() {
+        return new AttributedStyle(style | F_INVERSE, mask | F_INVERSE);
+    }
+
+    public AttributedStyle inverseNeg() {
+        int s = (style & F_INVERSE) != 0 ? style & ~F_INVERSE : style | F_INVERSE;
+        return new AttributedStyle(s, mask | F_INVERSE);
+    }
+
+    public AttributedStyle inverseOff() {
+        return new AttributedStyle(style & ~F_INVERSE, mask | F_INVERSE);
+    }
+
+    public AttributedStyle inverseDefault() {
+        return new AttributedStyle(style & ~F_INVERSE, mask & ~F_INVERSE);
+    }
+
+    public AttributedStyle conceal() {
+        return new AttributedStyle(style | F_CONCEAL, mask | F_CONCEAL);
+    }
+
+    public AttributedStyle concealOff() {
+        return new AttributedStyle(style & ~F_CONCEAL, mask | F_CONCEAL);
+    }
+
+    public AttributedStyle concealDefault() {
+        return new AttributedStyle(style & ~F_CONCEAL, mask & ~F_CONCEAL);
+    }
+
+    public AttributedStyle crossedOut() {
+        return new AttributedStyle(style | F_CROSSED_OUT, mask | F_CROSSED_OUT);
+    }
+
+    public AttributedStyle crossedOutOff() {
+        return new AttributedStyle(style & ~F_CROSSED_OUT, mask | F_CROSSED_OUT);
+    }
+
+    public AttributedStyle crossedOutDefault() {
+        return new AttributedStyle(style & ~F_CROSSED_OUT, mask & ~F_CROSSED_OUT);
+    }
+
+    public AttributedStyle foreground(int color) {
+        return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND | ((color << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND);
+    }
+
+    public AttributedStyle foregroundOff() {
+        return new AttributedStyle(style & ~FG_COLOR & ~F_FOREGROUND, mask | F_FOREGROUND);
+    }
+
+    public AttributedStyle foregroundDefault() {
+        return new AttributedStyle(style & ~FG_COLOR & ~F_FOREGROUND, mask & ~(F_FOREGROUND | FG_COLOR));
+    }
+
+    public AttributedStyle background(int color) {
+        return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND | ((color << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND);
+    }
+
+    public AttributedStyle backgroundOff() {
+        return new AttributedStyle(style & ~BG_COLOR & ~F_BACKGROUND, mask | F_BACKGROUND);
+    }
+
+    public AttributedStyle backgroundDefault() {
+        return new AttributedStyle(style & ~BG_COLOR & ~F_BACKGROUND, mask & ~(F_BACKGROUND | BG_COLOR));
+    }
+
+    /**
+     * The hidden flag can be used to embed custom escape sequences.
+     * The characters are considered being 0-column long and will be printed as-is.
+     * The user is responsible for ensuring that those sequences do not move the cursor.
+     *
+     * @return the new style
+     */
+    public AttributedStyle hidden() {
+        return new AttributedStyle(style | F_HIDDEN, mask | F_HIDDEN);
+    }
+
+    public AttributedStyle hiddenOff() {
+        return new AttributedStyle(style & ~F_HIDDEN, mask | F_HIDDEN);
+    }
+
+    public AttributedStyle hiddenDefault() {
+        return new AttributedStyle(style & ~F_HIDDEN, mask & ~F_HIDDEN);
+    }
+
+    public int getStyle() {
+        return style;
+    }
+
+    public int getMask() {
+        return mask;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        AttributedStyle that = (AttributedStyle) o;
+        if (style != that.style) return false;
+        return mask == that.mask;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = style;
+        result = 31 * result + mask;
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+
+public class ClosedException extends IOException {
+
+    private static final long serialVersionUID = 3085420657077696L;
+
+    public ClosedException() {
+    }
+
+    public ClosedException(String message) {
+        super(message);
+    }
+
+    public ClosedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ClosedException(Throwable cause) {
+        super(cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.BufferedReader;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_COLOR_DISTANCE;
+
+public class Colors {
+
+    /**
+     * Default 256 colors palette
+     */
+    public static final int[] DEFAULT_COLORS_256 = {
+            0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xc0c0c0,
+            0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
+
+            0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
+            0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af,
+            0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
+            0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
+            0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
+            0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
+            0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
+            0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
+            0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
+            0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
+            0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
+            0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
+            0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
+            0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
+            0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
+            0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
+            0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
+            0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
+            0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
+            0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
+            0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
+            0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
+            0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
+            0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
+            0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
+            0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
+            0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
+
+            0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
+            0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
+            0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee,
+    };
+
+    /** D50 illuminant for CAM color spaces */
+    public static final double[] D50 = new double[] { 96.422f, 100.0f,  82.521f };
+    /** D65 illuminant for CAM color spaces */
+    public static final double[] D65 = new double[] { 95.047, 100.0, 108.883 };
+
+    /** Average surrounding for CAM color spaces */
+    public static final double[] averageSurrounding = new double[] { 1.0, 0.690, 1.0 };
+    /** Dim surrounding for CAM color spaces */
+    public static final double[] dimSurrounding =     new double[] { 0.9, 0.590, 0.9 };
+    /** Dark surrounding for CAM color spaces */
+    public static final double[] darkSurrounding =    new double[] { 0.8, 0.525, 0.8 };
+
+    /** sRGB encoding environment */
+    public static final double[] sRGB_encoding_environment = vc(D50,  64.0,  64/5, dimSurrounding);
+    /** sRGB typical environment */
+    public static final double[] sRGB_typical_environment  = vc(D50, 200.0, 200/5, averageSurrounding);
+    /** Adobe RGB environment */
+    public static final double[] AdobeRGB_environment      = vc(D65, 160.0, 160/5, averageSurrounding);
+
+    private static int[] COLORS_256 = DEFAULT_COLORS_256;
+
+    private static Map<String, Integer> COLOR_NAMES;
+
+    public static void setRgbColors(int[] colors) {
+        if (colors == null || colors.length != 256) {
+            throw new IllegalArgumentException();
+        }
+        COLORS_256 = colors;
+    }
+
+    public static int rgbColor(int col) {
+        return COLORS_256[col];
+    }
+
+    public static Integer rgbColor(String name) {
+        if (COLOR_NAMES == null) {
+            Map<String, Integer> colors = new LinkedHashMap<>();
+            try (InputStream is = InfoCmp.class.getResourceAsStream("colors.txt");
+                 BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+                br.lines().map(String::trim)
+                        .filter(s -> !s.startsWith("#"))
+                        .filter(s -> !s.isEmpty())
+                        .forEachOrdered(s -> {
+                            colors.put(s, colors.size());
+                        });
+                COLOR_NAMES = colors;
+            } catch (IOException e) {
+                throw new IOError(e);
+            }
+        }
+        return COLOR_NAMES.get(name);
+    }
+
+    public static int roundColor(int col, int max) {
+        return roundColor(col, max, null);
+    }
+
+    public static int roundColor(int col, int max, String dist) {
+        if (col >= max) {
+            int c = COLORS_256[col];
+            col = roundColor(c, COLORS_256, max, dist);
+        }
+        return col;
+    }
+
+    public static int roundRgbColor(int r, int g, int b, int max) {
+        return roundColor((r << 16) + (g << 8) + b, COLORS_256, max, (String) null);
+    }
+
+    private static int roundColor(int color, int[] colors, int max, String dist) {
+        return roundColor(color, colors, max, getDistance(dist));
+    }
+
+    private interface Distance {
+        double compute(int c1, int c2);
+    }
+
+    private static int roundColor(int color, int[] colors, int max, Distance distance) {
+        double best_distance = Integer.MAX_VALUE;
+        int best_index = Integer.MAX_VALUE;
+        for (int idx = 0; idx < max; idx++) {
+            double d = distance.compute(color, colors[idx]);
+            if (d <= best_distance) {
+                best_index = idx;
+                best_distance = d;
+            }
+        }
+        return best_index;
+    }
+
+    private static Distance getDistance(String dist) {
+        if (dist == null) {
+            dist = System.getProperty(PROP_COLOR_DISTANCE, "cie76");
+        }
+        return doGetDistance(dist);
+    }
+
+    private static Distance doGetDistance(String dist) {
+        if (dist.equals("rgb")) {
+            return (p1, p2) -> {
+                // rgb: see https://www.compuphase.com/cmetric.htm
+                double[] c1 = rgb(p1);
+                double[] c2 = rgb(p2);
+                double rmean = (c1[0] + c2[0]) / 2.0;
+                double[] w = { 2.0 + rmean, 4.0, 3.0 - rmean };
+                return scalar(c1, c2, w);
+            };
+        }
+        if (dist.matches("rgb\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) {
+            return (p1, p2) -> scalar(rgb(p1), rgb(p2), getWeights(dist));
+        }
+        if (dist.equals("lab") || dist.equals("cie76")) {
+            return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2));
+        }
+        if (dist.matches("lab\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) {
+            double[] w = getWeights(dist);
+            return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] { w[0], w[1], w[1] });
+        }
+        if (dist.equals("cie94")) {
+            return (p1, p2) -> cie94(rgb2cielab(p1), rgb2cielab(p2));
+        }
+        if (dist.equals("cie00") || dist.equals("cie2000")) {
+            return (p1, p2) -> cie00(rgb2cielab(p1), rgb2cielab(p2));
+        }
+        if (dist.equals("cam02")) {
+            return (p1, p2) -> cam02(p1, p2, sRGB_typical_environment);
+        }
+        if (dist.equals("camlab")) {
+            return (p1, p2) -> {
+                double[] c1 = camlab(p1, sRGB_typical_environment);
+                double[] c2 = camlab(p2, sRGB_typical_environment);
+                return scalar(c1, c2);
+            };
+        }
+        if (dist.matches("camlab\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) {
+            return (p1, p2) -> {
+                double[] c1 = camlab(p1, sRGB_typical_environment);
+                double[] c2 = camlab(p2, sRGB_typical_environment);
+                double[] w = getWeights(dist);
+                return scalar(c1, c2, new double[] { w[0], w[1], w[1] });
+            };
+        }
+        if (dist.matches("camlch")) {
+            return (p1, p2) -> {
+                double[] c1 = camlch(p1, sRGB_typical_environment);
+                double[] c2 = camlch(p2, sRGB_typical_environment);
+                return camlch(c1, c2);
+            };
+        }
+        if (dist.matches("camlch\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) {
+            return (p1, p2) -> {
+                double[] c1 = camlch(p1, sRGB_typical_environment);
+                double[] c2 = camlch(p2, sRGB_typical_environment);
+                double[] w = getWeights(dist);
+                return camlch(c1, c2, w);
+            };
+        }
+        throw new IllegalArgumentException("Unsupported distance function: " + dist);
+    }
+
+    private static double[] getWeights(String dist) {
+        String[] weights = dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(",");
+        return Stream.of(weights).mapToDouble(Double::parseDouble).toArray();
+    }
+
+    private static double scalar(double[] c1, double[] c2, double[] w) {
+        return sqr((c1[0] - c2[0]) * w[0])
+             + sqr((c1[1] - c2[1]) * w[1])
+             + sqr((c1[2] - c2[2]) * w[2]);
+    }
+
+    private static double scalar(double[] c1, double[] c2) {
+        return sqr(c1[0] - c2[0])
+             + sqr(c1[1] - c2[1])
+             + sqr(c1[2] - c2[2]);
+    }
+
+    private static final int L = 0;
+    private static final int A = 1;
+    private static final int B = 2;
+    private static final int X = 0;
+    private static final int Y = 1;
+    private static final int Z = 2;
+    private static final double kl = 2.0;
+    private static final double kc = 1.0;
+    private static final double kh = 1.0;
+    private static final double k1 = 0.045;
+    private static final double k2 = 0.015;
+
+    private static double cie94(double[] lab1, double[] lab2) {
+        double dl = lab1[L] - lab2[L];
+        double da = lab1[A] - lab2[A];
+        double db = lab1[B] - lab2[B];
+        double c1 = Math.sqrt(lab1[A] * lab1[A] + lab1[B] * lab1[B]);
+        double c2 = Math.sqrt(lab2[A] * lab2[A] + lab2[B] * lab2[B]);
+        double dc = c1 - c2;
+        double dh = da * da + db * db - dc * dc;
+        dh = dh < 0.0 ? 0.0 : Math.sqrt(dh);
+        double sl = 1.0;
+        double sc = 1.0 + k1 * c1;
+        double sh = 1.0 + k2 * c1;
+        double dLKlsl = dl / (kl * sl);
+        double dCkcsc = dc / (kc * sc);
+        double dHkhsh = dh / (kh * sh);
+        return dLKlsl * dLKlsl + dCkcsc * dCkcsc + dHkhsh * dHkhsh;
+    }
+
+    private static double cie00(double[] lab1, double[] lab2) {
+        double c_star_1_ab = Math.sqrt(lab1[A] * lab1[A] + lab1[B] * lab1[B]);
+        double c_star_2_ab = Math.sqrt(lab2[A] * lab2[A] + lab2[B] * lab2[B]);
+        double c_star_average_ab = (c_star_1_ab + c_star_2_ab) / 2.0;
+        double c_star_average_ab_pot_3 = c_star_average_ab * c_star_average_ab * c_star_average_ab;
+        double c_star_average_ab_pot_7 = c_star_average_ab_pot_3 * c_star_average_ab_pot_3 * c_star_average_ab;
+        double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); //25^7
+        double a1_prime = (1.0 + G) * lab1[A];
+        double a2_prime = (1.0 + G) * lab2[A];
+        double C_prime_1 = Math.sqrt(a1_prime * a1_prime + lab1[B] * lab1[B]);
+        double C_prime_2 = Math.sqrt(a2_prime * a2_prime + lab2[B] * lab2[B]);
+        double h_prime_1 = (Math.toDegrees(Math.atan2(lab1[B], a1_prime)) + 360.0) % 360.0;
+        double h_prime_2 = (Math.toDegrees(Math.atan2(lab2[B], a2_prime)) + 360.0) % 360.0;
+        double delta_L_prime = lab2[L] - lab1[L];
+        double delta_C_prime = C_prime_2 - C_prime_1;
+        double h_bar = Math.abs(h_prime_1 - h_prime_2);
+        double delta_h_prime;
+        if (C_prime_1 * C_prime_2 == 0.0) {
+            delta_h_prime = 0.0;
+        } else if (h_bar <= 180.0) {
+            delta_h_prime = h_prime_2 - h_prime_1;
+        } else if (h_prime_2 <= h_prime_1) {
+            delta_h_prime = h_prime_2 - h_prime_1 + 360.0;
+        } else {
+            delta_h_prime = h_prime_2 - h_prime_1 - 360.0;
+        }
+        double delta_H_prime = 2.0 * Math.sqrt(C_prime_1 * C_prime_2) * Math.sin(Math.toRadians(delta_h_prime / 2.0));
+        double L_prime_average = (lab1[L] + lab2[L]) / 2.0;
+        double C_prime_average = (C_prime_1 + C_prime_2) / 2.0;
+        double h_prime_average;
+        if (C_prime_1 * C_prime_2 == 0.0) {
+            h_prime_average = 0.0;
+        } else if (h_bar <= 180.0) {
+            h_prime_average = (h_prime_1 + h_prime_2) / 2.0;
+        } else if ((h_prime_1 + h_prime_2) < 360.0) {
+            h_prime_average = (h_prime_1 + h_prime_2 + 360.0) / 2.0;
+        } else {
+            h_prime_average = (h_prime_1 + h_prime_2 - 360.0) / 2.0;
+        }
+        double L_prime_average_minus_50 = L_prime_average - 50.0;
+        double L_prime_average_minus_50_square = L_prime_average_minus_50 * L_prime_average_minus_50;
+        double T = 1.0
+                - 0.17 * Math.cos(Math.toRadians(h_prime_average - 30.0))
+                + 0.24 * Math.cos(Math.toRadians(h_prime_average * 2.0))
+                + 0.32 * Math.cos(Math.toRadians(h_prime_average * 3.0 + 6.0))
+                - 0.20 * Math.cos(Math.toRadians(h_prime_average * 4.0 - 63.0));
+        double S_L = 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square));
+        double S_C = 1.0 + 0.045 * C_prime_average;
+        double S_H = 1.0 + 0.015 * T * C_prime_average;
+        double h_prime_average_minus_275_div_25 = (h_prime_average - 275.0) / (25.0);
+        double h_prime_average_minus_275_div_25_square = h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25;
+        double delta_theta = 30.0 * Math.exp(-h_prime_average_minus_275_div_25_square);
+        double C_prime_average_pot_3 = C_prime_average * C_prime_average * C_prime_average;
+        double C_prime_average_pot_7 = C_prime_average_pot_3 * C_prime_average_pot_3 * C_prime_average;
+        double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); //25^7
+        double R_T = - Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C;
+        double dLKlsl = delta_L_prime / (kl * S_L);
+        double dCkcsc = delta_C_prime / (kc * S_C);
+        double dHkhsh = delta_H_prime / (kh * S_H);
+        return dLKlsl * dLKlsl + dCkcsc * dCkcsc + dHkhsh * dHkhsh + R_T * dCkcsc * dHkhsh;
+    }
+
+    private static double cam02(int p1, int p2, double[] vc) {
+        double[] c1 = jmh2ucs(camlch(p1, vc));
+        double[] c2 = jmh2ucs(camlch(p2, vc));
+        return scalar(c1, c2);
+    }
+
+    private static double[] jmh2ucs(double[] lch) {
+        double sJ = ((1.0 + 100 * 0.007) * lch[0]) / (1.0 + 0.007 * lch[0]);
+        double sM = ((1.0 / 0.0228) * Math.log(1.0 + 0.0228 * lch[1]));
+        double a = sM * Math.cos(Math.toRadians(lch[2]));
+        double b = sM * Math.sin(Math.toRadians(lch[2]));
+        return new double[] {sJ, a, b };
+    }
+
+    static double camlch(double[] c1, double[] c2) {
+        return camlch(c1, c2, new double[] { 1.0, 1.0, 1.0 });
+    }
+
+    static double camlch(double[] c1, double[] c2, double[] w) {
+        // normalize weights to correlate range
+        double lightnessWeight = w[0] / 100.0;
+        double colorfulnessWeight = w[1] / 120.0;
+        double hueWeight = w[2] / 360.0;
+        // calculate sort-of polar distance
+        double dl = (c1[0] - c2[0]) * lightnessWeight;
+        double dc = (c1[1] - c2[1]) * colorfulnessWeight;
+        double dh = hueDifference(c1[2], c2[2], 360.0) * hueWeight;
+        return dl * dl + dc * dc + dh * dh;
+    }
+
+    private static double hueDifference(double hue1, double hue2, double c) {
+        double difference = (hue2 - hue1) % c;
+        double ch = c / 2;
+        if (difference > ch)
+            difference -= c;
+        if (difference < -ch)
+            difference += c;
+        return difference;
+    }
+
+    private static double[] rgb(int color) {
+        int r = (color >> 16) & 0xFF;
+        int g = (color >>  8) & 0xFF;
+        int b = (color >>  0) & 0xFF;
+        return new double[] { r / 255.0, g / 255.0, b / 255.0 };
+    }
+
+    static double[] rgb2xyz(int color) {
+        return rgb2xyz(rgb(color));
+    }
+
+    static double[] rgb2cielab(int color) {
+        return rgb2cielab(rgb(color));
+    }
+
+    static double[] camlch(int color) {
+        return camlch(color, sRGB_typical_environment);
+    }
+
+    static double[] camlch(int color, double[] vc) {
+        return xyz2camlch(rgb2xyz(color), vc);
+    }
+
+    static double[] camlab(int color) {
+        return camlab(color, sRGB_typical_environment);
+    }
+
+    static double[] camlab(int color, double[] vc) {
+        return lch2lab(camlch(color, vc));
+    }
+
+    static double[] lch2lab(double[] lch) {
+        double toRad = Math.PI / 180;
+        return new double[] { lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad) };
+    }
+
+    private static double[] xyz2camlch(double[] xyz, double[] vc) {
+        double[] XYZ = new double[] {xyz[0] * 100.0, xyz[1] * 100.0, xyz[2] * 100.0};
+        double[] cam = forwardTransform(XYZ, vc);
+        return new double[] { cam[J], cam[M], cam[h] };
+    }
+
+    /** Lightness */
+    public static final int J = 0;
+    /** Brightness */
+    public static final int Q = 1;
+    /** Chroma */
+    public static final int C = 2;
+    /** Colorfulness */
+    public static final int M = 3;
+    /** Saturation */
+    public static final int s = 4;
+    /** Hue Composition / Hue Quadrature */
+    public static final int H = 5;
+    /** Hue */
+    public static final int h = 6;
+
+
+    /** CIECAM02 appearance correlates */
+    private static double[] forwardTransform(double[] XYZ, double[] vc) {
+        // calculate sharpened cone response
+        double[] RGB = forwardPreAdaptationConeResponse(XYZ);
+        // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions in D
+        double[] RGB_c = forwardPostAdaptationConeResponse(RGB, vc);
+        // calculate HPE equal area cone fundamentals
+        double[] RGBPrime = CAT02toHPE(RGB_c);
+        // calculate response-compressed postadaptation cone response
+        double[] RGBPrime_a = forwardResponseCompression(RGBPrime, vc);
+        // calculate achromatic response
+        double A = (2.0 * RGBPrime_a[0] + RGBPrime_a[1] + RGBPrime_a[2] / 20.0 - 0.305) * vc[VC_N_BB];
+        // calculate lightness
+        double J = 100.0 * Math.pow(A / vc[VC_A_W], vc[VC_Z] * vc[VC_C]);
+        // calculate redness-greenness and yellowness-blueness color opponent values
+        double a = RGBPrime_a[0] + (-12.0 * RGBPrime_a[1] + RGBPrime_a[2]) / 11.0;
+        double b = (RGBPrime_a[0] + RGBPrime_a[1] - 2.0 * RGBPrime_a[2]) / 9.0;
+        // calculate hue angle
+        double h = (Math.toDegrees(Math.atan2(b, a)) + 360.0) % 360.0;
+        // calculate eccentricity
+        double e = ((12500.0 / 13.0) * vc[VC_N_C] * vc[VC_N_CB]) * (Math.cos(Math.toRadians(h) + 2.0) + 3.8);
+        // get t
+        double t = e * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]);
+        // calculate brightness
+        double Q = (4.0 / vc[VC_C]) * Math.sqrt(J / 100.0) * (vc[VC_A_W] + 4.0) * Math.pow(vc[VC_F_L], 0.25);
+        // calculate the correlates of chroma, colorfulness, and saturation
+        double C = Math.signum(t) * Math.pow(Math.abs(t), 0.9) * Math.sqrt(J / 100.0) * Math.pow(1.64- Math.pow(0.29, vc[VC_N]), 0.73);
+        double M = C * Math.pow(vc[VC_F_L], 0.25);
+        double s = 100.0 * Math.sqrt(M / Q);
+        // calculate hue composition
+        double H = calculateH(h);
+        return new double[] { J, Q, C, M, s, H, h };
+    }
+
+    private static double calculateH(double h) {
+        if (h < 20.14)
+            h = h + 360;
+        double i;
+        if (h >= 20.14 && h < 90.0) {  // index i = 1
+            i = (h - 20.14) / 0.8;
+            return 100.0 * i / (i + (90 - h) / 0.7);
+        } else if (h < 164.25) { // index i = 2
+            i = (h - 90) / 0.7;
+            return 100.0 + 100.0 * i / (i + (164.25 - h) / 1);
+        } else if (h < 237.53) {  // index i = 3
+            i = (h - 164.25) / 1.0;
+            return 200.0 + 100.0 * i / (i + (237.53 - h) / 1.2);
+        } else if (h <= 380.14) {  // index i = 4
+            i = (h - 237.53) / 1.2;
+            double H = 300.0 + 100.0 * i / (i + (380.14 - h) / 0.8);
+            // don't use 400 if we can use 0
+            if (H <= 400.0 && H >= 399.999)
+                H = 0;
+            return H;
+        } else {
+            throw new IllegalArgumentException("h outside assumed range 0..360: " + Double.toString(h));
+        }
+    }
+
+    private static double[] forwardResponseCompression(double[] RGB, double[] vc) {
+        double[] result = new double[3];
+        for(int channel = 0; channel < RGB.length; channel++) {
+            if(RGB[channel] >= 0) {
+                double n = Math.pow(vc[VC_F_L] * RGB[channel] / 100.0, 0.42);
+                result[channel] = 400.0 * n / (n + 27.13) + 0.1;
+            } else {
+                double n = Math.pow(-1.0 * vc[VC_F_L] * RGB[channel] / 100.0, 0.42);
+                result[channel] = -400.0 * n / (n + 27.13) + 0.1;
+            }
+        }
+        return result;
+    }
+
+    private static double[] forwardPostAdaptationConeResponse(double[] RGB, double[] vc) {
+        return new double[] { vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2] };
+    }
+
+    public static double[] CAT02toHPE(double[] RGB) {
+        double[] RGBPrime = new double[3];
+        RGBPrime[0] =  0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2];
+        RGBPrime[1] =  0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2];
+        RGBPrime[2] = -0.0096280 * RGB[0] - 0.0056980 * RGB[1] + 1.0153260 * RGB[2];
+        return RGBPrime;
+    }
+
+    private static double[] forwardPreAdaptationConeResponse(double[] XYZ) {
+        double[] RGB = new double[3];
+        RGB[0] =  0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2];
+        RGB[1] = -0.7036 * XYZ[0] + 1.6975 * XYZ[1] + 0.0061 * XYZ[2];
+        RGB[2] =  0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2];
+        return RGB;
+    }
+
+    static final int SUR_F = 0;
+    static final int SUR_C = 1;
+    static final int SUR_N_C = 2;
+
+    static final int VC_X_W = 0;
+    static final int VC_Y_W = 1;
+    static final int VC_Z_W = 2;
+    static final int VC_L_A = 3;
+    static final int VC_Y_B = 4;
+    static final int VC_F =   5;
+    static final int VC_C =   6;
+    static final int VC_N_C = 7;
+
+    static final int VC_Z = 8;
+    static final int VC_N = 9;
+    static final int VC_N_BB = 10;
+    static final int VC_N_CB = 11;
+    static final int VC_A_W = 12;
+    static final int VC_F_L = 13;
+    static final int VC_D_RGB_R = 14;
+    static final int VC_D_RGB_G = 15;
+    static final int VC_D_RGB_B = 16;
+
+    static double[] vc(double[] xyz_w, double L_A, double Y_b, double[] surrounding) {
+        double[] vc = new double[17];
+        vc[VC_X_W] = xyz_w[0];
+        vc[VC_Y_W] = xyz_w[1];
+        vc[VC_Z_W] = xyz_w[2];
+        vc[VC_L_A] = L_A;
+        vc[VC_Y_B] = Y_b;
+        vc[VC_F] = surrounding[SUR_F];
+        vc[VC_C] = surrounding[SUR_C];
+        vc[VC_N_C] = surrounding[SUR_N_C];
+
+        double[] RGB_w = forwardPreAdaptationConeResponse(xyz_w);
+        double D = Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0))));
+        double Yw = xyz_w[1];
+        double[] RGB_c = new double[] {
+                (D * Yw / RGB_w[0]) + (1.0 - D),
+                (D * Yw / RGB_w[1]) + (1.0 - D),
+                (D * Yw / RGB_w[2]) + (1.0 - D),
+        };
+
+        // calculate increase in brightness and colorfulness caused by brighter viewing environments
+        double L_Ax5 = 5.0 * L_A;
+        double k = 1.0 / (L_Ax5 + 1.0);
+        double kpow4 = Math.pow(k, 4.0);
+        vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0/3.0);
+
+        // calculate response compression on J and C caused by background lightness.
+        vc[VC_N] = Y_b / Yw;
+        vc[VC_Z] = 1.48 + Math.sqrt(vc[VC_N]);
+
+        vc[VC_N_BB] = 0.725 * Math.pow(1.0 / vc[VC_N], 0.2);
+        vc[VC_N_CB] = vc[VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds)
+
+        // calculate achromatic response to white
+        double[] RGB_wc = new double[] {RGB_c[0] * RGB_w[0], RGB_c[1] * RGB_w[1], RGB_c[2] * RGB_w[2]};
+        double[] RGBPrime_w = CAT02toHPE(RGB_wc);
+        double[] RGBPrime_aw = new double[3];
+        for(int channel = 0; channel < RGBPrime_w.length; channel++) {
+            if(RGBPrime_w[channel] >= 0) {
+                double n = Math.pow(vc[VC_F_L] * RGBPrime_w[channel] / 100.0, 0.42);
+                RGBPrime_aw[channel] = 400.0 * n / (n + 27.13) + 0.1;
+            } else {
+                double n = Math.pow(-1.0 * vc[VC_F_L] * RGBPrime_w[channel] / 100.0, 0.42);
+                RGBPrime_aw[channel] = -400.0 * n / (n + 27.13) + 0.1;
+            }
+        }
+        vc[VC_A_W] = (2.0 * RGBPrime_aw[0] + RGBPrime_aw[1] + RGBPrime_aw[2] / 20.0 - 0.305) * vc[VC_N_BB];
+        vc[VC_D_RGB_R] = RGB_c[0];
+        vc[VC_D_RGB_G] = RGB_c[1];
+        vc[VC_D_RGB_B] = RGB_c[2];
+        return vc;
+    }
+
+    public static double[] rgb2cielab(double[] rgb) {
+        return xyz2lab(rgb2xyz(rgb));
+    }
+
+    private static double[] rgb2xyz(double[] rgb) {
+        double vr = pivotRgb(rgb[0]);
+        double vg = pivotRgb(rgb[1]);
+        double vb = pivotRgb(rgb[2]);
+        // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+        double x = vr * 0.4124564 + vg * 0.3575761 + vb * 0.1804375;
+        double y = vr * 0.2126729 + vg * 0.7151522 + vb * 0.0721750;
+        double z = vr * 0.0193339 + vg * 0.1191920 + vb * 0.9503041;
+        return new double[] { x, y, z };
+    }
+
+    private static double pivotRgb(double n) {
+        return n > 0.04045 ? Math.pow((n + 0.055) / 1.055, 2.4) : n / 12.92;
+    }
+
+    private static double[] xyz2lab(double[] xyz) {
+        double fx = pivotXyz(xyz[0]);
+        double fy = pivotXyz(xyz[1]);
+        double fz = pivotXyz(xyz[2]);
+        double l = 116.0 * fy - 16.0;
+        double a = 500.0 * (fx - fy);
+        double b = 200.0 * (fy - fz);
+        return new double[] { l, a, b };
+    }
+
+    private static final double epsilon = 216.0 / 24389.0;
+    private static final double kappa = 24389.0 / 27.0;
+    private static double pivotXyz(double n) {
+        return n > epsilon ? Math.cbrt(n) : (kappa * n + 16) / 116;
+    }
+
+    private static double sqr(double n) {
+        return n * n;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.Flushable;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Stack;
+
+/**
+ * Curses helper methods.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public final class Curses {
+
+    private static Object[] sv = new Object[26];
+    private static Object[] dv = new Object[26];
+
+    private static final int IFTE_NONE = 0;
+    private static final int IFTE_IF = 1;
+    private static final int IFTE_THEN = 2;
+    private static final int IFTE_ELSE = 3;
+
+    private Curses() {
+    }
+
+    /**
+     * Print the given terminal capabilities
+     *
+     * @param cap the capability to output
+     * @param params optional parameters
+     * @return the result string
+     */
+    public static String tputs(String cap, Object... params) {
+        if (cap != null) {
+            StringWriter sw = new StringWriter();
+            tputs(sw, cap, params);
+            return sw.toString();
+        }
+        return null;
+    }
+
+    /**
+     * Print the given terminal capabilities
+     *
+     * @param out the output stream
+     * @param str the capability to output
+     * @param params optional parameters
+     */
+    public static void tputs(Appendable out, String str, Object... params) {
+        try {
+            doTputs(out, str, params);
+        } catch (Exception e) {
+            throw new IOError(e);
+        }
+    }
+
+    private static void doTputs(Appendable out, String str, Object... params) throws IOException {
+        int index = 0;
+        int length = str.length();
+        int ifte = IFTE_NONE;
+        boolean exec = true;
+        Stack<Object> stack = new Stack<>();
+        while (index < length) {
+            char ch = str.charAt(index++);
+            switch (ch) {
+                case '\\':
+                    ch = str.charAt(index++);
+                    if (ch >= '0' && ch <= '9') {
+                        throw new UnsupportedOperationException(); // todo
+                    } else {
+                        switch (ch) {
+                            case 'e':
+                            case 'E':
+                                if (exec) {
+                                    out.append((char) 27); // escape
+                                }
+                                break;
+                            case 'n':
+                                out.append('\n');
+                                break;
+//                        case 'l':
+//                            rawPrint('\l');
+//                            break;
+                            case 'r':
+                                if (exec) {
+                                    out.append('\r');
+                                }
+                                break;
+                            case 't':
+                                if (exec) {
+                                    out.append('\t');
+                                }
+                                break;
+                            case 'b':
+                                if (exec) {
+                                    out.append('\b');
+                                }
+                                break;
+                            case 'f':
+                                if (exec) {
+                                    out.append('\f');
+                                }
+                                break;
+                            case 's':
+                                if (exec) {
+                                    out.append(' ');
+                                }
+                                break;
+                            case ':':
+                            case '^':
+                            case '\\':
+                                if (exec) {
+                                    out.append(ch);
+                                }
+                                break;
+                            default:
+                                throw new IllegalArgumentException();
+                        }
+                    }
+                    break;
+                case '^':
+                    ch = str.charAt(index++);
+                    if (exec) {
+                        out.append((char)(ch - '@'));
+                    }
+                    break;
+                case '%':
+                    ch = str.charAt(index++);
+                    switch (ch) {
+                        case '%':
+                            if (exec) {
+                                out.append('%');
+                            }
+                            break;
+                        case 'p':
+                            ch = str.charAt(index++);
+                            if (exec) {
+                                stack.push(params[ch - '1']);
+                            }
+                            break;
+                        case 'P':
+                            ch = str.charAt(index++);
+                            if (ch >= 'a' && ch <= 'z') {
+                                if (exec) {
+                                    dv[ch - 'a'] = stack.pop();
+                                }
+                            } else if (ch >= 'A' && ch <= 'Z') {
+                                if (exec) {
+                                    sv[ch - 'A'] = stack.pop();
+                                }
+                            } else {
+                                throw new IllegalArgumentException();
+                            }
+                            break;
+                        case 'g':
+                            ch = str.charAt(index++);
+                            if (ch >= 'a' && ch <= 'z') {
+                                if (exec) {
+                                    stack.push(dv[ch - 'a']);
+                                }
+                            } else if (ch >= 'A' && ch <= 'Z') {
+                                if (exec) {
+                                    stack.push(sv[ch - 'A']);
+                                }
+                            } else {
+                                throw new IllegalArgumentException();
+                            }
+                            break;
+                        case '\'':
+                            ch = str.charAt(index++);
+                            if (exec) {
+                                stack.push((int) ch);
+                            }
+                            ch = str.charAt(index++);
+                            if (ch != '\'') {
+                                throw new IllegalArgumentException();
+                            }
+                            break;
+                        case '{':
+                            int start = index;
+                            while (str.charAt(index++) != '}') ;
+                            if (exec) {
+                                int v = Integer.valueOf(str.substring(start, index - 1));
+                                stack.push(v);
+                            }
+                            break;
+                        case 'l':
+                            if (exec) {
+                                stack.push(stack.pop().toString().length());
+                            }
+                            break;
+                        case '+':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 + v2);
+                            }
+                            break;
+                        case '-':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 - v2);
+                            }
+                            break;
+                        case '*':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 * v2);
+                            }
+                            break;
+                        case '/':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 / v2);
+                            }
+                            break;
+                        case 'm':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 % v2);
+                            }
+                            break;
+                        case '&':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 & v2);
+                            }
+                            break;
+                        case '|':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 | v2);
+                            }
+                            break;
+                        case '^':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 ^ v2);
+                            }
+                            break;
+                        case '=':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 == v2);
+                            }
+                            break;
+                        case '>':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 > v2);
+                            }
+                            break;
+                        case '<':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 < v2);
+                            }
+                            break;
+                        case 'A':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 != 0 && v2 != 0);
+                            }
+                            break;
+                        case '!':
+                            if (exec) {
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 == 0);
+                            }
+                            break;
+                        case '~':
+                            if (exec) {
+                                int v1 = toInteger(stack.pop());
+                                stack.push(~v1);
+                            }
+                            break;
+                        case 'O':
+                            if (exec) {
+                                int v2 = toInteger(stack.pop());
+                                int v1 = toInteger(stack.pop());
+                                stack.push(v1 != 0 || v2 != 0);
+                            }
+                            break;
+                        case '?':
+                            if (ifte != IFTE_NONE) {
+                                throw new IllegalArgumentException();
+                            } else {
+                                ifte = IFTE_IF;
+                            }
+                            break;
+                        case 't':
+                            if (ifte != IFTE_IF && ifte != IFTE_ELSE) {
+                                throw new IllegalArgumentException();
+                            } else {
+                                ifte = IFTE_THEN;
+                            }
+                            exec = toInteger(stack.pop()) != 0;
+                            break;
+                        case 'e':
+                            if (ifte != IFTE_THEN) {
+                                throw new IllegalArgumentException();
+                            } else {
+                                ifte = IFTE_ELSE;
+                            }
+                            exec = !exec;
+                            break;
+                        case ';':
+                            if (ifte == IFTE_NONE || ifte == IFTE_IF) {
+                                throw new IllegalArgumentException();
+                            } else {
+                                ifte = IFTE_NONE;
+                            }
+                            exec = true;
+                            break;
+                        case 'i':
+                            if (params.length >= 1) {
+                                params[0] = toInteger(params[0]) + 1;
+                            }
+                            if (params.length >= 2) {
+                                params[1] = toInteger(params[1]) + 1;
+                            }
+                            break;
+                        case 'd':
+                            out.append(Integer.toString(toInteger(stack.pop())));
+                            break;
+                        default:
+                            throw new UnsupportedOperationException();
+                    }
+                    break;
+                case '$':
+                    if (str.charAt(index) == '<') {
+                        // We don't honour delays, just skip
+                        int nb = 0;
+                        while ((ch = str.charAt(++index)) != '>') {
+                            if (ch >= '0' && ch <= '9') {
+                                nb = nb * 10 + (ch - '0');
+                            } else if (ch == '*') {
+                                // ignore
+                            } else if (ch == '/') {
+                                // ignore
+                            } else {
+                                // illegal, but ...
+                            }
+                        }
+                        index++;
+                        try {
+                            if (out instanceof Flushable) {
+                                ((Flushable) out).flush();
+                            }
+                            Thread.sleep(nb);
+                        } catch (InterruptedException e) {
+                        }
+                    } else {
+                        if (exec) {
+                            out.append(ch);
+                        }
+                    }
+                    break;
+                default:
+                    if (exec) {
+                        out.append(ch);
+                    }
+                    break;
+            }
+        }
+    }
+
+    private static int toInteger(Object pop) {
+        if (pop instanceof Number) {
+            return ((Number) pop).intValue();
+        } else if (pop instanceof Boolean) {
+            return (Boolean) pop ? 1 : 0;
+        } else {
+            return Integer.valueOf(pop.toString());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Class containing the diff method.
+ * This diff is ANSI aware and will correctly handle text attributes
+ * so that any text in a Diff object is a valid ansi string.
+ */
+public class DiffHelper {
+
+    /**
+     * The data structure representing a diff is a Linked list of Diff objects:
+     * {Diff(Operation.DELETE, "Hello"), Diff(Operation.INSERT, "Goodbye"),
+     *  Diff(Operation.EQUAL, " world.")}
+     * which means: delete "Hello", add "Goodbye" and keep " world."
+     */
+    public enum Operation {
+        DELETE, INSERT, EQUAL
+    }
+
+    /**
+     * Class representing one diff operation.
+     */
+    public static class Diff {
+        /**
+         * One of: INSERT, DELETE or EQUAL.
+         */
+        public final Operation operation;
+        /**
+         * The text associated with this diff operation.
+         */
+        public final AttributedString text;
+
+        /**
+         * Constructor.  Initializes the diff with the provided values.
+         * @param operation One of INSERT, DELETE or EQUAL.
+         * @param text The text being applied.
+         */
+        public Diff(Operation operation, AttributedString text) {
+            // Construct a diff with the specified operation and text.
+            this.operation = operation;
+            this.text = text;
+        }
+
+        /**
+         * Display a human-readable version of this Diff.
+         * @return text version.
+         */
+        public String toString() {
+            return "Diff(" + this.operation + ",\"" + this.text + "\")";
+        }
+    }
+
+    /**
+     * Compute a list of difference between two lines.
+     * The result will contain at most 4 Diff objects, as the method
+     * aims to return the common prefix, inserted text, deleted text and
+     * common suffix.
+     * The computation is done on characters and their attributes expressed
+     * as ansi sequences.
+     *
+     * @param text1 the old line
+     * @param text2 the new line
+     * @return a list of Diff
+     */
+    public static List<Diff> diff(AttributedString text1, AttributedString text2) {
+        int l1 = text1.length();
+        int l2 = text2.length();
+        int n = Math.min(l1, l2);
+        int commonStart = 0;
+        // Given a run of contiguous "hidden" characters (which are
+        // sequences of uninterrupted escape sequences) we always want to
+        // print either the entire run or none of it - never a part of it.
+        int startHiddenRange = -1;
+        while (commonStart < n
+                && text1.charAt(commonStart) == text2.charAt(commonStart)
+                && text1.styleAt(commonStart).equals(text2.styleAt(commonStart))) {
+            if (text1.isHidden(commonStart)) {
+                if (startHiddenRange < 0)
+                    startHiddenRange = commonStart;
+            } else
+                startHiddenRange = -1;
+            commonStart++;
+        }
+        if (startHiddenRange >= 0
+            && ((l1 > commonStart && text1.isHidden(commonStart))
+                || (l2 > commonStart && text2.isHidden(commonStart))))
+            commonStart = startHiddenRange;
+
+        startHiddenRange = -1;
+        int commonEnd = 0;
+        while (commonEnd < n - commonStart
+                && text1.charAt(l1 - commonEnd - 1) == text2.charAt(l2 - commonEnd - 1)
+                && text1.styleAt(l1 - commonEnd - 1).equals(text2.styleAt(l2 - commonEnd - 1))) {
+            if (text1.isHidden(l1 - commonEnd - 1)) {
+                if (startHiddenRange < 0)
+                    startHiddenRange = commonEnd;
+            } else
+                startHiddenRange = -1;
+            commonEnd++;
+        }
+        if (startHiddenRange >= 0)
+            commonEnd = startHiddenRange;
+        LinkedList<Diff> diffs = new LinkedList<>();
+        if (commonStart > 0) {
+            diffs.add(new Diff(DiffHelper.Operation.EQUAL,
+                    text1.subSequence(0, commonStart)));
+        }
+        if (l2 > commonStart + commonEnd) {
+            diffs.add(new Diff(DiffHelper.Operation.INSERT,
+                    text2.subSequence(commonStart, l2 - commonEnd)));
+        }
+        if (l1 > commonStart + commonEnd) {
+            diffs.add(new Diff(DiffHelper.Operation.DELETE,
+                    text1.subSequence(commonStart, l1 - commonEnd)));
+        }
+        if (commonEnd > 0) {
+            diffs.add(new Diff(DiffHelper.Operation.EQUAL,
+                    text1.subSequence(l1 - commonEnd, l1)));
+        }
+        return diffs;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+
+/**
+ * Handle display and visual cursor.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class Display {
+
+    /**OpenJDK:
+     * When true, when the cursor is moved to column 0, carriage_return capability is not used,
+     * but rather the cursor is moved left the appropriate number of positions.
+     * This is useful when there's something already printed on the first line (which is not
+     * specified as a prompt), for example when the user is providing an input.
+     */
+    public static boolean DISABLE_CR = false;
+
+    protected final Terminal terminal;
+    protected final boolean fullScreen;
+    protected List<AttributedString> oldLines = Collections.emptyList();
+    protected int cursorPos;
+    private int columns;
+    private int columns1; // columns+1
+    protected int rows;
+    protected boolean reset;
+    protected boolean delayLineWrap;
+
+    protected final Map<Capability, Integer> cost = new HashMap<>();
+    protected final boolean canScroll;
+    protected final boolean wrapAtEol;
+    protected final boolean delayedWrapAtEol;
+    protected final boolean cursorDownIsNewLine;
+
+    public Display(Terminal terminal, boolean fullscreen) {
+        this.terminal = terminal;
+        this.fullScreen = fullscreen;
+
+        this.canScroll = can(Capability.insert_line, Capability.parm_insert_line)
+                            && can(Capability.delete_line, Capability.parm_delete_line);
+        this.wrapAtEol = terminal.getBooleanCapability(Capability.auto_right_margin);
+        this.delayedWrapAtEol = this.wrapAtEol
+            && terminal.getBooleanCapability(Capability.eat_newline_glitch);
+        this.cursorDownIsNewLine = "\n".equals(Curses.tputs(terminal.getStringCapability(Capability.cursor_down)));
+    }
+
+    /**
+     * If cursor is at right margin, don't wrap immediately.
+     * See <code>org.jline.reader.LineReader.Option#DELAY_LINE_WRAP</code>.
+     * @return <code>true</code> if line wrap is delayed, <code>false</code> otherwise
+     */
+    public boolean delayLineWrap() {
+        return delayLineWrap;
+    }
+    public void setDelayLineWrap(boolean v) { delayLineWrap = v; }
+
+    public void resize(int rows, int columns) {
+        if (this.rows != rows || this.columns != columns) {
+            this.rows = rows;
+            this.columns = columns;
+            this.columns1 = columns + 1;
+            oldLines = AttributedString.join(AttributedString.EMPTY, oldLines).columnSplitLength(columns, true, delayLineWrap());
+        }
+    }
+
+    public void reset() {
+        oldLines = Collections.emptyList();
+    }
+
+    /**
+     * Clears the whole screen.
+     * Use this method only when using full-screen / application mode.
+     */
+    public void clear() {
+        if (fullScreen) {
+            reset = true;
+        }
+    }
+
+    public void updateAnsi(List<String> newLines, int targetCursorPos) {
+        update(newLines.stream().map(AttributedString::fromAnsi).collect(Collectors.toList()), targetCursorPos);
+    }
+
+    /**
+     * Update the display according to the new lines and flushes the output.
+     * @param newLines the lines to display
+     * @param targetCursorPos desired cursor position - see Size.cursorPos.
+     */
+    public void update(List<AttributedString> newLines, int targetCursorPos) {
+        update(newLines, targetCursorPos, true);
+    }
+
+    /**
+     * Update the display according to the new lines.
+     * @param newLines the lines to display
+     * @param targetCursorPos desired cursor position - see Size.cursorPos.
+     * @param flush whether the output should be flushed or not
+     */
+    public void update(List<AttributedString> newLines, int targetCursorPos, boolean flush) {
+        if (reset) {
+            terminal.puts(Capability.clear_screen);
+            oldLines.clear();
+            cursorPos = 0;
+            reset = false;
+        }
+
+        // If dumb display, get rid of ansi sequences now
+        Integer cols = terminal.getNumericCapability(Capability.max_colors);
+        if (cols == null || cols < 8) {
+            newLines = newLines.stream().map(s -> new AttributedString(s.toString()))
+                    .collect(Collectors.toList());
+        }
+
+        // Detect scrolling
+        if ((fullScreen || newLines.size() >= rows) && newLines.size() == oldLines.size() && canScroll) {
+            int nbHeaders = 0;
+            int nbFooters = 0;
+            // Find common headers and footers
+            int l = newLines.size();
+            while (nbHeaders < l
+                   && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) {
+                nbHeaders++;
+            }
+            while (nbFooters < l - nbHeaders - 1
+                    && Objects.equals(newLines.get(newLines.size() - nbFooters - 1), oldLines.get(oldLines.size() - nbFooters - 1))) {
+                nbFooters++;
+            }
+            List<AttributedString> o1 = newLines.subList(nbHeaders, newLines.size() - nbFooters);
+            List<AttributedString> o2 = oldLines.subList(nbHeaders, oldLines.size() - nbFooters);
+            int[] common = longestCommon(o1, o2);
+            if (common != null) {
+                int s1 = common[0];
+                int s2 = common[1];
+                int sl = common[2];
+                if (sl > 1 && s1 < s2) {
+                    moveVisualCursorTo((nbHeaders + s1) * columns1);
+                    int nb = s2 - s1;
+                    deleteLines(nb);
+                    for (int i = 0; i < nb; i++) {
+                        oldLines.remove(nbHeaders + s1);
+                    }
+                    if (nbFooters > 0) {
+                        moveVisualCursorTo((nbHeaders + s1 + sl) * columns1);
+                        insertLines(nb);
+                        for (int i = 0; i < nb; i++) {
+                            oldLines.add(nbHeaders + s1 + sl, new AttributedString(""));
+                        }
+                    }
+                } else if (sl > 1 && s1 > s2) {
+                    int nb = s1 - s2;
+                    if (nbFooters > 0) {
+                        moveVisualCursorTo((nbHeaders + s2 + sl) * columns1);
+                        deleteLines(nb);
+                        for (int i = 0; i < nb; i++) {
+                            oldLines.remove(nbHeaders + s2 + sl);
+                        }
+                    }
+                    moveVisualCursorTo((nbHeaders + s2) * columns1);
+                    insertLines(nb);
+                    for (int i = 0; i < nb; i++) {
+                        oldLines.add(nbHeaders + s2, new AttributedString(""));
+                    }
+                }
+            }
+        }
+
+        int lineIndex = 0;
+        int currentPos = 0;
+        int numLines = Math.max(oldLines.size(), newLines.size());
+        boolean wrapNeeded = false;
+        while (lineIndex < numLines) {
+            AttributedString oldLine =
+                lineIndex < oldLines.size() ? oldLines.get(lineIndex)
+                : AttributedString.NEWLINE;
+            AttributedString newLine =
+                 lineIndex < newLines.size() ? newLines.get(lineIndex)
+                : AttributedString.NEWLINE;
+            currentPos = lineIndex * columns1;
+            int curCol = currentPos;
+            int oldLength = oldLine.length();
+            int newLength = newLine.length();
+            boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength-1)=='\n';
+            boolean newNL = newLength > 0 && newLine.charAt(newLength-1)=='\n';
+            if (oldNL) {
+                oldLength--;
+                oldLine = oldLine.substring(0, oldLength);
+            }
+            if (newNL) {
+                newLength--;
+                newLine = newLine.substring(0, newLength);
+            }
+            if (wrapNeeded
+                && lineIndex == (cursorPos + 1) / columns1
+                && lineIndex < newLines.size()) {
+                // move from right margin to next line's left margin
+                cursorPos++;
+                if (newLength == 0 || newLine.isHidden(0)) {
+                    // go to next line column zero
+                    rawPrint(new AttributedString(" \b"));
+                } else {
+                    AttributedString firstChar =
+                        newLine.columnSubSequence(0, 1);
+                    // go to next line column one
+                    rawPrint(firstChar);
+                    cursorPos++;
+                    int firstLength = firstChar.length(); // normally 1
+                    newLine = newLine.substring(firstLength, newLength);
+                    newLength -= firstLength;
+                    if (oldLength >= firstLength) {
+                        oldLine = oldLine.substring(firstLength, oldLength);
+                        oldLength -= firstLength;
+                    }
+                    currentPos = cursorPos;
+                }
+            }
+            List<DiffHelper.Diff> diffs = DiffHelper.diff(oldLine, newLine);
+            boolean ident = true;
+            boolean cleared = false;
+            for (int i = 0; i < diffs.size(); i++) {
+                DiffHelper.Diff diff = diffs.get(i);
+                int width = diff.text.columnLength();
+                switch (diff.operation) {
+                    case EQUAL:
+                        if (!ident) {
+                            cursorPos = moveVisualCursorTo(currentPos);
+                            rawPrint(diff.text);
+                            cursorPos += width;
+                            currentPos = cursorPos;
+                        } else {
+                            currentPos += width;
+                        }
+                        break;
+                    case INSERT:
+                        if (i <= diffs.size() - 2
+                                && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) {
+                            cursorPos = moveVisualCursorTo(currentPos);
+                            if (insertChars(width)) {
+                                rawPrint(diff.text);
+                                cursorPos += width;
+                                currentPos = cursorPos;
+                                break;
+                            }
+                        } else if (i <= diffs.size() - 2
+                                && diffs.get(i + 1).operation == DiffHelper.Operation.DELETE
+                                && width == diffs.get(i + 1).text.columnLength()) {
+                            moveVisualCursorTo(currentPos);
+                            rawPrint(diff.text);
+                            cursorPos += width;
+                            currentPos = cursorPos;
+                            i++; // skip delete
+                            break;
+                        }
+                        moveVisualCursorTo(currentPos);
+                        rawPrint(diff.text);
+                        cursorPos += width;
+                        currentPos = cursorPos;
+                        ident = false;
+                        break;
+                    case DELETE:
+                        if (cleared) {
+                            continue;
+                        }
+                        if (currentPos - curCol >= columns) {
+                            continue;
+                        }
+                        if (i <= diffs.size() - 2
+                                && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) {
+                            if (currentPos + diffs.get(i + 1).text.columnLength() < columns) {
+                                moveVisualCursorTo(currentPos);
+                                if (deleteChars(width)) {
+                                    break;
+                                }
+                            }
+                        }
+                        int oldLen = oldLine.columnLength();
+                        int newLen = newLine.columnLength();
+                        int nb = Math.max(oldLen, newLen) - (currentPos - curCol);
+                        moveVisualCursorTo(currentPos);
+                        if (!terminal.puts(Capability.clr_eol)) {
+                            rawPrint(' ', nb);
+                            cursorPos += nb;
+                        }
+                        cleared = true;
+                        ident = false;
+                        break;
+                }
+            }
+            lineIndex++;
+            boolean newWrap = ! newNL && lineIndex < newLines.size();
+            if (targetCursorPos + 1 == lineIndex * columns1
+                && (newWrap || ! delayLineWrap))
+                targetCursorPos++;
+            boolean atRight = (cursorPos - curCol) % columns1 == columns;
+            wrapNeeded = false;
+            if (this.delayedWrapAtEol) {
+                boolean oldWrap = ! oldNL && lineIndex < oldLines.size();
+                if (newWrap != oldWrap && ! (oldWrap && cleared)) {
+                    moveVisualCursorTo(lineIndex*columns1-1, newLines);
+                    if (newWrap)
+                        wrapNeeded = true;
+                    else
+                        terminal.puts(Capability.clr_eol);
+                }
+            } else if (atRight) {
+                if (this.wrapAtEol) {
+                    terminal.writer().write(" \b");
+                    cursorPos++;
+                } else {
+                    terminal.puts(Capability.carriage_return); // CR / not newline.
+                    cursorPos = curCol;
+                }
+                currentPos = cursorPos;
+            }
+        }
+        int was = cursorPos;
+        if (cursorPos != targetCursorPos) {
+            moveVisualCursorTo(targetCursorPos < 0 ? currentPos : targetCursorPos, newLines);
+        }
+        oldLines = newLines;
+
+        if (flush) {
+            terminal.flush();
+        }
+    }
+
+    protected boolean deleteLines(int nb) {
+        return perform(Capability.delete_line, Capability.parm_delete_line, nb);
+    }
+
+    protected boolean insertLines(int nb) {
+        return perform(Capability.insert_line, Capability.parm_insert_line, nb);
+    }
+
+    protected boolean insertChars(int nb) {
+        return perform(Capability.insert_character, Capability.parm_ich, nb);
+    }
+
+    protected boolean deleteChars(int nb) {
+        return perform(Capability.delete_character, Capability.parm_dch, nb);
+    }
+
+    protected boolean can(Capability single, Capability multi) {
+        return terminal.getStringCapability(single) != null
+                || terminal.getStringCapability(multi) != null;
+    }
+
+    protected boolean perform(Capability single, Capability multi, int nb) {
+        boolean hasMulti = terminal.getStringCapability(multi) != null;
+        boolean hasSingle = terminal.getStringCapability(single) != null;
+        if (hasMulti && (!hasSingle || cost(single) * nb > cost(multi))) {
+            terminal.puts(multi, nb);
+            return true;
+        } else if (hasSingle) {
+            for (int i = 0; i < nb; i++) {
+                terminal.puts(single);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private int cost(Capability cap) {
+        return cost.computeIfAbsent(cap, this::computeCost);
+    }
+
+    private int computeCost(Capability cap) {
+        String s = Curses.tputs(terminal.getStringCapability(cap), 0);
+        return s != null ? s.length() : Integer.MAX_VALUE;
+    }
+
+    private static int[] longestCommon(List<AttributedString> l1, List<AttributedString> l2) {
+        int start1 = 0;
+        int start2 = 0;
+        int max = 0;
+        for (int i = 0; i < l1.size(); i++) {
+            for (int j = 0; j < l2.size(); j++) {
+                int x = 0;
+                while (Objects.equals(l1.get(i + x), l2.get(j + x))) {
+                    x++;
+                    if (((i + x) >= l1.size()) || ((j + x) >= l2.size())) break;
+                }
+                if (x > max) {
+                    max = x;
+                    start1 = i;
+                    start2 = j;
+                }
+            }
+        }
+        return max != 0 ? new int[] { start1, start2, max } : null;
+    }
+
+    /*
+     * Move cursor from cursorPos to argument, updating cursorPos
+     * We're at the right margin if {@code (cursorPos % columns1) == columns}.
+     * This method knows how to move both *from* and *to* the right margin.
+     */
+    protected void moveVisualCursorTo(int targetPos,
+                                      List<AttributedString> newLines) {
+        if (cursorPos != targetPos) {
+            boolean atRight = (targetPos % columns1) == columns;
+            moveVisualCursorTo(targetPos - (atRight ? 1 : 0));
+            if (atRight) {
+                // There is no portable way to move to the right margin
+                // except by writing a character in the right-most column.
+                int row = targetPos / columns1;
+                AttributedString lastChar = row >= newLines.size() ? AttributedString.EMPTY
+                    : newLines.get(row).columnSubSequence(columns-1, columns);
+                if (lastChar.length() == 0)
+                    rawPrint((int) ' ');
+                else
+                    rawPrint(lastChar);
+                cursorPos++;
+            }
+        }
+    }
+
+    /*
+     * Move cursor from cursorPos to argument, updating cursorPos
+     * We're at the right margin if {@code (cursorPos % columns1) == columns}.
+     * This method knows how to move *from* the right margin,
+     * but does not know how to move *to* the right margin.
+     * I.e. {@code (i1 % columns1) == column} is not allowed.
+     */
+    protected int moveVisualCursorTo(int i1) {
+        int i0 = cursorPos;
+        if (i0 == i1) return i1;
+        int width = columns1;
+        int l0 = i0 / width;
+        int c0 = i0 % width;
+        int l1 = i1 / width;
+        int c1 = i1 % width;
+        if (c0 == columns) { // at right margin
+            terminal.puts(Capability.carriage_return);
+            c0 = 0;
+        }
+        if (l0 > l1) {
+            perform(Capability.cursor_up, Capability.parm_up_cursor, l0 - l1);
+        } else if (l0 < l1) {
+            // TODO: clean the following
+            if (fullScreen) {
+                if (!terminal.puts(Capability.parm_down_cursor, l1 - l0)) {
+                    for (int i = l0; i < l1; i++) {
+                        terminal.puts(Capability.cursor_down);
+                    }
+                    if (cursorDownIsNewLine) {
+                        c0 = 0;
+                    }
+                }
+            } else {
+                terminal.puts(Capability.carriage_return);
+                rawPrint('\n', l1 - l0);
+                c0 = 0;
+            }
+        }
+        if (c0 != 0 && c1 == 0 && !DISABLE_CR) {
+            terminal.puts(Capability.carriage_return);
+        } else if (c0 < c1) {
+            perform(Capability.cursor_right, Capability.parm_right_cursor, c1 - c0);
+        } else if (c0 > c1) {
+            perform(Capability.cursor_left, Capability.parm_left_cursor, c0 - c1);
+        }
+        cursorPos = i1;
+        return i1;
+    }
+
+    void rawPrint(char c, int num) {
+        for (int i = 0; i < num; i++) {
+            rawPrint(c);
+        }
+    }
+
+    void rawPrint(int c) {
+        terminal.writer().write(c);
+    }
+
+    void rawPrint(AttributedString str) {
+        terminal.writer().write(str.toAnsi(terminal));
+    }
+
+    public int wcwidth(String str) {
+        return AttributedString.fromAnsi(str).columnLength();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.util.Objects;
+
+/**
+ * Helper methods for running unix commands.
+ */
+public final class ExecHelper {
+
+    private ExecHelper() {
+    }
+
+    public static String exec(boolean redirectInput, final String... cmd) throws IOException {
+        Objects.requireNonNull(cmd);
+        try {
+            Log.trace("Running: ", cmd);
+            ProcessBuilder pb = new ProcessBuilder(cmd);
+            if (redirectInput) {
+                pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
+            }
+            Process p = pb.start();
+            String result = waitAndCapture(p);
+            Log.trace("Result: ", result);
+            if (p.exitValue() != 0) {
+                if (result.endsWith("\n")) {
+                    result = result.substring(0, result.length() - 1);
+                }
+                throw new IOException("Error executing '" + String.join(" ", (CharSequence[]) cmd) + "': " + result);
+            }
+            return result;
+        } catch (InterruptedException e) {
+            throw (IOException) new InterruptedIOException("Command interrupted").initCause(e);
+        }
+    }
+
+    public static String waitAndCapture(Process p) throws IOException, InterruptedException {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        InputStream in = null;
+        InputStream err = null;
+        OutputStream out = null;
+        try {
+            int c;
+            in = p.getInputStream();
+            while ((c = in.read()) != -1) {
+                bout.write(c);
+            }
+            err = p.getErrorStream();
+            while ((c = err.read()) != -1) {
+                bout.write(c);
+            }
+            out = p.getOutputStream();
+            p.waitFor();
+        } finally {
+            close(in, out, err);
+        }
+
+        return bout.toString();
+    }
+
+    private static void close(final Closeable... closeables) {
+        for (Closeable c : closeables) {
+            if (c != null) {
+                try {
+                    c.close();
+                } catch (Exception e) {
+                    // Ignore
+                }
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.BufferedReader;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Infocmp helper methods.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public final class InfoCmp {
+
+    private static final Map<String, Object> CAPS = new HashMap<>();
+
+    private InfoCmp() {
+    }
+
+    @SuppressWarnings("unused")
+    public enum Capability {
+
+        auto_left_margin,           // auto_left_margin, bw, bw
+        auto_right_margin,          // auto_right_margin, am, am
+        back_color_erase,           // back_color_erase, bce, ut
+        can_change,                 // can_change, ccc, cc
+        ceol_standout_glitch,       // ceol_standout_glitch, xhp, xs
+        col_addr_glitch,            // col_addr_glitch, xhpa, YA
+        cpi_changes_res,            // cpi_changes_res, cpix, YF
+        cr_cancels_micro_mode,      // cr_cancels_micro_mode, crxm, YB
+        dest_tabs_magic_smso,       // dest_tabs_magic_smso, xt, xt
+        eat_newline_glitch,         // eat_newline_glitch, xenl, xn
+        erase_overstrike,           // erase_overstrike, eo, eo
+        generic_type,               // generic_type, gn, gn
+        hard_copy,                  // hard_copy, hc, hc
+        hard_cursor,                // hard_cursor, chts, HC
+        has_meta_key,               // has_meta_key, km, km
+        has_print_wheel,            // has_print_wheel, daisy, YC
+        has_status_line,            // has_status_line, hs, hs
+        hue_lightness_saturation,   // hue_lightness_saturation, hls, hl
+        insert_null_glitch,         // insert_null_glitch, in, in
+        lpi_changes_res,            // lpi_changes_res, lpix, YG
+        memory_above,               // memory_above, da, da
+        memory_below,               // memory_below, db, db
+        move_insert_mode,           // move_insert_mode, mir, mi
+        move_standout_mode,         // move_standout_mode, msgr, ms
+        needs_xon_xoff,             // needs_xon_xoff, nxon, nx
+        no_esc_ctlc,                // no_esc_ctlc, xsb, xb
+        no_pad_char,                // no_pad_char, npc, NP
+        non_dest_scroll_region,     // non_dest_scroll_region, ndscr, ND
+        non_rev_rmcup,              // non_rev_rmcup, nrrmc, NR
+        over_strike,                // over_strike, os, os
+        prtr_silent,                // prtr_silent, mc5i, 5i
+        row_addr_glitch,            // row_addr_glitch, xvpa, YD
+        semi_auto_right_margin,     // semi_auto_right_margin, sam, YE
+        status_line_esc_ok,         // status_line_esc_ok, eslok, es
+        tilde_glitch,               // tilde_glitch, hz, hz
+        transparent_underline,      // transparent_underline, ul, ul
+        xon_xoff,                   // xon_xoff, xon, xo
+        columns,                    // columns, cols, co
+        init_tabs,                  // init_tabs, it, it
+        label_height,               // label_height, lh, lh
+        label_width,                // label_width, lw, lw
+        lines,                      // lines, lines, li
+        lines_of_memory,            // lines_of_memory, lm, lm
+        magic_cookie_glitch,        // magic_cookie_glitch, xmc, sg
+        max_attributes,             // max_attributes, ma, ma
+        max_colors,                 // max_colors, colors, Co
+        max_pairs,                  // max_pairs, pairs, pa
+        maximum_windows,            // maximum_windows, wnum, MW
+        no_color_video,             // no_color_video, ncv, NC
+        num_labels,                 // num_labels, nlab, Nl
+        padding_baud_rate,          // padding_baud_rate, pb, pb
+        virtual_terminal,           // virtual_terminal, vt, vt
+        width_status_line,          // width_status_line, wsl, ws
+        bit_image_entwining,        // bit_image_entwining, bitwin, Yo
+        bit_image_type,             // bit_image_type, bitype, Yp
+        buffer_capacity,            // buffer_capacity, bufsz, Ya
+        buttons,                    // buttons, btns, BT
+        dot_horz_spacing,           // dot_horz_spacing, spinh, Yc
+        dot_vert_spacing,           // dot_vert_spacing, spinv, Yb
+        max_micro_address,          // max_micro_address, maddr, Yd
+        max_micro_jump,             // max_micro_jump, mjump, Ye
+        micro_col_size,             // micro_col_size, mcs, Yf
+        micro_line_size,            // micro_line_size, mls, Yg
+        number_of_pins,             // number_of_pins, npins, Yh
+        output_res_char,            // output_res_char, orc, Yi
+        output_res_horz_inch,       // output_res_horz_inch, orhi, Yk
+        output_res_line,            // output_res_line, orl, Yj
+        output_res_vert_inch,       // output_res_vert_inch, orvi, Yl
+        print_rate,                 // print_rate, cps, Ym
+        wide_char_size,             // wide_char_size, widcs, Yn
+        acs_chars,                  // acs_chars, acsc, ac
+        back_tab,                   // back_tab, cbt, bt
+        bell,                       // bell, bel, bl
+        carriage_return,            // carriage_return, cr, cr
+        change_char_pitch,          // change_char_pitch, cpi, ZA
+        change_line_pitch,          // change_line_pitch, lpi, ZB
+        change_res_horz,            // change_res_horz, chr, ZC
+        change_res_vert,            // change_res_vert, cvr, ZD
+        change_scroll_region,       // change_scroll_region, csr, cs
+        char_padding,               // char_padding, rmp, rP
+        clear_all_tabs,             // clear_all_tabs, tbc, ct
+        clear_margins,              // clear_margins, mgc, MC
+        clear_screen,               // clear_screen, clear, cl
+        clr_bol,                    // clr_bol, el1, cb
+        clr_eol,                    // clr_eol, el, ce
+        clr_eos,                    // clr_eos, ed, cd
+        column_address,             // column_address, hpa, ch
+        command_character,          // command_character, cmdch, CC
+        create_window,              // create_window, cwin, CW
+        cursor_address,             // cursor_address, cup, cm
+        cursor_down,                // cursor_down, cud1, do
+        cursor_home,                // cursor_home, home, ho
+        cursor_invisible,           // cursor_invisible, civis, vi
+        cursor_left,                // cursor_left, cub1, le
+        cursor_mem_address,         // cursor_mem_address, mrcup, CM
+        cursor_normal,              // cursor_normal, cnorm, ve
+        cursor_right,               // cursor_right, cuf1, nd
+        cursor_to_ll,               // cursor_to_ll, ll, ll
+        cursor_up,                  // cursor_up, cuu1, up
+        cursor_visible,             // cursor_visible, cvvis, vs
+        define_char,                // define_char, defc, ZE
+        delete_character,           // delete_character, dch1, dc
+        delete_line,                // delete_line, dl1, dl
+        dial_phone,                 // dial_phone, dial, DI
+        dis_status_line,            // dis_status_line, dsl, ds
+        display_clock,              // display_clock, dclk, DK
+        down_half_line,             // down_half_line, hd, hd
+        ena_acs,                    // ena_acs, enacs, eA
+        enter_alt_charset_mode,     // enter_alt_charset_mode, smacs, as
+        enter_am_mode,              // enter_am_mode, smam, SA
+        enter_blink_mode,           // enter_blink_mode, blink, mb
+        enter_bold_mode,            // enter_bold_mode, bold, md
+        enter_ca_mode,              // enter_ca_mode, smcup, ti
+        enter_delete_mode,          // enter_delete_mode, smdc, dm
+        enter_dim_mode,             // enter_dim_mode, dim, mh
+        enter_doublewide_mode,      // enter_doublewide_mode, swidm, ZF
+        enter_draft_quality,        // enter_draft_quality, sdrfq, ZG
+        enter_insert_mode,          // enter_insert_mode, smir, im
+        enter_italics_mode,         // enter_italics_mode, sitm, ZH
+        enter_leftward_mode,        // enter_leftward_mode, slm, ZI
+        enter_micro_mode,           // enter_micro_mode, smicm, ZJ
+        enter_near_letter_quality,  // enter_near_letter_quality, snlq, ZK
+        enter_normal_quality,       // enter_normal_quality, snrmq, ZL
+        enter_protected_mode,       // enter_protected_mode, prot, mp
+        enter_reverse_mode,         // enter_reverse_mode, rev, mr
+        enter_secure_mode,          // enter_secure_mode, invis, mk
+        enter_shadow_mode,          // enter_shadow_mode, sshm, ZM
+        enter_standout_mode,        // enter_standout_mode, smso, so
+        enter_subscript_mode,       // enter_subscript_mode, ssubm, ZN
+        enter_superscript_mode,     // enter_superscript_mode, ssupm, ZO
+        enter_underline_mode,       // enter_underline_mode, smul, us
+        enter_upward_mode,          // enter_upward_mode, sum, ZP
+        enter_xon_mode,             // enter_xon_mode, smxon, SX
+        erase_chars,                // erase_chars, ech, ec
+        exit_alt_charset_mode,      // exit_alt_charset_mode, rmacs, ae
+        exit_am_mode,               // exit_am_mode, rmam, RA
+        exit_attribute_mode,        // exit_attribute_mode, sgr0, me
+        exit_ca_mode,               // exit_ca_mode, rmcup, te
+        exit_delete_mode,           // exit_delete_mode, rmdc, ed
+        exit_doublewide_mode,       // exit_doublewide_mode, rwidm, ZQ
+        exit_insert_mode,           // exit_insert_mode, rmir, ei
+        exit_italics_mode,          // exit_italics_mode, ritm, ZR
+        exit_leftward_mode,         // exit_leftward_mode, rlm, ZS
+        exit_micro_mode,            // exit_micro_mode, rmicm, ZT
+        exit_shadow_mode,           // exit_shadow_mode, rshm, ZU
+        exit_standout_mode,         // exit_standout_mode, rmso, se
+        exit_subscript_mode,        // exit_subscript_mode, rsubm, ZV
+        exit_superscript_mode,      // exit_superscript_mode, rsupm, ZW
+        exit_underline_mode,        // exit_underline_mode, rmul, ue
+        exit_upward_mode,           // exit_upward_mode, rum, ZX
+        exit_xon_mode,              // exit_xon_mode, rmxon, RX
+        fixed_pause,                // fixed_pause, pause, PA
+        flash_hook,                 // flash_hook, hook, fh
+        flash_screen,               // flash_screen, flash, vb
+        form_feed,                  // form_feed, ff, ff
+        from_status_line,           // from_status_line, fsl, fs
+        goto_window,                // goto_window, wingo, WG
+        hangup,                     // hangup, hup, HU
+        init_1string,               // init_1string, is1, i1
+        init_2string,               // init_2string, is2, is
+        init_3string,               // init_3string, is3, i3
+        init_file,                  // init_file, if, if
+        init_prog,                  // init_prog, iprog, iP
+        initialize_color,           // initialize_color, initc, Ic
+        initialize_pair,            // initialize_pair, initp, Ip
+        insert_character,           // insert_character, ich1, ic
+        insert_line,                // insert_line, il1, al
+        insert_padding,             // insert_padding, ip, ip
+        key_a1,                     // key_a1, ka1, K1
+        key_a3,                     // key_a3, ka3, K3
+        key_b2,                     // key_b2, kb2, K2
+        key_backspace,              // key_backspace, kbs, kb
+        key_beg,                    // key_beg, kbeg, @1
+        key_btab,                   // key_btab, kcbt, kB
+        key_c1,                     // key_c1, kc1, K4
+        key_c3,                     // key_c3, kc3, K5
+        key_cancel,                 // key_cancel, kcan, @2
+        key_catab,                  // key_catab, ktbc, ka
+        key_clear,                  // key_clear, kclr, kC
+        key_close,                  // key_close, kclo, @3
+        key_command,                // key_command, kcmd, @4
+        key_copy,                   // key_copy, kcpy, @5
+        key_create,                 // key_create, kcrt, @6
+        key_ctab,                   // key_ctab, kctab, kt
+        key_dc,                     // key_dc, kdch1, kD
+        key_dl,                     // key_dl, kdl1, kL
+        key_down,                   // key_down, kcud1, kd
+        key_eic,                    // key_eic, krmir, kM
+        key_end,                    // key_end, kend, @7
+        key_enter,                  // key_enter, kent, @8
+        key_eol,                    // key_eol, kel, kE
+        key_eos,                    // key_eos, ked, kS
+        key_exit,                   // key_exit, kext, @9
+        key_f0,                     // key_f0, kf0, k0
+        key_f1,                     // key_f1, kf1, k1
+        key_f10,                    // key_f10, kf10, k;
+        key_f11,                    // key_f11, kf11, F1
+        key_f12,                    // key_f12, kf12, F2
+        key_f13,                    // key_f13, kf13, F3
+        key_f14,                    // key_f14, kf14, F4
+        key_f15,                    // key_f15, kf15, F5
+        key_f16,                    // key_f16, kf16, F6
+        key_f17,                    // key_f17, kf17, F7
+        key_f18,                    // key_f18, kf18, F8
+        key_f19,                    // key_f19, kf19, F9
+        key_f2,                     // key_f2, kf2, k2
+        key_f20,                    // key_f20, kf20, FA
+        key_f21,                    // key_f21, kf21, FB
+        key_f22,                    // key_f22, kf22, FC
+        key_f23,                    // key_f23, kf23, FD
+        key_f24,                    // key_f24, kf24, FE
+        key_f25,                    // key_f25, kf25, FF
+        key_f26,                    // key_f26, kf26, FG
+        key_f27,                    // key_f27, kf27, FH
+        key_f28,                    // key_f28, kf28, FI
+        key_f29,                    // key_f29, kf29, FJ
+        key_f3,                     // key_f3, kf3, k3
+        key_f30,                    // key_f30, kf30, FK
+        key_f31,                    // key_f31, kf31, FL
+        key_f32,                    // key_f32, kf32, FM
+        key_f33,                    // key_f33, kf33, FN
+        key_f34,                    // key_f34, kf34, FO
+        key_f35,                    // key_f35, kf35, FP
+        key_f36,                    // key_f36, kf36, FQ
+        key_f37,                    // key_f37, kf37, FR
+        key_f38,                    // key_f38, kf38, FS
+        key_f39,                    // key_f39, kf39, FT
+        key_f4,                     // key_f4, kf4, k4
+        key_f40,                    // key_f40, kf40, FU
+        key_f41,                    // key_f41, kf41, FV
+        key_f42,                    // key_f42, kf42, FW
+        key_f43,                    // key_f43, kf43, FX
+        key_f44,                    // key_f44, kf44, FY
+        key_f45,                    // key_f45, kf45, FZ
+        key_f46,                    // key_f46, kf46, Fa
+        key_f47,                    // key_f47, kf47, Fb
+        key_f48,                    // key_f48, kf48, Fc
+        key_f49,                    // key_f49, kf49, Fd
+        key_f5,                     // key_f5, kf5, k5
+        key_f50,                    // key_f50, kf50, Fe
+        key_f51,                    // key_f51, kf51, Ff
+        key_f52,                    // key_f52, kf52, Fg
+        key_f53,                    // key_f53, kf53, Fh
+        key_f54,                    // key_f54, kf54, Fi
+        key_f55,                    // key_f55, kf55, Fj
+        key_f56,                    // key_f56, kf56, Fk
+        key_f57,                    // key_f57, kf57, Fl
+        key_f58,                    // key_f58, kf58, Fm
+        key_f59,                    // key_f59, kf59, Fn
+        key_f6,                     // key_f6, kf6, k6
+        key_f60,                    // key_f60, kf60, Fo
+        key_f61,                    // key_f61, kf61, Fp
+        key_f62,                    // key_f62, kf62, Fq
+        key_f63,                    // key_f63, kf63, Fr
+        key_f7,                     // key_f7, kf7, k7
+        key_f8,                     // key_f8, kf8, k8
+        key_f9,                     // key_f9, kf9, k9
+        key_find,                   // key_find, kfnd, @0
+        key_help,                   // key_help, khlp, %1
+        key_home,                   // key_home, khome, kh
+        key_ic,                     // key_ic, kich1, kI
+        key_il,                     // key_il, kil1, kA
+        key_left,                   // key_left, kcub1, kl
+        key_ll,                     // key_ll, kll, kH
+        key_mark,                   // key_mark, kmrk, %2
+        key_message,                // key_message, kmsg, %3
+        key_move,                   // key_move, kmov, %4
+        key_next,                   // key_next, knxt, %5
+        key_npage,                  // key_npage, knp, kN
+        key_open,                   // key_open, kopn, %6
+        key_options,                // key_options, kopt, %7
+        key_ppage,                  // key_ppage, kpp, kP
+        key_previous,               // key_previous, kprv, %8
+        key_print,                  // key_print, kprt, %9
+        key_redo,                   // key_redo, krdo, %0
+        key_reference,              // key_reference, kref, &1
+        key_refresh,                // key_refresh, krfr, &2
+        key_replace,                // key_replace, krpl, &3
+        key_restart,                // key_restart, krst, &4
+        key_resume,                 // key_resume, kres, &5
+        key_right,                  // key_right, kcuf1, kr
+        key_save,                   // key_save, ksav, &6
+        key_sbeg,                   // key_sbeg, kBEG, &9
+        key_scancel,                // key_scancel, kCAN, &0
+        key_scommand,               // key_scommand, kCMD, *1
+        key_scopy,                  // key_scopy, kCPY, *2
+        key_screate,                // key_screate, kCRT, *3
+        key_sdc,                    // key_sdc, kDC, *4
+        key_sdl,                    // key_sdl, kDL, *5
+        key_select,                 // key_select, kslt, *6
+        key_send,                   // key_send, kEND, *7
+        key_seol,                   // key_seol, kEOL, *8
+        key_sexit,                  // key_sexit, kEXT, *9
+        key_sf,                     // key_sf, kind, kF
+        key_sfind,                  // key_sfind, kFND, *0
+        key_shelp,                  // key_shelp, kHLP, #1
+        key_shome,                  // key_shome, kHOM, #2
+        key_sic,                    // key_sic, kIC, #3
+        key_sleft,                  // key_sleft, kLFT, #4
+        key_smessage,               // key_smessage, kMSG, %a
+        key_smove,                  // key_smove, kMOV, %b
+        key_snext,                  // key_snext, kNXT, %c
+        key_soptions,               // key_soptions, kOPT, %d
+        key_sprevious,              // key_sprevious, kPRV, %e
+        key_sprint,                 // key_sprint, kPRT, %f
+        key_sr,                     // key_sr, kri, kR
+        key_sredo,                  // key_sredo, kRDO, %g
+        key_sreplace,               // key_sreplace, kRPL, %h
+        key_sright,                 // key_sright, kRIT, %i
+        key_srsume,                 // key_srsume, kRES, %j
+        key_ssave,                  // key_ssave, kSAV, !1
+        key_ssuspend,               // key_ssuspend, kSPD, !2
+        key_stab,                   // key_stab, khts, kT
+        key_sundo,                  // key_sundo, kUND, !3
+        key_suspend,                // key_suspend, kspd, &7
+        key_undo,                   // key_undo, kund, &8
+        key_up,                     // key_up, kcuu1, ku
+        keypad_local,               // keypad_local, rmkx, ke
+        keypad_xmit,                // keypad_xmit, smkx, ks
+        lab_f0,                     // lab_f0, lf0, l0
+        lab_f1,                     // lab_f1, lf1, l1
+        lab_f10,                    // lab_f10, lf10, la
+        lab_f2,                     // lab_f2, lf2, l2
+        lab_f3,                     // lab_f3, lf3, l3
+        lab_f4,                     // lab_f4, lf4, l4
+        lab_f5,                     // lab_f5, lf5, l5
+        lab_f6,                     // lab_f6, lf6, l6
+        lab_f7,                     // lab_f7, lf7, l7
+        lab_f8,                     // lab_f8, lf8, l8
+        lab_f9,                     // lab_f9, lf9, l9
+        label_format,               // label_format, fln, Lf
+        label_off,                  // label_off, rmln, LF
+        label_on,                   // label_on, smln, LO
+        meta_off,                   // meta_off, rmm, mo
+        meta_on,                    // meta_on, smm, mm
+        micro_column_address,       // micro_column_address, mhpa, ZY
+        micro_down,                 // micro_down, mcud1, ZZ
+        micro_left,                 // micro_left, mcub1, Za
+        micro_right,                // micro_right, mcuf1, Zb
+        micro_row_address,          // micro_row_address, mvpa, Zc
+        micro_up,                   // micro_up, mcuu1, Zd
+        newline,                    // newline, nel, nw
+        order_of_pins,              // order_of_pins, porder, Ze
+        orig_colors,                // orig_colors, oc, oc
+        orig_pair,                  // orig_pair, op, op
+        pad_char,                   // pad_char, pad, pc
+        parm_dch,                   // parm_dch, dch, DC
+        parm_delete_line,           // parm_delete_line, dl, DL
+        parm_down_cursor,           // parm_down_cursor, cud, DO
+        parm_down_micro,            // parm_down_micro, mcud, Zf
+        parm_ich,                   // parm_ich, ich, IC
+        parm_index,                 // parm_index, indn, SF
+        parm_insert_line,           // parm_insert_line, il, AL
+        parm_left_cursor,           // parm_left_cursor, cub, LE
+        parm_left_micro,            // parm_left_micro, mcub, Zg
+        parm_right_cursor,          // parm_right_cursor, cuf, RI
+        parm_right_micro,           // parm_right_micro, mcuf, Zh
+        parm_rindex,                // parm_rindex, rin, SR
+        parm_up_cursor,             // parm_up_cursor, cuu, UP
+        parm_up_micro,              // parm_up_micro, mcuu, Zi
+        pkey_key,                   // pkey_key, pfkey, pk
+        pkey_local,                 // pkey_local, pfloc, pl
+        pkey_xmit,                  // pkey_xmit, pfx, px
+        plab_norm,                  // plab_norm, pln, pn
+        print_screen,               // print_screen, mc0, ps
+        prtr_non,                   // prtr_non, mc5p, pO
+        prtr_off,                   // prtr_off, mc4, pf
+        prtr_on,                    // prtr_on, mc5, po
+        pulse,                      // pulse, pulse, PU
+        quick_dial,                 // quick_dial, qdial, QD
+        remove_clock,               // remove_clock, rmclk, RC
+        repeat_char,                // repeat_char, rep, rp
+        req_for_input,              // req_for_input, rfi, RF
+        reset_1string,              // reset_1string, rs1, r1
+        reset_2string,              // reset_2string, rs2, r2
+        reset_3string,              // reset_3string, rs3, r3
+        reset_file,                 // reset_file, rf, rf
+        restore_cursor,             // restore_cursor, rc, rc
+        row_address,                // row_address, vpa, cv
+        save_cursor,                // save_cursor, sc, sc
+        scroll_forward,             // scroll_forward, ind, sf
+        scroll_reverse,             // scroll_reverse, ri, sr
+        select_char_set,            // select_char_set, scs, Zj
+        set_attributes,             // set_attributes, sgr, sa
+        set_background,             // set_background, setb, Sb
+        set_bottom_margin,          // set_bottom_margin, smgb, Zk
+        set_bottom_margin_parm,     // set_bottom_margin_parm, smgbp, Zl
+        set_clock,                  // set_clock, sclk, SC
+        set_color_pair,             // set_color_pair, scp, sp
+        set_foreground,             // set_foreground, setf, Sf
+        set_left_margin,            // set_left_margin, smgl, ML
+        set_left_margin_parm,       // set_left_margin_parm, smglp, Zm
+        set_right_margin,           // set_right_margin, smgr, MR
+        set_right_margin_parm,      // set_right_margin_parm, smgrp, Zn
+        set_tab,                    // set_tab, hts, st
+        set_top_margin,             // set_top_margin, smgt, Zo
+        set_top_margin_parm,        // set_top_margin_parm, smgtp, Zp
+        set_window,                 // set_window, wind, wi
+        start_bit_image,            // start_bit_image, sbim, Zq
+        start_char_set_def,         // start_char_set_def, scsd, Zr
+        stop_bit_image,             // stop_bit_image, rbim, Zs
+        stop_char_set_def,          // stop_char_set_def, rcsd, Zt
+        subscript_characters,       // subscript_characters, subcs, Zu
+        superscript_characters,     // superscript_characters, supcs, Zv
+        tab,                        // tab, ht, ta
+        these_cause_cr,             // these_cause_cr, docr, Zw
+        to_status_line,             // to_status_line, tsl, ts
+        tone,                       // tone, tone, TO
+        underline_char,             // underline_char, uc, uc
+        up_half_line,               // up_half_line, hu, hu
+        user0,                      // user0, u0, u0
+        user1,                      // user1, u1, u1
+        user2,                      // user2, u2, u2
+        user3,                      // user3, u3, u3
+        user4,                      // user4, u4, u4
+        user5,                      // user5, u5, u5
+        user6,                      // user6, u6, u6
+        user7,                      // user7, u7, u7
+        user8,                      // user8, u8, u8
+        user9,                      // user9, u9, u9
+        wait_tone,                  // wait_tone, wait, WA
+        xoff_character,             // xoff_character, xoffc, XF
+        xon_character,              // xon_character, xonc, XN
+        zero_motion,                // zero_motion, zerom, Zx
+        alt_scancode_esc,           // alt_scancode_esc, scesa, S8
+        bit_image_carriage_return,  // bit_image_carriage_return, bicr, Yv
+        bit_image_newline,          // bit_image_newline, binel, Zz
+        bit_image_repeat,           // bit_image_repeat, birep, Xy
+        char_set_names,             // char_set_names, csnm, Zy
+        code_set_init,              // code_set_init, csin, ci
+        color_names,                // color_names, colornm, Yw
+        define_bit_image_region,    // define_bit_image_region, defbi, Yx
+        device_type,                // device_type, devt, dv
+        display_pc_char,            // display_pc_char, dispc, S1
+        end_bit_image_region,       // end_bit_image_region, endbi, Yy
+        enter_pc_charset_mode,      // enter_pc_charset_mode, smpch, S2
+        enter_scancode_mode,        // enter_scancode_mode, smsc, S4
+        exit_pc_charset_mode,       // exit_pc_charset_mode, rmpch, S3
+        exit_scancode_mode,         // exit_scancode_mode, rmsc, S5
+        get_mouse,                  // get_mouse, getm, Gm
+        key_mouse,                  // key_mouse, kmous, Km
+        mouse_info,                 // mouse_info, minfo, Mi
+        pc_term_options,            // pc_term_options, pctrm, S6
+        pkey_plab,                  // pkey_plab, pfxl, xl
+        req_mouse_pos,              // req_mouse_pos, reqmp, RQ
+        scancode_escape,            // scancode_escape, scesc, S7
+        set0_des_seq,               // set0_des_seq, s0ds, s0
+        set1_des_seq,               // set1_des_seq, s1ds, s1
+        set2_des_seq,               // set2_des_seq, s2ds, s2
+        set3_des_seq,               // set3_des_seq, s3ds, s3
+        set_a_background,           // set_a_background, setab, AB
+        set_a_foreground,           // set_a_foreground, setaf, AF
+        set_color_band,             // set_color_band, setcolor, Yz
+        set_lr_margin,              // set_lr_margin, smglr, ML
+        set_page_length,            // set_page_length, slines, YZ
+        set_tb_margin,              // set_tb_margin, smgtb, MT
+        enter_horizontal_hl_mode,   // enter_horizontal_hl_mode, ehhlm, Xh
+        enter_left_hl_mode,         // enter_left_hl_mode, elhlm, Xl
+        enter_low_hl_mode,          // enter_low_hl_mode, elohlm, Xo
+        enter_right_hl_mode,        // enter_right_hl_mode, erhlm, Xr
+        enter_top_hl_mode,          // enter_top_hl_mode, ethlm, Xt
+        enter_vertical_hl_mode,     // enter_vertical_hl_mode, evhlm, Xv
+        set_a_attributes,           // set_a_attributes, sgr1, sA
+        set_pglen_inch,             // set_pglen_inch, slength, sL)
+        ;
+
+        public String[] getNames() {
+            return getCapabilitiesByName().entrySet().stream()
+                    .filter(e -> e.getValue() == this)
+                    .map(Map.Entry::getValue)
+                    .toArray(String[]::new);
+        }
+
+        public static Capability byName(String name) {
+            return getCapabilitiesByName().get(name);
+        }
+    }
+
+    public static Map<String, Capability> getCapabilitiesByName() {
+        Map<String, Capability> capabilities = new LinkedHashMap<>();
+        try (InputStream is = InfoCmp.class.getResourceAsStream("capabilities.txt");
+             BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+            br.lines().map(String::trim)
+                    .filter(s -> !s.startsWith("#"))
+                    .filter(s -> !s.isEmpty())
+                    .forEach(s -> {
+                        String[] names = s.split(", ");
+                        Capability cap = Enum.valueOf(Capability.class, names[0]);
+                        capabilities.put(names[0], cap);
+                        capabilities.put(names[1], cap);
+                    });
+            return capabilities;
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    public static void setDefaultInfoCmp(String terminal, String caps) {
+        CAPS.putIfAbsent(terminal, caps);
+    }
+
+    public static void setDefaultInfoCmp(String terminal, Supplier<String> caps) {
+        CAPS.putIfAbsent(terminal, caps);
+    }
+
+    public static String getInfoCmp(
+            String terminal
+    ) throws IOException, InterruptedException {
+        String caps = getLoadedInfoCmp(terminal);
+        if (caps == null) {
+            Process p = new ProcessBuilder(OSUtils.INFOCMP_COMMAND, terminal).start();
+            caps = ExecHelper.waitAndCapture(p);
+            CAPS.put(terminal, caps);
+        }
+        return caps;
+    }
+
+    public static String getLoadedInfoCmp(String terminal) {
+        Object caps = CAPS.get(terminal);
+        if (caps instanceof Supplier) {
+            caps = ((Supplier) caps).get();
+        }
+        return (String) caps;
+    }
+
+    public static void parseInfoCmp(
+            String capabilities,
+            Set<Capability> bools,
+            Map<Capability, Integer> ints,
+            Map<Capability, String> strings
+    ) {
+        Map<String, Capability> capsByName = getCapabilitiesByName();
+        String[] lines = capabilities.split("\n");
+        for (int i = 1; i < lines.length; i++) {
+            Matcher m = Pattern.compile("\\s*(([^,]|\\\\,)+)\\s*[,$]").matcher(lines[i]);
+            while (m.find()) {
+                String cap = m.group(1);
+                if (cap.contains("#")) {
+                    int index = cap.indexOf('#');
+                    String key = cap.substring(0, index);
+                    String val = cap.substring(index + 1);
+                    int iVal;
+                    if (val.startsWith("0x")) {
+                        iVal = Integer.parseInt(val.substring(2), 16);
+                    } else {
+                        iVal = Integer.parseInt(val);
+                    }
+                    Capability c = capsByName.get(key);
+                    if (c != null) {
+                        ints.put(c, iVal);
+                    }
+                } else if (cap.contains("=")) {
+                    int index = cap.indexOf('=');
+                    String key = cap.substring(0, index);
+                    String val = cap.substring(index + 1);
+                    Capability c = capsByName.get(key);
+                    if (c != null) {
+                        strings.put(c, val);
+                    }
+                } else {
+                    Capability c = capsByName.get(cap);
+                    if (c != null) {
+                        bools.add(c);
+                    }
+                }
+            }
+        }
+    }
+
+    static String loadDefaultInfoCmp(String name) {
+        try (InputStream is = InfoCmp.class.getResourceAsStream(name + ".caps");
+             BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+            return br.lines().collect(Collectors.joining("\n", "", "\n"));
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+    }
+
+    static {
+        for (String s : Arrays.asList("dumb", "ansi", "xterm", "xterm-256color",
+                                      "windows", "windows-256color", "windows-vtp",
+                                      "screen", "screen-256color")) {
+            setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+
+/**
+ *
+ * NOTE for JLine: the default InputStreamReader that comes from the JRE
+ * usually read more bytes than needed from the input stream, which
+ * is not usable in a character per character model used in the terminal.
+ * We thus use the harmony code which only reads the minimal number of bytes.
+ */
+
+/**
+ * A class for turning a byte stream into a character stream. Data read from the
+ * source input stream is converted into characters by either a default or a
+ * provided character converter. The default encoding is taken from the
+ * "file.encoding" system property. {@code InputStreamReader} contains a buffer
+ * of bytes read from the source stream and converts these into characters as
+ * needed. The buffer size is 8K.
+ *
+ * @see OutputStreamWriter
+ */
+public class InputStreamReader extends Reader {
+    private InputStream in;
+
+    private static final int BUFFER_SIZE = 4;
+
+    private boolean endOfInput = false;
+
+    CharsetDecoder decoder;
+
+    ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE);
+
+    char pending = (char) -1;
+
+    /**
+     * Constructs a new {@code InputStreamReader} on the {@link InputStream}
+     * {@code in}. This constructor sets the character converter to the encoding
+     * specified in the "file.encoding" property and falls back to ISO 8859_1
+     * (ISO-Latin-1) if the property doesn't exist.
+     *
+     * @param in
+     *            the input stream from which to read characters.
+     */
+    public InputStreamReader(InputStream in) {
+        super(in);
+        this.in = in;
+        decoder = Charset.defaultCharset().newDecoder().onMalformedInput(
+                CodingErrorAction.REPLACE).onUnmappableCharacter(
+                CodingErrorAction.REPLACE);
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in}. The
+     * character converter that is used to decode bytes into characters is
+     * identified by name by {@code enc}. If the encoding cannot be found, an
+     * UnsupportedEncodingException error is thrown.
+     *
+     * @param in
+     *            the InputStream from which to read characters.
+     * @param enc
+     *            identifies the character converter to use.
+     * @throws NullPointerException
+     *             if {@code enc} is {@code null}.
+     * @throws UnsupportedEncodingException
+     *             if the encoding specified by {@code enc} cannot be found.
+     */
+    public InputStreamReader(InputStream in, final String enc)
+            throws UnsupportedEncodingException {
+        super(in);
+        if (enc == null) {
+            throw new NullPointerException();
+        }
+        this.in = in;
+        try {
+            decoder = Charset.forName(enc).newDecoder().onMalformedInput(
+                    CodingErrorAction.REPLACE).onUnmappableCharacter(
+                    CodingErrorAction.REPLACE);
+        } catch (IllegalArgumentException e) {
+            throw (UnsupportedEncodingException)
+                    new UnsupportedEncodingException(enc).initCause(e);
+        }
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in} and
+     * CharsetDecoder {@code dec}.
+     *
+     * @param in
+     *            the source InputStream from which to read characters.
+     * @param dec
+     *            the CharsetDecoder used by the character conversion.
+     */
+    public InputStreamReader(InputStream in, CharsetDecoder dec) {
+        super(in);
+        dec.averageCharsPerByte();
+        this.in = in;
+        decoder = dec;
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in} and
+     * Charset {@code charset}.
+     *
+     * @param in
+     *            the source InputStream from which to read characters.
+     * @param charset
+     *            the Charset that defines the character converter
+     */
+    public InputStreamReader(InputStream in, Charset charset) {
+        super(in);
+        this.in = in;
+        decoder = charset.newDecoder().onMalformedInput(
+                CodingErrorAction.REPLACE).onUnmappableCharacter(
+                CodingErrorAction.REPLACE);
+        bytes.limit(0);
+    }
+
+    /**
+     * Closes this reader. This implementation closes the source InputStream and
+     * releases all local storage.
+     *
+     * @throws IOException
+     *             if an error occurs attempting to close this reader.
+     */
+    @Override
+    public void close() throws IOException {
+        synchronized (lock) {
+            decoder = null;
+            if (in != null) {
+                in.close();
+                in = null;
+            }
+        }
+    }
+
+    /**
+     * Returns the name of the encoding used to convert bytes into characters.
+     * The value {@code null} is returned if this reader has been closed.
+     *
+     * @return the name of the character converter or {@code null} if this
+     *         reader is closed.
+     */
+    public String getEncoding() {
+        if (!isOpen()) {
+            return null;
+        }
+        return decoder.charset().name();
+    }
+
+    /**
+     * Reads a single character from this reader and returns it as an integer
+     * with the two higher-order bytes set to 0. Returns -1 if the end of the
+     * reader has been reached. The byte value is either obtained from
+     * converting bytes in this reader's buffer or by first filling the buffer
+     * from the source InputStream and then reading from the buffer.
+     *
+     * @return the character read or -1 if the end of the reader has been
+     *         reached.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public int read() throws IOException {
+        synchronized (lock) {
+            if (!isOpen()) {
+                throw new ClosedException("InputStreamReader is closed.");
+            }
+
+            if (pending != (char) -1) {
+                char c = pending;
+                pending = (char) -1;
+                return c;
+            }
+            char buf[] = new char[2];
+            int nb = read(buf, 0, 2);
+            if (nb == 2) {
+                pending = buf[1];
+            }
+            if (nb > 0) {
+                return buf[0];
+            } else {
+                return -1;
+            }
+        }
+    }
+
+    /**
+     * Reads at most {@code length} characters from this reader and stores them
+     * at position {@code offset} in the character array {@code buf}. Returns
+     * the number of characters actually read or -1 if the end of the reader has
+     * been reached. The bytes are either obtained from converting bytes in this
+     * reader's buffer or by first filling the buffer from the source
+     * InputStream and then reading from the buffer.
+     *
+     * @param buf
+     *            the array to store the characters read.
+     * @param offset
+     *            the initial position in {@code buf} to store the characters
+     *            read from this reader.
+     * @param length
+     *            the maximum number of characters to read.
+     * @return the number of characters read or -1 if the end of the reader has
+     *         been reached.
+     * @throws IndexOutOfBoundsException
+     *             if {@code offset < 0} or {@code length < 0}, or if
+     *             {@code offset + length} is greater than the length of
+     *             {@code buf}.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public int read(char[] buf, int offset, int length) throws IOException {
+        synchronized (lock) {
+            if (!isOpen()) {
+                throw new IOException("InputStreamReader is closed.");
+            }
+            if (offset < 0 || offset > buf.length - length || length < 0) {
+                throw new IndexOutOfBoundsException();
+            }
+            if (length == 0) {
+                return 0;
+            }
+
+            CharBuffer out = CharBuffer.wrap(buf, offset, length);
+            CoderResult result = CoderResult.UNDERFLOW;
+
+            // bytes.remaining() indicates number of bytes in buffer
+            // when 1-st time entered, it'll be equal to zero
+            boolean needInput = !bytes.hasRemaining();
+
+            while (out.position() == offset) {
+                // fill the buffer if needed
+                if (needInput) {
+                    try {
+                        if ((in.available() == 0)
+                            && (out.position() > offset)) {
+                            // we could return the result without blocking read
+                            break;
+                        }
+                    } catch (IOException e) {
+                        // available didn't work so just try the read
+                    }
+
+                    int off = bytes.arrayOffset() + bytes.limit();
+                    int was_red = in.read(bytes.array(), off, 1);
+
+                    if (was_red == -1) {
+                        endOfInput = true;
+                        break;
+                    } else if (was_red == 0) {
+                        break;
+                    }
+                    bytes.limit(bytes.limit() + was_red);
+                }
+
+                // decode bytes
+                result = decoder.decode(bytes, out, false);
+
+                if (result.isUnderflow()) {
+                    // compact the buffer if no space left
+                    if (bytes.limit() == bytes.capacity()) {
+                        bytes.compact();
+                        bytes.limit(bytes.position());
+                        bytes.position(0);
+                    }
+                    needInput = true;
+                } else {
+                    break;
+                }
+            }
+
+            if (result == CoderResult.UNDERFLOW && endOfInput) {
+                result = decoder.decode(bytes, out, true);
+                decoder.flush(out);
+                decoder.reset();
+            }
+            if (result.isMalformed()) {
+                throw new MalformedInputException(result.length());
+            } else if (result.isUnmappable()) {
+                throw new UnmappableCharacterException(result.length());
+            }
+
+            return out.position() - offset == 0 ? -1 : out.position() - offset;
+        }
+    }
+
+    /*
+     * Answer a boolean indicating whether or not this InputStreamReader is
+     * open.
+     */
+    private boolean isOpen() {
+        return in != null;
+    }
+
+    /**
+     * Indicates whether this reader is ready to be read without blocking. If
+     * the result is {@code true}, the next {@code read()} will not block. If
+     * the result is {@code false} then this reader may or may not block when
+     * {@code read()} is called. This implementation returns {@code true} if
+     * there are bytes available in the buffer or the source stream has bytes
+     * available.
+     *
+     * @return {@code true} if the receiver will not block when {@code read()}
+     *         is called, {@code false} if unknown or blocking will occur.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public boolean ready() throws IOException {
+        synchronized (lock) {
+            if (in == null) {
+                throw new IOException("InputStreamReader is closed.");
+            }
+            try {
+                return bytes.hasRemaining() || in.available() > 0;
+            } catch (IOException e) {
+                return false;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The Damerau-Levenshtein Algorithm is an extension to the Levenshtein
+ * Algorithm which solves the edit distance problem between a source string and
+ * a target string with the following operations:
+ *
+ * <ul>
+ * <li>Character Insertion</li>
+ * <li>Character Deletion</li>
+ * <li>Character Replacement</li>
+ * <li>Adjacent Character Swap</li>
+ * </ul>
+ *
+ * Note that the adjacent character swap operation is an edit that may be
+ * applied when two adjacent characters in the source string match two adjacent
+ * characters in the target string, but in reverse order, rather than a general
+ * allowance for adjacent character swaps.
+ * <p>
+ *
+ * This implementation allows the client to specify the costs of the various
+ * edit operations with the restriction that the cost of two swap operations
+ * must not be less than the cost of a delete operation followed by an insert
+ * operation. This restriction is required to preclude two swaps involving the
+ * same character being required for optimality which, in turn, enables a fast
+ * dynamic programming solution.
+ * <p>
+ *
+ * The running time of the Damerau-Levenshtein algorithm is O(n*m) where n is
+ * the length of the source string and m is the length of the target string.
+ * This implementation consumes O(n*m) space.
+ *
+ * @author Kevin L. Stern
+ */
+public class Levenshtein {
+
+    public static int distance(CharSequence lhs, CharSequence rhs) {
+        return distance(lhs, rhs, 1, 1, 1, 1);
+    }
+
+    public static int distance(CharSequence source, CharSequence target,
+                               int deleteCost, int insertCost,
+                               int replaceCost, int swapCost) {
+        /*
+         * Required to facilitate the premise to the algorithm that two swaps of the
+         * same character are never required for optimality.
+         */
+        if (2 * swapCost < insertCost + deleteCost) {
+            throw new IllegalArgumentException("Unsupported cost assignment");
+        }
+        if (source.length() == 0) {
+            return target.length() * insertCost;
+        }
+        if (target.length() == 0) {
+            return source.length() * deleteCost;
+        }
+        int[][] table = new int[source.length()][target.length()];
+        Map<Character, Integer> sourceIndexByCharacter = new HashMap<>();
+        if (source.charAt(0) != target.charAt(0)) {
+            table[0][0] = Math.min(replaceCost, deleteCost + insertCost);
+        }
+        sourceIndexByCharacter.put(source.charAt(0), 0);
+        for (int i = 1; i < source.length(); i++) {
+            int deleteDistance = table[i - 1][0] + deleteCost;
+            int insertDistance = (i + 1) * deleteCost + insertCost;
+            int matchDistance = i * deleteCost + (source.charAt(i) == target.charAt(0) ? 0 : replaceCost);
+            table[i][0] = Math.min(Math.min(deleteDistance, insertDistance), matchDistance);
+        }
+        for (int j = 1; j < target.length(); j++) {
+            int deleteDistance = (j + 1) * insertCost + deleteCost;
+            int insertDistance = table[0][j - 1] + insertCost;
+            int matchDistance = j * insertCost + (source.charAt(0) == target.charAt(j) ? 0 : replaceCost);
+            table[0][j] = Math.min(Math.min(deleteDistance, insertDistance), matchDistance);
+        }
+        for (int i = 1; i < source.length(); i++) {
+            int maxSourceLetterMatchIndex = source.charAt(i) == target.charAt(0) ? 0 : -1;
+            for (int j = 1; j < target.length(); j++) {
+                Integer candidateSwapIndex = sourceIndexByCharacter.get(target.charAt(j));
+                int jSwap = maxSourceLetterMatchIndex;
+                int deleteDistance = table[i - 1][j] + deleteCost;
+                int insertDistance = table[i][j - 1] + insertCost;
+                int matchDistance = table[i - 1][j - 1];
+                if (source.charAt(i) != target.charAt(j)) {
+                    matchDistance += replaceCost;
+                } else {
+                    maxSourceLetterMatchIndex = j;
+                }
+                int swapDistance;
+                if (candidateSwapIndex != null && jSwap != -1) {
+                    int iSwap = candidateSwapIndex;
+                    int preSwapCost;
+                    if (iSwap == 0 && jSwap == 0) {
+                        preSwapCost = 0;
+                    } else {
+                        preSwapCost = table[Math.max(0, iSwap - 1)][Math.max(0, jSwap - 1)];
+                    }
+                    swapDistance = preSwapCost + (i - iSwap - 1) * deleteCost + (j - jSwap - 1) * insertCost + swapCost;
+                } else {
+                    swapDistance = Integer.MAX_VALUE;
+                }
+                table[i][j] = Math.min(Math.min(Math.min(deleteDistance, insertDistance), matchDistance), swapDistance);
+            }
+            sourceIndexByCharacter.put(source.charAt(i), i);
+        }
+        return table[source.length() - 1][target.length() - 1];
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.function.Supplier;
+//import java.util.logging.Level;
+//import java.util.logging.LogRecord;
+//import java.util.logging.Logger;
+
+/**
+ * Internal logger.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.0
+ */
+public final class Log
+{
+    public static void trace(final Object... messages) {
+//        log(Level.FINEST, messages);
+    }
+
+    public static void trace(Supplier<String> supplier) {
+//        log(Level.FINEST, supplier);
+    }
+
+    public static void debug(Supplier<String> supplier) {
+//        log(Level.FINE, supplier);
+    }
+
+    public static void debug(final Object... messages) {
+//        log(Level.FINE, messages);
+    }
+
+    public static void info(final Object... messages) {
+//        log(Level.INFO, messages);
+    }
+
+    public static void warn(final Object... messages) {
+//        log(Level.WARNING, messages);
+    }
+
+    public static void error(final Object... messages) {
+//        log(Level.SEVERE, messages);
+    }
+
+    public static boolean isDebugEnabled() {
+//        return isEnabled(Level.FINE);
+        return false;
+    }
+
+    /**
+     * Helper to support rendering messages.
+     */
+    static void render(final PrintStream out, final Object message) {
+        if (message != null && message.getClass().isArray()) {
+            Object[] array = (Object[]) message;
+
+            out.print("[");
+            for (int i = 0; i < array.length; i++) {
+                out.print(array[i]);
+                if (i + 1 < array.length) {
+                    out.print(",");
+                }
+            }
+            out.print("]");
+        }
+        else {
+            out.print(message);
+        }
+    }
+
+//    static LogRecord createRecord(final Level level, final Object... messages) {
+//        Throwable cause = null;
+//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//        PrintStream ps = new PrintStream(baos);
+//        for (int i = 0; i < messages.length; i++) {
+//            // Special handling for the last message if its a throwable, render its stack on the next line
+//            if (i + 1 == messages.length && messages[i] instanceof Throwable) {
+//                cause = (Throwable) messages[i];
+//            }
+//            else {
+//                render(ps, messages[i]);
+//            }
+//        }
+//        ps.close();
+//        LogRecord r = new LogRecord(level, baos.toString());
+//        r.setThrown(cause);
+//        return r;
+//    }
+//
+//    static LogRecord createRecord(final Level level, final Supplier<String> message) {
+//        return new LogRecord(level, message.get());
+//    }
+//
+//    static void log(final Level level, final Supplier<String> message) {
+//        logr(level, () -> createRecord(level, message));
+//    }
+//
+//    static void log(final Level level, final Object... messages) {
+//        logr(level, () -> createRecord(level, messages));
+//    }
+//
+//    static void logr(final Level level, final Supplier<LogRecord> record) {
+//        Logger logger = Logger.getLogger("org.jline");
+//        if (logger.isLoggable(level)) {
+//            // inform record of the logger-name
+//            LogRecord tmp = record.get();
+//            tmp.setLoggerName(logger.getName());
+//            logger.log(tmp);
+//        }
+//    }
+//
+//    static boolean isEnabled(Level level) {
+//        Logger logger = Logger.getLogger("org.jline");
+//        return logger.isLoggable(level);
+//    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+
+public class NonBlocking {
+
+    public static NonBlockingPumpReader nonBlockingPumpReader() {
+        return new NonBlockingPumpReader();
+    }
+
+    public static NonBlockingPumpReader nonBlockingPumpReader(int size) {
+        return new NonBlockingPumpReader(size);
+    }
+
+    public static NonBlockingPumpInputStream nonBlockingPumpInputStream() {
+        return new NonBlockingPumpInputStream();
+    }
+
+    public static NonBlockingPumpInputStream nonBlockingPumpInputStream(int size) {
+        return new NonBlockingPumpInputStream(size);
+    }
+
+    public static NonBlockingInputStream nonBlockingStream(NonBlockingReader reader, Charset encoding) {
+        return new NonBlockingReaderInputStream(reader, encoding);
+    }
+
+    public static NonBlockingInputStream nonBlocking(String name, InputStream inputStream) {
+        if (inputStream instanceof NonBlockingInputStream) {
+            return (NonBlockingInputStream) inputStream;
+        }
+        return new NonBlockingInputStreamImpl(name, inputStream);
+    }
+
+    public static NonBlockingReader nonBlocking(String name, Reader reader) {
+        if (reader instanceof NonBlockingReader) {
+            return (NonBlockingReader) reader;
+        }
+        return new NonBlockingReaderImpl(name, reader);
+    }
+
+    public static NonBlockingReader nonBlocking(String name, InputStream inputStream, Charset encoding) {
+        return new NonBlockingInputStreamReader(nonBlocking(name, inputStream), encoding);
+    }
+
+    private static class NonBlockingReaderInputStream extends NonBlockingInputStream {
+
+        private final NonBlockingReader reader;
+        private final CharsetEncoder encoder;
+
+        // To encode a character with multiple bytes (e.g. certain Unicode characters)
+        // we need enough space to encode them. Reading would fail if the read() method
+        // is used to read a single byte in these cases.
+        // Use this buffer to ensure we always have enough space to encode a character.
+        private final ByteBuffer bytes;
+        private final CharBuffer chars;
+
+        private NonBlockingReaderInputStream(NonBlockingReader reader, Charset charset) {
+            this.reader = reader;
+            this.encoder = charset.newEncoder()
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE)
+                    .onMalformedInput(CodingErrorAction.REPLACE);
+            this.bytes = ByteBuffer.allocate(4);
+            this.chars = CharBuffer.allocate(2);
+            // No input available after initialization
+            this.bytes.limit(0);
+            this.chars.limit(0);
+        }
+
+        @Override
+        public int available() {
+            return (int) (reader.available() * this.encoder.averageBytesPerChar())
+                    + bytes.remaining();
+        }
+
+        @Override
+        public void close() throws IOException {
+            reader.close();
+        }
+
+        @Override
+        public int read(long timeout, boolean isPeek) throws IOException {
+            boolean isInfinite = (timeout <= 0L);
+            while (!bytes.hasRemaining() && (isInfinite || timeout > 0L)) {
+                long start = 0;
+                if (!isInfinite) {
+                    start = System.currentTimeMillis();
+                }
+                int c = reader.read(timeout);
+                if (c == EOF) {
+                    return EOF;
+                }
+                if (c >= 0) {
+                    if (!chars.hasRemaining()) {
+                        chars.position(0);
+                        chars.limit(0);
+                    }
+                    int l = chars.limit();
+                    chars.array()[chars.arrayOffset() + l] = (char) c;
+                    chars.limit(l + 1);
+                    bytes.clear();
+                    encoder.encode(chars, bytes, false);
+                    bytes.flip();
+                }
+                if (!isInfinite) {
+                    timeout -= System.currentTimeMillis() - start;
+                }
+            }
+            if (bytes.hasRemaining()) {
+                if (isPeek) {
+                    return bytes.get(bytes.position());
+                } else {
+                    return bytes.get();
+                }
+            } else {
+                return READ_EXPIRED;
+            }
+        }
+
+    }
+
+    private static class NonBlockingInputStreamReader extends NonBlockingReader {
+
+        private final NonBlockingInputStream input;
+        private final CharsetDecoder decoder;
+        private final ByteBuffer bytes;
+        private final CharBuffer chars;
+
+        public NonBlockingInputStreamReader(NonBlockingInputStream inputStream, Charset encoding) {
+            this(inputStream,
+                (encoding != null ? encoding : Charset.defaultCharset()).newDecoder()
+                    .onMalformedInput(CodingErrorAction.REPLACE)
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE));
+        }
+
+        public NonBlockingInputStreamReader(NonBlockingInputStream input, CharsetDecoder decoder) {
+            this.input = input;
+            this.decoder = decoder;
+            this.bytes = ByteBuffer.allocate(4);
+            this.chars = CharBuffer.allocate(2);
+            this.bytes.limit(0);
+            this.chars.limit(0);
+        }
+
+        @Override
+        protected int read(long timeout, boolean isPeek) throws IOException {
+            boolean isInfinite = (timeout <= 0L);
+            while (!chars.hasRemaining() && (isInfinite || timeout > 0L)) {
+                long start = 0;
+                if (!isInfinite) {
+                    start = System.currentTimeMillis();
+                }
+                int b = input.read(timeout);
+                if (b == EOF) {
+                    return EOF;
+                }
+                if (b >= 0) {
+                    if (!bytes.hasRemaining()) {
+                        bytes.position(0);
+                        bytes.limit(0);
+                    }
+                    int l = bytes.limit();
+                    bytes.array()[bytes.arrayOffset() + l] = (byte) b;
+                    bytes.limit(l + 1);
+                    chars.clear();
+                    decoder.decode(bytes, chars, false);
+                    chars.flip();
+                }
+
+                if (!isInfinite) {
+                    timeout -= System.currentTimeMillis() - start;
+                }
+            }
+            if (chars.hasRemaining()) {
+                if (isPeek) {
+                    return chars.get(chars.position());
+                } else {
+                    return chars.get();
+                }
+            } else {
+                return READ_EXPIRED;
+            }
+        }
+
+        @Override
+        public void shutdown() {
+            input.shutdown();
+        }
+
+        @Override
+        public void close() throws IOException {
+            input.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Non blocking input stream
+ */
+public abstract class NonBlockingInputStream extends InputStream {
+
+    public static final int EOF = -1;
+    public static final int READ_EXPIRED = -2;
+
+    /**
+     * Reads the next byte of data from the input stream. The value byte is
+     * returned as an <code>int</code> in the range <code>0</code> to
+     * <code>255</code>. If no byte is available because the end of the stream
+     * has been reached, the value <code>-1</code> is returned. This method
+     * blocks until input data is available, the end of the stream is detected,
+     * or an exception is thrown.
+     *
+     * @return     the next byte of data, or <code>-1</code> if the end of the
+     *             stream is reached.
+     * @exception  IOException  if an I/O error occurs.
+     */
+    @Override
+    public int read() throws IOException {
+        return read(0L, false);
+    }
+
+    /**
+     * Peeks to see if there is a byte waiting in the input stream without
+     * actually consuming the byte.
+     *
+     * @param      timeout The amount of time to wait, 0 == forever
+     * @return     -1 on eof, -2 if the timeout expired with no available input
+     *             or the character that was read (without consuming it).
+     * @exception  IOException  if an I/O error occurs.
+     */
+    public int peek(long timeout) throws IOException {
+        return read(timeout, true);
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     *
+     * @param      timeout      The amount of time to wait for the character
+     * @return     The character read, -1 if EOF is reached,
+     *             or -2 if the read timed out.
+     * @exception  IOException  if an I/O error occurs.
+     */
+    public int read(long timeout) throws IOException {
+        return read(timeout, false);
+    }
+
+    public int read(byte b[], int off, int len) throws IOException {
+        if (b == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || len < 0 || len > b.length - off) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return 0;
+        }
+        int c = read();
+        if (c == EOF) {
+            return EOF;
+        }
+        b[off] = (byte)c;
+        return 1;
+    }
+
+    /**
+     * Shuts down the thread that is handling blocking I/O if any. Note that if the
+     * thread is currently blocked waiting for I/O it may not actually
+     * shut down until the I/O is received.
+     */
+    public void shutdown() {
+    }
+
+    public abstract int read(long timeout, boolean isPeek) throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+/**
+ * This class wraps a regular input stream and allows it to appear as if it
+ * is non-blocking; that is, reads can be performed against it that timeout
+ * if no data is seen for a period of time.  This effect is achieved by having
+ * a separate thread perform all non-blocking read requests and then
+ * waiting on the thread to complete.
+ *
+ * <p>VERY IMPORTANT NOTES
+ * <ul>
+ *   <li> This class is not thread safe. It expects at most one reader.
+ *   <li> The {@link #shutdown()} method must be called in order to shut down
+ *          the thread that handles blocking I/O.
+ * </ul>
+ */
+public class NonBlockingInputStreamImpl
+    extends NonBlockingInputStream
+{
+    private InputStream in;                  // The actual input stream
+    private int         b = READ_EXPIRED;    // Recently read byte
+
+    private String      name;
+    private boolean     threadIsReading      = false;
+    private IOException exception            = null;
+    private long        threadDelay          = 60 * 1000;
+    private Thread      thread;
+
+    /**
+     * Creates a <code>NonBlockingReader</code> out of a normal blocking
+     * reader. Note that this call also spawn a separate thread to perform the
+     * blocking I/O on behalf of the thread that is using this class. The
+     * {@link #shutdown()} method must be called in order to shut this thread down.
+     * @param name The stream name
+     * @param in The reader to wrap
+     */
+    public NonBlockingInputStreamImpl(String name, InputStream in) {
+        this.in = in;
+        this.name = name;
+    }
+
+    private synchronized void startReadingThreadIfNeeded() {
+        if (thread == null) {
+            thread = new Thread(this::run);
+            thread.setName(name + " non blocking reader thread");
+            thread.setDaemon(true);
+            thread.start();
+        }
+    }
+
+    /**
+     * Shuts down the thread that is handling blocking I/O. Note that if the
+     * thread is currently blocked waiting for I/O it will not actually
+     * shut down until the I/O is received.
+     */
+    public synchronized void shutdown() {
+        if (thread != null) {
+            notify();
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        /*
+         * The underlying input stream is closed first. This means that if the
+         * I/O thread was blocked waiting on input, it will be woken for us.
+         */
+        in.close();
+        shutdown();
+    }
+
+    /**
+     * Attempts to read a byte from the input stream for a specific
+     * period of time.
+     * @param timeout The amount of time to wait for the character
+     * @param isPeek <code>true</code>if the byte read must not be consumed
+     * @return The byte read, -1 if EOF is reached, or -2 if the
+     *   read timed out.
+     * @throws IOException if anything wrong happens
+     */
+    public synchronized int read(long timeout, boolean isPeek) throws IOException {
+        /*
+         * If the thread hit an IOException, we report it.
+         */
+        if (exception != null) {
+            assert b == READ_EXPIRED;
+            IOException toBeThrown = exception;
+            if (!isPeek)
+                exception = null;
+            throw toBeThrown;
+        }
+
+        /*
+         * If there was a pending character from the thread, then
+         * we send it. If the timeout is 0L or the thread was shut down
+         * then do a local read.
+         */
+        if (b >= -1) {
+            assert exception == null;
+        }
+        else if (!isPeek && timeout <= 0L && !threadIsReading) {
+            b = in.read();
+        }
+        else {
+            /*
+             * If the thread isn't reading already, then ask it to do so.
+             */
+            if (!threadIsReading) {
+                threadIsReading = true;
+                startReadingThreadIfNeeded();
+                notifyAll();
+            }
+
+            boolean isInfinite = (timeout <= 0L);
+
+            /*
+             * So the thread is currently doing the reading for us. So
+             * now we play the waiting game.
+             */
+            while (isInfinite || timeout > 0L)  {
+                long start = System.currentTimeMillis ();
+
+                try {
+                    if (Thread.interrupted()) {
+                        throw new InterruptedException();
+                    }
+                    wait(timeout);
+                }
+                catch (InterruptedException e) {
+                    exception = (IOException) new InterruptedIOException().initCause(e);
+                }
+
+                if (exception != null) {
+                    assert b == READ_EXPIRED;
+
+                    IOException toBeThrown = exception;
+                    if (!isPeek)
+                        exception = null;
+                    throw toBeThrown;
+                }
+
+                if (b >= -1) {
+                    assert exception == null;
+                    break;
+                }
+
+                if (!isInfinite) {
+                    timeout -= System.currentTimeMillis() - start;
+                }
+            }
+        }
+
+        /*
+         * b is the character that was just read. Either we set it because
+         * a local read was performed or the read thread set it (or failed to
+         * change it).  We will return it's value, but if this was a peek
+         * operation, then we leave it in place.
+         */
+        int ret = b;
+        if (!isPeek) {
+            b = READ_EXPIRED;
+        }
+        return ret;
+    }
+
+    private void run () {
+        Log.debug("NonBlockingInputStream start");
+        boolean needToRead;
+
+        try {
+            while (true) {
+
+                /*
+                 * Synchronize to grab variables accessed by both this thread
+                 * and the accessing thread.
+                 */
+                synchronized (this) {
+                    needToRead = this.threadIsReading;
+
+                    try {
+                        /*
+                         * Nothing to do? Then wait.
+                         */
+                        if (!needToRead) {
+                            wait(threadDelay);
+                        }
+                    } catch (InterruptedException e) {
+                        /* IGNORED */
+                    }
+
+                    needToRead = this.threadIsReading;
+                    if (!needToRead) {
+                        return;
+                    }
+                }
+
+                /*
+                 * We're not shutting down, but we need to read. This cannot
+                 * happen while we are holding the lock (which we aren't now).
+                 */
+                int byteRead = READ_EXPIRED;
+                IOException failure = null;
+                try {
+                    byteRead = in.read();
+                } catch (IOException e) {
+                    failure = e;
+                }
+
+                /*
+                 * Re-grab the lock to update the state.
+                 */
+                synchronized (this) {
+                    exception = failure;
+                    b = byteRead;
+                    threadIsReading = false;
+                    notify();
+                }
+
+                // If end of stream, exit the loop thread
+                if (byteRead < 0) {
+                    return;
+                }
+            }
+        } catch (Throwable t) {
+            Log.warn("Error in NonBlockingInputStream thread", t);
+        } finally {
+            Log.debug("NonBlockingInputStream shutdown");
+            synchronized (this) {
+                thread = null;
+                threadIsReading = false;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class NonBlockingPumpInputStream extends NonBlockingInputStream {
+
+    private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+    // Read and write buffer are backed by the same array
+    private final ByteBuffer readBuffer;
+    private final ByteBuffer writeBuffer;
+
+    private final OutputStream output;
+
+    private boolean closed;
+
+    private IOException ioException;
+
+    public NonBlockingPumpInputStream() {
+        this(DEFAULT_BUFFER_SIZE);
+    }
+
+    public NonBlockingPumpInputStream(int bufferSize) {
+        byte[] buf = new byte[bufferSize];
+        this.readBuffer = ByteBuffer.wrap(buf);
+        this.writeBuffer = ByteBuffer.wrap(buf);
+        this.output = new NbpOutputStream();
+        // There are no bytes available to read after initialization
+        readBuffer.limit(0);
+    }
+
+    public OutputStream getOutputStream() {
+        return this.output;
+    }
+
+    private int wait(ByteBuffer buffer, long timeout) throws IOException {
+        boolean isInfinite = (timeout <= 0L);
+        long end = 0;
+        if (!isInfinite) {
+            end = System.currentTimeMillis() + timeout;
+        }
+        while (!closed && !buffer.hasRemaining() && (isInfinite || timeout > 0L)) {
+            // Wake up waiting readers/writers
+            notifyAll();
+            try {
+                wait(timeout);
+                checkIoException();
+            } catch (InterruptedException e) {
+                checkIoException();
+                throw new InterruptedIOException();
+            }
+            if (!isInfinite) {
+                timeout = end - System.currentTimeMillis();
+            }
+        }
+        return buffer.hasRemaining()
+                ? 0
+                : closed
+                    ? EOF
+                    : READ_EXPIRED;
+    }
+
+    private static boolean rewind(ByteBuffer buffer, ByteBuffer other) {
+        // Extend limit of other buffer if there is additional input/output available
+        if (buffer.position() > other.position()) {
+            other.limit(buffer.position());
+        }
+        // If we have reached the end of the buffer, rewind and set the new limit
+        if (buffer.position() == buffer.capacity()) {
+            buffer.rewind();
+            buffer.limit(other.position());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public synchronized int available() {
+        int count = readBuffer.remaining();
+        if (writeBuffer.position() < readBuffer.position()) {
+            count += writeBuffer.position();
+        }
+        return count;
+    }
+
+    @Override
+    public synchronized int read(long timeout, boolean isPeek) throws IOException {
+        checkIoException();
+        // Blocks until more input is available or the reader is closed.
+        int res = wait(readBuffer, timeout);
+        if (res >= 0) {
+            res = readBuffer.get() & 0x00FF;
+        }
+        rewind(readBuffer, writeBuffer);
+        return res;
+    }
+
+    public synchronized void setIoException(IOException exception) {
+        this.ioException = exception;
+        notifyAll();
+    }
+
+    protected synchronized void checkIoException() throws IOException {
+        if (ioException != null) {
+            throw ioException;
+        }
+    }
+
+    synchronized void write(byte[] cbuf, int off, int len) throws IOException {
+        while (len > 0) {
+            // Blocks until there is new space available for buffering or the
+            // reader is closed.
+            if (wait(writeBuffer, 0L) == EOF) {
+                throw new ClosedException();
+            }
+            // Copy as much characters as we can
+            int count = Math.min(len, writeBuffer.remaining());
+            writeBuffer.put(cbuf, off, count);
+            off += count;
+            len -= count;
+            // Update buffer states and rewind if necessary
+            rewind(writeBuffer, readBuffer);
+        }
+    }
+
+    synchronized void flush() {
+        // Avoid waking up readers when there is nothing to read
+        if (readBuffer.hasRemaining()) {
+            // Notify readers
+            notifyAll();
+        }
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        this.closed = true;
+        notifyAll();
+    }
+
+    private class NbpOutputStream extends OutputStream {
+
+        @Override
+        public void write(int b) throws IOException {
+            NonBlockingPumpInputStream.this.write(new byte[] { (byte) b }, 0, 1);
+        }
+
+        @Override
+        public void write(byte[] cbuf, int off, int len) throws IOException {
+            NonBlockingPumpInputStream.this.write(cbuf, off, len);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            NonBlockingPumpInputStream.this.flush();
+        }
+
+        @Override
+        public void close() throws IOException {
+            NonBlockingPumpInputStream.this.close();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.Writer;
+import java.nio.CharBuffer;
+
+public class NonBlockingPumpReader extends NonBlockingReader {
+
+    private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+    // Read and write buffer are backed by the same array
+    private final CharBuffer readBuffer;
+    private final CharBuffer writeBuffer;
+
+    private final Writer writer;
+
+    private boolean closed;
+
+    public NonBlockingPumpReader() {
+        this(DEFAULT_BUFFER_SIZE);
+    }
+
+    public NonBlockingPumpReader(int bufferSize) {
+        char[] buf = new char[bufferSize];
+        this.readBuffer = CharBuffer.wrap(buf);
+        this.writeBuffer = CharBuffer.wrap(buf);
+        this.writer = new NbpWriter();
+        // There are no bytes available to read after initialization
+        readBuffer.limit(0);
+    }
+
+    public Writer getWriter() {
+        return this.writer;
+    }
+
+    private int wait(CharBuffer buffer, long timeout) throws InterruptedIOException {
+        boolean isInfinite = (timeout <= 0L);
+        long end = 0;
+        if (!isInfinite) {
+            end = System.currentTimeMillis() + timeout;
+        }
+        while (!closed && !buffer.hasRemaining() && (isInfinite || timeout > 0L)) {
+            // Wake up waiting readers/writers
+            notifyAll();
+            try {
+                wait(timeout);
+            } catch (InterruptedException e) {
+                throw new InterruptedIOException();
+            }
+            if (!isInfinite) {
+                timeout = end - System.currentTimeMillis();
+            }
+        }
+        return closed
+                ? EOF
+                : buffer.hasRemaining()
+                    ? 0
+                    : READ_EXPIRED;
+    }
+
+    private static boolean rewind(CharBuffer buffer, CharBuffer other) {
+        // Extend limit of other buffer if there is additional input/output available
+        if (buffer.position() > other.position()) {
+            other.limit(buffer.position());
+        }
+        // If we have reached the end of the buffer, rewind and set the new limit
+        if (buffer.position() == buffer.capacity()) {
+            buffer.rewind();
+            buffer.limit(other.position());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public synchronized boolean ready() {
+        return readBuffer.hasRemaining();
+    }
+
+    public synchronized int available() {
+        int count = readBuffer.remaining();
+        if (writeBuffer.position() < readBuffer.position()) {
+            count += writeBuffer.position();
+        }
+        return count;
+    }
+
+    @Override
+    protected synchronized int read(long timeout, boolean isPeek) throws IOException {
+        // Blocks until more input is available or the reader is closed.
+        int res = wait(readBuffer, timeout);
+        if (res >= 0) {
+            res = isPeek ? readBuffer.get(readBuffer.position()) : readBuffer.get();
+        }
+        rewind(readBuffer, writeBuffer);
+        return res;
+    }
+
+    synchronized void write(char[] cbuf, int off, int len) throws IOException {
+        while (len > 0) {
+            // Blocks until there is new space available for buffering or the
+            // reader is closed.
+            if (wait(writeBuffer, 0L) == EOF) {
+                throw new ClosedException();
+            }
+            // Copy as much characters as we can
+            int count = Math.min(len, writeBuffer.remaining());
+            writeBuffer.put(cbuf, off, count);
+            off += count;
+            len -= count;
+            // Update buffer states and rewind if necessary
+            rewind(writeBuffer, readBuffer);
+        }
+    }
+
+    synchronized void flush() {
+        // Avoid waking up readers when there is nothing to read
+        if (readBuffer.hasRemaining()) {
+            // Notify readers
+            notifyAll();
+        }
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        this.closed = true;
+        notifyAll();
+    }
+
+    private class NbpWriter extends Writer {
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            NonBlockingPumpReader.this.write(cbuf, off, len);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            NonBlockingPumpReader.this.flush();
+        }
+
+        @Override
+        public void close() throws IOException {
+            NonBlockingPumpReader.this.close();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Non blocking reader
+ */
+public abstract class NonBlockingReader extends Reader {
+    public static final int EOF = -1;
+    public static final int READ_EXPIRED = -2;
+
+    /**
+     * Shuts down the thread that is handling blocking I/O. Note that if the
+     * thread is currently blocked waiting for I/O it will not actually
+     * shut down until the I/O is received.
+     */
+    public void shutdown() {
+    }
+
+    @Override
+    public int read() throws IOException {
+        return read(0L, false);
+    }
+
+    /**
+     * Peeks to see if there is a byte waiting in the input stream without
+     * actually consuming the byte.
+     *
+     * @param timeout The amount of time to wait, 0 == forever
+     * @return -1 on eof, -2 if the timeout expired with no available input
+     * or the character that was read (without consuming it).
+     * @throws IOException if anything wrong happens
+     */
+    public int peek(long timeout) throws IOException {
+        return read(timeout, true);
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     *
+     * @param timeout The amount of time to wait for the character
+     * @return The character read, -1 if EOF is reached, or -2 if the
+     * read timed out.
+     * @throws IOException if anything wrong happens
+     */
+    public int read(long timeout) throws IOException {
+        return read(timeout, false);
+    }
+
+    /**
+     * This version of read() is very specific to jline's purposes, it
+     * will always always return a single byte at a time, rather than filling
+     * the entire buffer.
+     * @param b the buffer
+     * @param off the offset in the buffer
+     * @param len the maximum number of chars to read
+     * @throws IOException if anything wrong happens
+     */
+    @Override
+    public int read(char[] b, int off, int len) throws IOException {
+        if (b == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || len < 0 || len > b.length - off) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return 0;
+        }
+
+        int c = this.read(0L);
+
+        if (c == EOF) {
+            return EOF;
+        }
+        b[off] = (char) c;
+        return 1;
+    }
+
+    public int available() {
+        return 0;
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     * @param timeout The amount of time to wait for the character
+     * @param isPeek <code>true</code>if the character read must not be consumed
+     * @return The character read, -1 if EOF is reached, or -2 if the
+     *   read timed out.
+     * @throws IOException if anything wrong happens
+     */
+    protected abstract int read(long timeout, boolean isPeek) throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.Reader;
+
+/**
+ * This class wraps a regular reader and allows it to appear as if it
+ * is non-blocking; that is, reads can be performed against it that timeout
+ * if no data is seen for a period of time.  This effect is achieved by having
+ * a separate thread perform all non-blocking read requests and then
+ * waiting on the thread to complete.
+ *
+ * <p>VERY IMPORTANT NOTES
+ * <ul>
+ *   <li> This class is not thread safe. It expects at most one reader.
+ *   <li> The {@link #shutdown()} method must be called in order to shut down
+ *          the thread that handles blocking I/O.
+ * </ul>
+ * @since 2.7
+ * @author Scott C. Gray &lt;scottgray1@gmail.com&gt;
+ */
+public class NonBlockingReaderImpl
+    extends NonBlockingReader
+{
+    public static final int READ_EXPIRED = -2;
+
+    private Reader in;                  // The actual input stream
+    private int    ch   = READ_EXPIRED; // Recently read character
+
+    private String      name;
+    private boolean     threadIsReading      = false;
+    private IOException exception            = null;
+    private long        threadDelay          = 60 * 1000;
+    private Thread      thread;
+
+    /**
+     * Creates a <code>NonBlockingReader</code> out of a normal blocking
+     * reader. Note that this call also spawn a separate thread to perform the
+     * blocking I/O on behalf of the thread that is using this class. The
+     * {@link #shutdown()} method must be called in order to shut this thread down.
+     * @param name The reader name
+     * @param in The reader to wrap
+     */
+    public NonBlockingReaderImpl(String name, Reader in) {
+        this.in = in;
+        this.name = name;
+    }
+
+    private synchronized void startReadingThreadIfNeeded() {
+        if (thread == null) {
+            thread = new Thread(this::run);
+            thread.setName(name + " non blocking reader thread");
+            thread.setDaemon(true);
+            thread.start();
+        }
+    }
+
+    /**
+     * Shuts down the thread that is handling blocking I/O. Note that if the
+     * thread is currently blocked waiting for I/O it will not actually
+     * shut down until the I/O is received.
+     */
+    public synchronized void shutdown() {
+        if (thread != null) {
+            notify();
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        /*
+         * The underlying input stream is closed first. This means that if the
+         * I/O thread was blocked waiting on input, it will be woken for us.
+         */
+        in.close();
+        shutdown();
+    }
+
+    @Override
+    public synchronized boolean ready() throws IOException {
+        return ch >= 0 || in.ready();
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     * @param timeout The amount of time to wait for the character
+     * @return The character read, -1 if EOF is reached, or -2 if the
+     *   read timed out.
+     */
+    protected synchronized int read(long timeout, boolean isPeek) throws IOException {
+        /*
+         * If the thread hit an IOException, we report it.
+         */
+        if (exception != null) {
+            assert ch == READ_EXPIRED;
+            IOException toBeThrown = exception;
+            if (!isPeek)
+                exception = null;
+            throw toBeThrown;
+        }
+
+        /*
+         * If there was a pending character from the thread, then
+         * we send it. If the timeout is 0L or the thread was shut down
+         * then do a local read.
+         */
+        if (ch >= -1) {
+            assert exception == null;
+        }
+        else if (!isPeek && timeout <= 0L && !threadIsReading) {
+            ch = in.read();
+        }
+        else {
+            /*
+             * If the thread isn't reading already, then ask it to do so.
+             */
+            if (!threadIsReading) {
+                threadIsReading = true;
+                startReadingThreadIfNeeded();
+                notifyAll();
+            }
+
+            boolean isInfinite = (timeout <= 0L);
+
+            /*
+             * So the thread is currently doing the reading for us. So
+             * now we play the waiting game.
+             */
+            while (isInfinite || timeout > 0L)  {
+                long start = System.currentTimeMillis ();
+
+                try {
+                    if (Thread.interrupted()) {
+                        throw new InterruptedException();
+                    }
+                    wait(timeout);
+                }
+                catch (InterruptedException e) {
+                    exception = (IOException) new InterruptedIOException().initCause(e);
+                }
+
+                if (exception != null) {
+                    assert ch == READ_EXPIRED;
+
+                    IOException toBeThrown = exception;
+                    if (!isPeek)
+                        exception = null;
+                    throw toBeThrown;
+                }
+
+                if (ch >= -1) {
+                    assert exception == null;
+                    break;
+                }
+
+                if (!isInfinite) {
+                    timeout -= System.currentTimeMillis() - start;
+                }
+            }
+        }
+
+        /*
+         * ch is the character that was just read. Either we set it because
+         * a local read was performed or the read thread set it (or failed to
+         * change it).  We will return it's value, but if this was a peek
+         * operation, then we leave it in place.
+         */
+        int ret = ch;
+        if (!isPeek) {
+            ch = READ_EXPIRED;
+        }
+        return ret;
+    }
+
+    private void run () {
+        Log.debug("NonBlockingReader start");
+        boolean needToRead;
+
+        try {
+            while (true) {
+
+                /*
+                 * Synchronize to grab variables accessed by both this thread
+                 * and the accessing thread.
+                 */
+                synchronized (this) {
+                    needToRead = this.threadIsReading;
+
+                    try {
+                        /*
+                         * Nothing to do? Then wait.
+                         */
+                        if (!needToRead) {
+                            wait(threadDelay);
+                        }
+                    } catch (InterruptedException e) {
+                        /* IGNORED */
+                    }
+
+                    needToRead = this.threadIsReading;
+                    if (!needToRead) {
+                        return;
+                    }
+                }
+
+                /*
+                 * We're not shutting down, but we need to read. This cannot
+                 * happen while we are holding the lock (which we aren't now).
+                 */
+                int charRead = READ_EXPIRED;
+                IOException failure = null;
+                try {
+                    charRead = in.read();
+//                    if (charRead < 0) {
+//                        continue;
+//                    }
+                } catch (IOException e) {
+                    failure = e;
+//                    charRead = -1;
+                }
+
+                /*
+                 * Re-grab the lock to update the state.
+                 */
+                synchronized (this) {
+                    exception = failure;
+                    ch = charRead;
+                    threadIsReading = false;
+                    notify();
+                }
+            }
+        } catch (Throwable t) {
+            Log.warn("Error in NonBlockingReader thread", t);
+        } finally {
+            Log.debug("NonBlockingReader shutdown");
+            synchronized (this) {
+                thread = null;
+                threadIsReading = false;
+            }
+        }
+    }
+
+    public synchronized void clear() throws IOException {
+        while (ready()) {
+            read();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.File;
+
+public class OSUtils {
+
+    public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
+
+    public static final boolean IS_CYGWIN = IS_WINDOWS
+            && System.getenv("PWD") != null
+            && System.getenv("PWD").startsWith("/");
+
+    @Deprecated
+    public static final boolean IS_MINGW = IS_WINDOWS
+            && System.getenv("MSYSTEM") != null
+            && System.getenv("MSYSTEM").startsWith("MINGW");
+
+    public static final boolean IS_MSYSTEM = IS_WINDOWS
+            && System.getenv("MSYSTEM") != null
+            && (System.getenv("MSYSTEM").startsWith("MINGW")
+                || System.getenv("MSYSTEM").equals("MSYS"));
+
+    public static final boolean IS_CONEMU = IS_WINDOWS
+            && System.getenv("ConEmuPID") != null;
+
+    public static final boolean IS_OSX = System.getProperty("os.name").toLowerCase().contains("mac");
+
+    public static String TTY_COMMAND;
+    public static String STTY_COMMAND;
+    public static String STTY_F_OPTION;
+    public static String INFOCMP_COMMAND;
+
+    static {
+        String tty;
+        String stty;
+        String sttyfopt;
+        String infocmp;
+        if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) {
+            tty = "tty.exe";
+            stty = "stty.exe";
+            sttyfopt = null;
+            infocmp = "infocmp.exe";
+            String path = System.getenv("PATH");
+            if (path != null) {
+                String[] paths = path.split(";");
+                for (String p : paths) {
+                    if (tty == null && new File(p, "tty.exe").exists()) {
+                        tty = new File(p, "tty.exe").getAbsolutePath();
+                    }
+                    if (stty == null && new File(p, "stty.exe").exists()) {
+                        stty = new File(p, "stty.exe").getAbsolutePath();
+                    }
+                    if (infocmp == null && new File(p, "infocmp.exe").exists()) {
+                        infocmp = new File(p, "infocmp.exe").getAbsolutePath();
+                    }
+                }
+            }
+        } else {
+            tty = "tty";
+            stty = "stty";
+            infocmp = "infocmp";
+            if (IS_OSX) {
+                sttyfopt = "-f";
+            }
+            else {
+                sttyfopt = "-F";
+            }
+        }
+        TTY_COMMAND = tty;
+        STTY_COMMAND = stty;
+        STTY_F_OPTION = sttyfopt;
+        INFOCMP_COMMAND = infocmp;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+public class PumpReader extends Reader {
+
+    private static final int EOF = -1;
+    private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+    // Read and write buffer are backed by the same array
+    private final CharBuffer readBuffer;
+    private final CharBuffer writeBuffer;
+
+    private final Writer writer;
+
+    private boolean closed;
+
+    public PumpReader() {
+        this(DEFAULT_BUFFER_SIZE);
+    }
+
+    public PumpReader(int bufferSize) {
+        char[] buf = new char[bufferSize];
+        this.readBuffer = CharBuffer.wrap(buf);
+        this.writeBuffer = CharBuffer.wrap(buf);
+        this.writer = new Writer(this);
+
+        // There are no bytes available to read after initialization
+        readBuffer.limit(0);
+    }
+
+    public java.io.Writer getWriter() {
+        return this.writer;
+    }
+
+    public java.io.InputStream createInputStream(Charset charset) {
+        return new InputStream(this, charset);
+    }
+
+    private boolean wait(CharBuffer buffer) throws InterruptedIOException {
+        if (closed) {
+            return false;
+        }
+
+        while (!buffer.hasRemaining()) {
+            // Wake up waiting readers/writers
+            notifyAll();
+
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                throw new InterruptedIOException();
+            }
+
+            if (closed) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Blocks until more input is available or the reader is closed.
+     *
+     * @return true if more input is available, false if the reader is closed
+     * @throws InterruptedIOException If {@link #wait()} is interrupted
+     */
+    private boolean waitForInput() throws InterruptedIOException {
+        return wait(readBuffer);
+    }
+
+    /**
+     * Blocks until there is new space available for buffering or the
+     * reader is closed.
+     *
+     * @throws InterruptedIOException If {@link #wait()} is interrupted
+     * @throws ClosedException If the reader was closed
+     */
+    private void waitForBufferSpace() throws InterruptedIOException, ClosedException {
+        if (!wait(writeBuffer)) {
+            throw new ClosedException();
+        }
+    }
+
+    private static boolean rewind(CharBuffer buffer, CharBuffer other) {
+        // Extend limit of other buffer if there is additional input/output available
+        if (buffer.position() > other.position()) {
+            other.limit(buffer.position());
+        }
+
+        // If we have reached the end of the buffer, rewind and set the new limit
+        if (buffer.position() == buffer.capacity()) {
+            buffer.rewind();
+            buffer.limit(other.position());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Attempts to find additional input by rewinding the {@link #readBuffer}.
+     * Updates the {@link #writeBuffer} to make read bytes available for buffering.
+     *
+     * @return If more input is available
+     */
+    private boolean rewindReadBuffer() {
+        return rewind(readBuffer, writeBuffer) && readBuffer.hasRemaining();
+    }
+
+    /**
+     * Attempts to find additional buffer space by rewinding the {@link #writeBuffer}.
+     * Updates the {@link #readBuffer} to make written bytes available to the reader.
+     */
+    private void rewindWriteBuffer() {
+        rewind(writeBuffer, readBuffer);
+    }
+
+    @Override
+    public synchronized boolean ready() {
+        return readBuffer.hasRemaining();
+    }
+
+    public synchronized int available() {
+        int count = readBuffer.remaining();
+        if (writeBuffer.position() < readBuffer.position()) {
+            count += writeBuffer.position();
+        }
+        return count;
+    }
+
+    @Override
+    public synchronized int read() throws IOException {
+        if (!waitForInput()) {
+            return EOF;
+        }
+
+        int b = readBuffer.get();
+        rewindReadBuffer();
+        return b;
+    }
+
+    private int copyFromBuffer(char[] cbuf, int off, int len) {
+        len = Math.min(len, readBuffer.remaining());
+        readBuffer.get(cbuf, off, len);
+        return len;
+    }
+
+    @Override
+    public synchronized int read(char[] cbuf, int off, int len) throws IOException {
+        if (len == 0) {
+            return 0;
+        }
+
+        if (!waitForInput()) {
+            return EOF;
+        }
+
+        int count = copyFromBuffer(cbuf, off, len);
+        if (rewindReadBuffer() && count < len) {
+            count += copyFromBuffer(cbuf, off + count, len - count);
+            rewindReadBuffer();
+        }
+
+        return count;
+    }
+
+    @Override
+    public int read(CharBuffer target) throws IOException {
+        if (!target.hasRemaining()) {
+            return 0;
+        }
+
+        if (!waitForInput()) {
+            return EOF;
+        }
+
+        int count = readBuffer.read(target);
+        if (rewindReadBuffer() && target.hasRemaining()) {
+            count += readBuffer.read(target);
+            rewindReadBuffer();
+        }
+
+        return count;
+    }
+
+    private void encodeBytes(CharsetEncoder encoder, ByteBuffer output) throws IOException {
+        CoderResult result = encoder.encode(readBuffer, output, false);
+        if (rewindReadBuffer() && result.isUnderflow()) {
+            encoder.encode(readBuffer, output, false);
+            rewindReadBuffer();
+        }
+    }
+
+    synchronized int readBytes(CharsetEncoder encoder, byte[] b, int off, int len) throws IOException {
+        if (!waitForInput()) {
+            return 0;
+        }
+
+        ByteBuffer output = ByteBuffer.wrap(b, off, len);
+        encodeBytes(encoder, output);
+        return output.position() - off;
+    }
+
+    synchronized void readBytes(CharsetEncoder encoder, ByteBuffer output) throws IOException {
+        if (!waitForInput()) {
+            return;
+        }
+
+        encodeBytes(encoder, output);
+    }
+
+    synchronized void write(char c) throws IOException {
+        waitForBufferSpace();
+        writeBuffer.put(c);
+        rewindWriteBuffer();
+    }
+
+    synchronized void write(char[] cbuf, int off, int len) throws IOException {
+        while (len > 0) {
+            waitForBufferSpace();
+
+            // Copy as much characters as we can
+            int count = Math.min(len, writeBuffer.remaining());
+            writeBuffer.put(cbuf, off, count);
+
+            off += count;
+            len -= count;
+
+            // Update buffer states and rewind if necessary
+            rewindWriteBuffer();
+        }
+    }
+
+    synchronized void write(String str, int off, int len) throws IOException {
+        char[] buf = writeBuffer.array();
+
+        while (len > 0) {
+            waitForBufferSpace();
+
+            // Copy as much characters as we can
+            int count = Math.min(len, writeBuffer.remaining());
+            // CharBuffer.put(String) doesn't use getChars so do it manually
+            str.getChars(off, off + count, buf, writeBuffer.position());
+            writeBuffer.position(writeBuffer.position() + count);
+
+            off += count;
+            len -= count;
+
+            // Update buffer states and rewind if necessary
+            rewindWriteBuffer();
+        }
+    }
+
+    synchronized void flush() {
+        // Avoid waking up readers when there is nothing to read
+        if (readBuffer.hasRemaining()) {
+            // Notify readers
+            notifyAll();
+        }
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        this.closed = true;
+        notifyAll();
+    }
+
+    private static class Writer extends java.io.Writer {
+
+        private final PumpReader reader;
+
+        private Writer(PumpReader reader) {
+            this.reader = reader;
+        }
+
+        @Override
+        public void write(int c) throws IOException {
+            reader.write((char) c);
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            reader.write(cbuf, off, len);
+        }
+
+        @Override
+        public void write(String str, int off, int len) throws IOException {
+            reader.write(str, off, len);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            reader.flush();
+        }
+
+        @Override
+        public void close() throws IOException {
+            reader.close();
+        }
+
+    }
+
+    private static class InputStream extends java.io.InputStream {
+
+        private final PumpReader reader;
+        private final CharsetEncoder encoder;
+
+        // To encode a character with multiple bytes (e.g. certain Unicode characters)
+        // we need enough space to encode them. Reading would fail if the read() method
+        // is used to read a single byte in these cases.
+        // Use this buffer to ensure we always have enough space to encode a character.
+        private final ByteBuffer buffer;
+
+        private InputStream(PumpReader reader, Charset charset) {
+            this.reader = reader;
+            this.encoder = charset.newEncoder()
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE)
+                    .onMalformedInput(CodingErrorAction.REPLACE);
+            this.buffer = ByteBuffer.allocate((int) Math.ceil(encoder.maxBytesPerChar()));
+
+            // No input available after initialization
+            buffer.limit(0);
+        }
+
+        @Override
+        public int available() throws IOException {
+            return (int) (reader.available() * (double) this.encoder.averageBytesPerChar()) + buffer.remaining();
+        }
+
+        @Override
+        public int read() throws IOException {
+            if (!buffer.hasRemaining() && !readUsingBuffer()) {
+                return EOF;
+            }
+
+            return buffer.get();
+        }
+
+        private boolean readUsingBuffer() throws IOException {
+            buffer.clear(); // Reset buffer
+            reader.readBytes(encoder, buffer);
+            buffer.flip();
+            return buffer.hasRemaining();
+        }
+
+        private int copyFromBuffer(byte[] b, int off, int len) {
+            len = Math.min(len, buffer.remaining());
+            buffer.get(b, off, len);
+            return len;
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (len == 0) {
+                return 0;
+            }
+
+            int read;
+            if (buffer.hasRemaining()) {
+                read = copyFromBuffer(b, off, len);
+                if (read == len) {
+                    return len;
+                }
+
+                off += read;
+                len -= read;
+            } else {
+                read = 0;
+            }
+
+            // Do we have enough space to avoid buffering?
+            if (len >= buffer.capacity()) {
+                read += reader.readBytes(this.encoder, b, off, len);
+            } else if (readUsingBuffer()) {
+                read += copyFromBuffer(b, off, len);
+            }
+
+            // Return EOF if we didn't read any bytes
+            return read == 0 ? EOF : read;
+        }
+
+        @Override
+        public void close() throws IOException {
+            reader.close();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Manages the JLine shutdown-hook thread and tasks to execute on shutdown.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.7
+ */
+public final class ShutdownHooks
+{
+    private static final List<Task> tasks = new ArrayList<>();
+
+    private static Thread hook;
+
+    public static synchronized <T extends Task> T add(final T task) {
+        Objects.requireNonNull(task);
+
+        // Install the hook thread if needed
+        if (hook == null) {
+            hook = addHook(new Thread("JLine Shutdown Hook")
+            {
+                @Override
+                public void run() {
+                    runTasks();
+                }
+            });
+        }
+
+        // Track the task
+        Log.debug("Adding shutdown-hook task: ", task);
+        tasks.add(task);
+
+        return task;
+    }
+
+    private static synchronized void runTasks() {
+        Log.debug("Running all shutdown-hook tasks");
+
+        // Iterate through copy of tasks list
+        for (Task task : tasks.toArray(new Task[tasks.size()])) {
+            Log.debug("Running task: ", task);
+            try {
+                task.run();
+            }
+            catch (Throwable e) {
+                Log.warn("Task failed", e);
+            }
+        }
+
+        tasks.clear();
+    }
+
+    private static Thread addHook(final Thread thread) {
+        Log.debug("Registering shutdown-hook: ", thread);
+        Runtime.getRuntime().addShutdownHook(thread);
+        return thread;
+    }
+
+    public static synchronized void remove(final Task task) {
+        Objects.requireNonNull(task);
+
+        // ignore if hook never installed
+        if (hook == null) {
+            return;
+        }
+
+        // Drop the task
+        tasks.remove(task);
+
+        // If there are no more tasks, then remove the hook thread
+        if (tasks.isEmpty()) {
+            removeHook(hook);
+            hook = null;
+        }
+    }
+
+    private static void removeHook(final Thread thread) {
+        Log.debug("Removing shutdown-hook: ", thread);
+
+        try {
+            Runtime.getRuntime().removeShutdownHook(thread);
+        }
+        catch (IllegalStateException e) {
+            // The VM is shutting down, not a big deal; ignore
+        }
+    }
+
+    /**
+     * Essentially a {@link Runnable} which allows running to throw an exception.
+     */
+    public interface Task
+    {
+        void run() throws Exception;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.lang.reflect.Proxy;
+import java.util.Objects;
+
+/**
+ * Signals helpers.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 3.0
+ */
+public final class Signals {
+
+    private Signals() {
+    }
+
+    /**
+     *
+     * @param name the signal, CONT, STOP, etc...
+     * @param handler the callback to run
+     *
+     * @return an object that needs to be passed to the {@link #unregister(String, Object)}
+     *         method to unregister the handler
+     */
+    public static Object register(String name, Runnable handler) {
+        Objects.requireNonNull(handler);
+        return register(name, handler, handler.getClass().getClassLoader());
+    }
+
+    public static Object register(String name, final Runnable handler, ClassLoader loader) {
+        try {
+            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
+            // Implement signal handler
+            Object signalHandler = Proxy.newProxyInstance(loader,
+                    new Class<?>[]{signalHandlerClass}, (proxy, method, args) -> {
+                        // only method we are proxying is handle()
+                        if (method.getDeclaringClass() == Object.class) {
+                            if ("toString".equals(method.getName())) {
+                                return handler.toString();
+                            }
+                        } else if (method.getDeclaringClass() == signalHandlerClass) {
+                            Log.trace(() -> "Calling handler " + toString(handler) + " for signal " + name);
+                            handler.run();
+                        }
+                        return null;
+                    });
+            return doRegister(name, signalHandler);
+        } catch (Exception e) {
+            // Ignore this one too, if the above failed, the signal API is incompatible with what we're expecting
+            Log.debug("Error registering handler for signal ", name, e);
+            return null;
+        }
+    }
+
+    public static Object registerDefault(String name) {
+        try {
+            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
+            return doRegister(name, signalHandlerClass.getField("SIG_DFL").get(null));
+        } catch (Exception e) {
+            // Ignore this one too, if the above failed, the signal API is incompatible with what we're expecting
+            Log.debug("Error registering default handler for signal ", name, e);
+            return null;
+        }
+    }
+
+    public static void unregister(String name, Object previous) {
+        try {
+            // We should make sure the current signal is the one we registered
+            if (previous != null) {
+                doRegister(name, previous);
+            }
+        } catch (Exception e) {
+            // Ignore
+            Log.debug("Error unregistering handler for signal ", name, e);
+        }
+    }
+
+    private static Object doRegister(String name, Object handler) throws Exception {
+        Log.trace(() -> "Registering signal " + name + " with handler " + toString(handler));
+        if ("QUIT".equals(name) || "INFO".equals(name) && "9".equals(System.getProperty("java.specification.version"))) {
+            Log.trace(() -> "Ignoring unsupported signal " + name);
+            return null;
+        }
+        Class<?> signalClass = Class.forName("sun.misc.Signal");
+        Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
+        Object signal = signalClass.getConstructor(String.class).newInstance(name);
+        return signalClass.getMethod("handle", signalClass, signalHandlerClass)
+                .invoke(null, signal, handler);
+    }
+
+    @SuppressWarnings("")
+    private static String toString(Object handler) {
+        try {
+            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
+            if (handler == signalHandlerClass.getField("SIG_DFL").get(null)) {
+                return "SIG_DFL";
+            }
+            if (handler == signalHandlerClass.getField("SIG_IGN").get(null)) {
+                return "SIG_IGN";
+            }
+        } catch (Throwable t) {
+            // ignore
+        }
+        return handler != null ? handler.toString() : "null";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.Objects;
+import java.util.Collections;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.Terminal.Signal;
+import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
+import jdk.internal.org.jline.terminal.impl.AbstractTerminal;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
+import jdk.internal.org.jline.terminal.Size;
+
+public class Status {
+
+    protected final AbstractTerminal terminal;
+    protected final boolean supported;
+    protected List<AttributedString> oldLines = Collections.emptyList();
+    protected int rows;
+    protected int columns;
+    protected boolean force;
+
+    public static Status getStatus(Terminal terminal) {
+        return getStatus(terminal, true);
+    }
+
+    public static Status getStatus(Terminal terminal, boolean create) {
+        return terminal instanceof AbstractTerminal
+                ? ((AbstractTerminal) terminal).getStatus(create)
+                : null;
+    }
+
+
+    public Status(AbstractTerminal terminal) {
+        this.terminal = Objects.requireNonNull(terminal, "terminal can not be null");
+        this.supported = terminal.getStringCapability(Capability.change_scroll_region) != null
+            && terminal.getStringCapability(Capability.save_cursor) != null
+            && terminal.getStringCapability(Capability.restore_cursor) != null
+            && terminal.getStringCapability(Capability.cursor_address) != null;
+        if (supported) {
+            resize();
+        }
+    }
+
+    public void resize() {
+        Size size = terminal.getSize();
+        this.rows = size.getRows();
+        this.columns = size.getColumns();
+        this.force = true;
+    }
+
+    public void reset() {
+        this.force = true;
+    }
+
+    public void redraw() {
+        update(oldLines);
+    }
+
+    public void update(List<AttributedString> lines) {
+        if (lines == null) {
+            lines = Collections.emptyList();
+        }
+        if (!supported || (oldLines.equals(lines) && !force)) {
+            return;
+        }
+        int nb = lines.size() - oldLines.size();
+        if (nb > 0) {
+            for (int i = 0; i < nb; i++) {
+                terminal.puts(Capability.cursor_down);
+            }
+            for (int i = 0; i < nb; i++) {
+                terminal.puts(Capability.cursor_up);
+            }
+        }
+        terminal.puts(Capability.save_cursor);
+        terminal.puts(Capability.clr_eos);
+        for (int i = 0; i < lines.size(); i++) {
+            terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0);
+            terminal.writer().write(lines.get(i).columnSubSequence(0, columns).toAnsi(terminal));
+        }
+        terminal.puts(Capability.change_scroll_region, 0, rows - 1 - lines.size());
+        terminal.puts(Capability.restore_cursor);
+        terminal.flush();
+        oldLines = new ArrayList<>(lines);
+        force = false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.util.Locale;
+import java.util.function.Function;
+//import java.util.logging.Level;
+//import java.util.logging.Logger;
+
+import static java.util.Objects.requireNonNull;
+import static jdk.internal.org.jline.utils.AttributedStyle.*;
+
+// TODO: document style specification
+
+/**
+ * Resolves named (or source-referenced) {@link AttributedStyle}.
+ *
+ * @since 3.6
+ */
+public class StyleResolver {
+//    private static final Logger log = Logger.getLogger(StyleResolver.class.getName());
+
+    private final Function<String, String> source;
+
+    public StyleResolver(final Function<String, String> source) {
+        this.source = requireNonNull(source);
+    }
+
+    /**
+     * Returns the color identifier for the given name.
+     * <p>
+     * Bright color can be specified with: {@code !<color>} or {@code bright-<color>}.
+     * <p>
+     * Full xterm256 color can be specified with: {@code ~<color>}.
+     *
+     * @param name the name of the color
+     * @return color code, or {@code null} if unable to determine.
+     */
+    private static Integer color(String name) {
+        int flags = 0;
+        name = name.toLowerCase(Locale.US);
+
+        // extract bright flag from color name
+        if (name.charAt(0) == '!') {
+            name = name.substring(1, name.length());
+            flags = BRIGHT;
+        } else if (name.startsWith("bright-")) {
+            name = name.substring(7, name.length());
+            flags = BRIGHT;
+        } else if (name.charAt(0) == '~') {
+            try {
+                // TODO: if the palette is not the default one, should be
+                // TODO: translate into 24-bits first and let the #toAnsi() call
+                // TODO: round with the current palette ?
+                name = name.substring(1, name.length());
+                return Colors.rgbColor(name);
+            } catch (IllegalArgumentException e) {
+//                log.warning("Invalid style-color name: " + name);
+                return null;
+            }
+        }
+
+        switch (name) {
+            case "black":
+            case "k":
+                return flags + BLACK;
+
+            case "red":
+            case "r":
+                return flags + RED;
+
+            case "green":
+            case "g":
+                return flags + GREEN;
+
+            case "yellow":
+            case "y":
+                return flags + YELLOW;
+
+            case "blue":
+            case "b":
+                return flags + BLUE;
+
+            case "magenta":
+            case "m":
+                return flags + MAGENTA;
+
+            case "cyan":
+            case "c":
+                return flags + CYAN;
+
+            case "white":
+            case "w":
+                return flags + WHITE;
+        }
+
+        return null;
+    }
+
+    // TODO: could consider a small cache to reduce style calculations?
+
+    /**
+     * Resolve the given style specification.
+     * <p>
+     * If for some reason the specification is invalid, then {@link AttributedStyle#DEFAULT} will be used.
+     *
+     * @param spec the specification
+     * @return the style
+     */
+    public AttributedStyle resolve(final String spec) {
+        requireNonNull(spec);
+
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Resolve: " + spec);
+//        }
+
+        int i = spec.indexOf(":-");
+        if (i != -1) {
+            String[] parts = spec.split(":-");
+            return resolve(parts[0].trim(), parts[1].trim());
+        }
+
+        return apply(DEFAULT, spec);
+    }
+
+    /**
+     * Resolve the given style specification.
+     * <p>
+     * If this resolves to {@link AttributedStyle#DEFAULT} then given default specification is used if non-null.
+     *
+     * @param spec the specification
+     * @param defaultSpec the default specifiaction
+     * @return the style
+     */
+    public AttributedStyle resolve(final String spec, final String defaultSpec) {
+        requireNonNull(spec);
+
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest(String.format("Resolve: %s; default: %s", spec, defaultSpec));
+//        }
+
+        AttributedStyle style = apply(DEFAULT, spec);
+        if (style == DEFAULT && defaultSpec != null) {
+            style = apply(style, defaultSpec);
+        }
+        return style;
+    }
+
+    /**
+     * Apply style specification.
+     *
+     * @param style the style to apply to
+     * @param spec the specification
+     * @return the new style
+     */
+    private AttributedStyle apply(AttributedStyle style, final String spec) {
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Apply: " + spec);
+//        }
+
+        for (String item : spec.split(",")) {
+            item = item.trim();
+            if (item.isEmpty()) {
+                continue;
+            }
+
+            if (item.startsWith(".")) {
+                style = applyReference(style, item);
+            } else if (item.contains(":")) {
+                style = applyColor(style, item);
+            } else if (item.matches("[0-9]+(;[0-9]+)*")) {
+                style = applyAnsi(style, item);
+            } else {
+                style = applyNamed(style, item);
+            }
+        }
+
+        return style;
+    }
+
+    private AttributedStyle applyAnsi(final AttributedStyle style, final String spec) {
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Apply-ansi: " + spec);
+//        }
+
+        return new AttributedStringBuilder()
+                .style(style)
+                .ansiAppend("\033[" + spec + "m")
+                .style();
+    }
+
+    /**
+     * Apply source-referenced named style.
+     *
+     * @param style the style to apply to
+     * @param spec the specification
+     * @return the new style
+     */
+    private AttributedStyle applyReference(final AttributedStyle style, final String spec) {
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Apply-reference: " + spec);
+//        }
+
+        if (spec.length() == 1) {
+//            log.warning("Invalid style-reference; missing discriminator: " + spec);
+        } else {
+            String name = spec.substring(1, spec.length());
+            String resolvedSpec = source.apply(name);
+            if (resolvedSpec != null) {
+                return apply(style, resolvedSpec);
+            }
+            // null is normal if source has not be configured with named style
+        }
+
+        return style;
+    }
+
+    /**
+     * Apply default named styles.
+     *
+     * @param style the style to apply to
+     * @param name the named style
+     * @return the new style
+     */
+    private AttributedStyle applyNamed(final AttributedStyle style, final String name) {
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Apply-named: " + name);
+//        }
+
+        // TODO: consider short aliases for named styles
+
+        switch (name.toLowerCase(Locale.US)) {
+            case "default":
+                return DEFAULT;
+
+            case "bold":
+                return style.bold();
+
+            case "faint":
+                return style.faint();
+
+            case "italic":
+                return style.italic();
+
+            case "underline":
+                return style.underline();
+
+            case "blink":
+                return style.blink();
+
+            case "inverse":
+                return style.inverse();
+
+            case "inverse-neg":
+            case "inverseneg":
+                return style.inverseNeg();
+
+            case "conceal":
+                return style.conceal();
+
+            case "crossed-out":
+            case "crossedout":
+                return style.crossedOut();
+
+            case "hidden":
+                return style.hidden();
+
+            default:
+//                log.warning("Unknown style: " + name);
+                return style;
+        }
+    }
+
+    // TODO: consider simplify and always using StyleColor, for now for compat with other bits leaving syntax complexity
+
+    /**
+     * Apply color styles specification.
+     *
+     * @param style The style to apply to
+     * @param spec  Color specification: {@code <color-mode>:<color-name>}
+     * @return      The new style
+     */
+    private AttributedStyle applyColor(final AttributedStyle style, final String spec) {
+//        if (log.isLoggable(Level.FINEST)) {
+//            log.finest("Apply-color: " + spec);
+//        }
+
+        // extract color-mode:color-name
+        String[] parts = spec.split(":", 2);
+        String colorMode = parts[0].trim();
+        String colorName = parts[1].trim();
+
+        // resolve the color-name
+        Integer color = color(colorName);
+        if (color == null) {
+//            log.warning("Invalid color-name: " + colorName);
+        } else {
+            // resolve and apply color-mode
+            switch (colorMode.toLowerCase(Locale.US)) {
+                case "foreground":
+                case "fg":
+                case "f":
+                    return style.foreground(color);
+
+                case "background":
+                case "bg":
+                case "b":
+                    return style.background(color);
+
+                default:
+//                    log.warning("Invalid color-mode: " + colorMode);
+            }
+        }
+        return style;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+public final class WCWidth {
+
+    private WCWidth() {
+    }
+
+    /* The following two functions define the column width of an ISO 10646
+     * character as follows:
+     *
+     *    - The null character (U+0000) has a column width of 0.
+     *
+     *    - Other C0/C1 control characters and DEL will lead to a return
+     *      value of -1.
+     *
+     *    - Non-spacing and enclosing combining characters (general
+     *      category code Mn or Me in the Unicode database) have a
+     *      column width of 0.
+     *
+     *    - SOFT HYPHEN (U+00AD) has a column width of 1.
+     *
+     *    - Other format characters (general category code Cf in the Unicode
+     *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+     *
+     *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+     *      have a column width of 0.
+     *
+     *    - Spacing characters in the East Asian Wide (W) or East Asian
+     *      Full-width (F) category as defined in Unicode Technical
+     *      Report #11 have a column width of 2.
+     *
+     *    - All remaining characters (including all printable
+     *      ISO 8859-1 and WGL4 characters, Unicode control characters,
+     *      etc.) have a column width of 1.
+     *
+     * This implementation assumes that wchar_t characters are encoded
+     * in ISO 10646.
+     */
+    public static int wcwidth(int ucs)
+    {
+
+        /* test for 8-bit control characters */
+        if (ucs == 0)
+            return 0;
+        if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+            return -1;
+
+        /* binary search in table of non-spacing characters */
+        if (bisearch(ucs, combining, combining.length - 1))
+            return 0;
+
+        /* if we arrive here, ucs is not a combining or C0/C1 control character */
+        return 1 +
+                ((ucs >= 0x1100 &&
+                        (ucs <= 0x115f ||                           /* Hangul Jamo init. consonants */
+                                ucs == 0x2329 || ucs == 0x232a ||
+                                (ucs >= 0x2e80 && ucs <= 0xa4cf &&
+                                        ucs != 0x303f) ||           /* CJK ... Yi */
+                                (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+                                (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+                                (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
+                                (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+                                (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
+                                (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+                                (ucs >= 0x20000 && ucs <= 0x2fffd) ||
+                                (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0);
+    }
+
+    /* sorted list of non-overlapping intervals of non-spacing characters */
+    /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
+    static Interval[] combining = {
+            new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ),
+            new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ),
+            new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ),
+            new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ),
+            new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ),
+            new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ),
+            new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ),
+            new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ),
+            new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ),
+            new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ),
+            new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ),
+            new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ),
+            new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ),
+            new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ),
+            new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ),
+            new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ),
+            new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ),
+            new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ),
+            new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ),
+            new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ),
+            new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ),
+            new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ),
+            new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ),
+            new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ),
+            new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ),
+            new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ),
+            new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ),
+            new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ),
+            new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ),
+            new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ),
+            new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ),
+            new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ),
+            new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ),
+            new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ),
+            new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ),
+            new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ),
+            new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ),
+            new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ),
+            new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ),
+            new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ),
+            new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ),
+            new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ),
+            new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ),
+            new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ),
+            new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ),
+            new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ),
+            new Interval( 0x1D242, 0x1D244 ), new Interval( 0xE0001, 0xE0001 ), new Interval( 0xE0020, 0xE007F ),
+            new Interval( 0xE0100, 0xE01EF )
+    };
+
+    private static class Interval {
+        public final int first;
+        public final int last;
+
+        public Interval(int first, int last) {
+            this.first = first;
+            this.last = last;
+        }
+    }
+
+    /* auxiliary function for binary search in interval table */
+    private static boolean bisearch(int ucs, Interval[] table, int max) {
+        int min = 0;
+        int mid;
+
+        if (ucs < table[0].first || ucs > table[max].last)
+            return false;
+        while (max >= min) {
+            mid = (min + max) / 2;
+            if (ucs > table[mid].last)
+                min = mid + 1;
+            else if (ucs < table[mid].first)
+                max = mid - 1;
+            else
+                return true;
+        }
+
+        return false;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.utils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * Redirects an {@link OutputStream} to a {@link Writer} by decoding the data
+ * using the specified {@link Charset}.
+ *
+ * <p><b>Note:</b> This class should only be used if it is necessary to
+ * redirect an {@link OutputStream} to a {@link Writer} for compatibility
+ * purposes. It is much more efficient to write to the {@link Writer}
+ * directly.</p>
+ */
+public class WriterOutputStream extends OutputStream {
+
+    private final Writer out;
+    private final CharsetDecoder decoder;
+    private final ByteBuffer decoderIn = ByteBuffer.allocate(256);
+    private final CharBuffer decoderOut = CharBuffer.allocate(128);
+
+    public WriterOutputStream(Writer out, Charset charset) {
+        this(out, charset.newDecoder()
+                .onMalformedInput(CodingErrorAction.REPLACE)
+                .onUnmappableCharacter(CodingErrorAction.REPLACE));
+    }
+
+    public WriterOutputStream(Writer out, CharsetDecoder decoder) {
+        this.out = out;
+        this.decoder = decoder;
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        write(new byte[] { (byte)b }, 0, 1);
+    }
+
+    @Override
+    public void write(byte[] b) throws IOException {
+        write(b, 0, b.length);
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        while (len > 0) {
+            final int c = Math.min(len, decoderIn.remaining());
+            decoderIn.put(b, off, c);
+            processInput(false);
+            len -= c;
+            off += c;
+        }
+        flush();
+    }
+
+    @Override
+    public void flush() throws IOException {
+        flushOutput();
+        out.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        processInput(true);
+        flush();
+        out.close();
+    }
+
+    /**
+     * Decode the contents of the input ByteBuffer into a CharBuffer.
+     *
+     * @param endOfInput indicates end of input
+     * @throws IOException if an I/O error occurs
+     */
+    private void processInput(final boolean endOfInput) throws IOException {
+        // Prepare decoderIn for reading
+        decoderIn.flip();
+        CoderResult coderResult;
+        while (true) {
+            coderResult = decoder.decode(decoderIn, decoderOut, endOfInput);
+            if (coderResult.isOverflow()) {
+                flushOutput();
+            } else if (coderResult.isUnderflow()) {
+                break;
+            } else {
+                // The decoder is configured to replace malformed input and unmappable characters,
+                // so we should not get here.
+                throw new IOException("Unexpected coder result");
+            }
+        }
+        // Discard the bytes that have been read
+        decoderIn.compact();
+    }
+
+    /**
+     * Flush the output.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    private void flushOutput() throws IOException {
+        if (decoderOut.position() > 0) {
+            out.write(decoderOut.array(), 0, decoderOut.position());
+            decoderOut.rewind();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ansi.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,23 @@
+#	Reconstructed via infocmp from file: /usr/share/terminfo/61/ansi
+ansi|ansi/pc-term compatible with color,
+	am, mc5i, mir, msgr,
+	colors#8, cols#80, it#8, lines#24, ncv#3, pairs#64,
+	acsc=+\020\,\021-\030.^Y0\333`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
+	cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
+	cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
+	cuu=\E[%p1%dA, cuu1=\E[A, dch=\E[%p1%dP, dch1=\E[P,
+	dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K,
+	el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG, ht=\E[I, hts=\EH,
+	ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, ind=^J,
+	indn=\E[%p1%dS, invis=\E[8m, kbs=^H, kcbt=\E[Z, kcub1=\E[D,
+	kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A, khome=\E[H, kich1=\E[L,
+	mc4=\E[4i, mc5=\E[5i, nel=\r\E[S, op=\E[39;49m,
+	rep=%p1%c\E[%p2%{1}%-%db, rev=\E[7m, rin=\E[%p1%dT,
+	rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
+	s0ds=\E(B, s1ds=\E)B, s2ds=\E*B, s3ds=\E+B,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
+	sgr0=\E[0;10m, smacs=\E[11m, smpch=\E[11m, smso=\E[7m,
+	smul=\E[4m, tbc=\E[2g, u6=\E[%i%d;%dR, u7=\E[6n,
+	u8=\E[?%[;0123456789]c, u9=\E[c, vpa=\E[%i%p1%dd,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/capabilities.txt	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,473 @@
+#
+# Copyright (c) 2002-2016, the original author or authors.
+#
+# This software is distributable under the BSD license. See the terms of the
+# BSD license in the documentation provided with this software.
+#
+# http://www.opensource.org/licenses/bsd-license.php
+#
+
+auto_left_margin, bw, bw
+auto_right_margin, am, am
+back_color_erase, bce, ut
+can_change, ccc, cc
+ceol_standout_glitch, xhp, xs
+col_addr_glitch, xhpa, YA
+cpi_changes_res, cpix, YF
+cr_cancels_micro_mode, crxm, YB
+dest_tabs_magic_smso, xt, xt
+eat_newline_glitch, xenl, xn
+erase_overstrike, eo, eo
+generic_type, gn, gn
+hard_copy, hc, hc
+hard_cursor, chts, HC
+has_meta_key, km, km
+has_print_wheel, daisy, YC
+has_status_line, hs, hs
+hue_lightness_saturation, hls, hl
+insert_null_glitch, in, in
+lpi_changes_res, lpix, YG
+memory_above, da, da
+memory_below, db, db
+move_insert_mode, mir, mi
+move_standout_mode, msgr, ms
+needs_xon_xoff, nxon, nx
+no_esc_ctlc, xsb, xb
+no_pad_char, npc, NP
+non_dest_scroll_region, ndscr, ND
+non_rev_rmcup, nrrmc, NR
+over_strike, os, os
+prtr_silent, mc5i, 5i
+row_addr_glitch, xvpa, YD
+semi_auto_right_margin, sam, YE
+status_line_esc_ok, eslok, es
+tilde_glitch, hz, hz
+transparent_underline, ul, ul
+xon_xoff, xon, xo
+columns, cols, co
+init_tabs, it, it
+label_height, lh, lh
+label_width, lw, lw
+lines, lines, li
+lines_of_memory, lm, lm
+magic_cookie_glitch, xmc, sg
+max_attributes, ma, ma
+max_colors, colors, Co
+max_pairs, pairs, pa
+maximum_windows, wnum, MW
+no_color_video, ncv, NC
+num_labels, nlab, Nl
+padding_baud_rate, pb, pb
+virtual_terminal, vt, vt
+width_status_line, wsl, ws
+bit_image_entwining, bitwin, Yo
+bit_image_type, bitype, Yp
+buffer_capacity, bufsz, Ya
+buttons, btns, BT
+dot_horz_spacing, spinh, Yc
+dot_vert_spacing, spinv, Yb
+max_micro_address, maddr, Yd
+max_micro_jump, mjump, Ye
+micro_col_size, mcs, Yf
+micro_line_size, mls, Yg
+number_of_pins, npins, Yh
+output_res_char, orc, Yi
+output_res_horz_inch, orhi, Yk
+output_res_line, orl, Yj
+output_res_vert_inch, orvi, Yl
+print_rate, cps, Ym
+wide_char_size, widcs, Yn
+acs_chars, acsc, ac
+back_tab, cbt, bt
+bell, bel, bl
+carriage_return, cr, cr
+change_char_pitch, cpi, ZA
+change_line_pitch, lpi, ZB
+change_res_horz, chr, ZC
+change_res_vert, cvr, ZD
+change_scroll_region, csr, cs
+char_padding, rmp, rP
+clear_all_tabs, tbc, ct
+clear_margins, mgc, MC
+clear_screen, clear, cl
+clr_bol, el1, cb
+clr_eol, el, ce
+clr_eos, ed, cd
+column_address, hpa, ch
+command_character, cmdch, CC
+create_window, cwin, CW
+cursor_address, cup, cm
+cursor_down, cud1, do
+cursor_home, home, ho
+cursor_invisible, civis, vi
+cursor_left, cub1, le
+cursor_mem_address, mrcup, CM
+cursor_normal, cnorm, ve
+cursor_right, cuf1, nd
+cursor_to_ll, ll, ll
+cursor_up, cuu1, up
+cursor_visible, cvvis, vs
+define_char, defc, ZE
+delete_character, dch1, dc
+delete_line, dl1, dl
+dial_phone, dial, DI
+dis_status_line, dsl, ds
+display_clock, dclk, DK
+down_half_line, hd, hd
+ena_acs, enacs, eA
+enter_alt_charset_mode, smacs, as
+enter_am_mode, smam, SA
+enter_blink_mode, blink, mb
+enter_bold_mode, bold, md
+enter_ca_mode, smcup, ti
+enter_delete_mode, smdc, dm
+enter_dim_mode, dim, mh
+enter_doublewide_mode, swidm, ZF
+enter_draft_quality, sdrfq, ZG
+enter_insert_mode, smir, im
+enter_italics_mode, sitm, ZH
+enter_leftward_mode, slm, ZI
+enter_micro_mode, smicm, ZJ
+enter_near_letter_quality, snlq, ZK
+enter_normal_quality, snrmq, ZL
+enter_protected_mode, prot, mp
+enter_reverse_mode, rev, mr
+enter_secure_mode, invis, mk
+enter_shadow_mode, sshm, ZM
+enter_standout_mode, smso, so
+enter_subscript_mode, ssubm, ZN
+enter_superscript_mode, ssupm, ZO
+enter_underline_mode, smul, us
+enter_upward_mode, sum, ZP
+enter_xon_mode, smxon, SX
+erase_chars, ech, ec
+exit_alt_charset_mode, rmacs, ae
+exit_am_mode, rmam, RA
+exit_attribute_mode, sgr0, me
+exit_ca_mode, rmcup, te
+exit_delete_mode, rmdc, ed
+exit_doublewide_mode, rwidm, ZQ
+exit_insert_mode, rmir, ei
+exit_italics_mode, ritm, ZR
+exit_leftward_mode, rlm, ZS
+exit_micro_mode, rmicm, ZT
+exit_shadow_mode, rshm, ZU
+exit_standout_mode, rmso, se
+exit_subscript_mode, rsubm, ZV
+exit_superscript_mode, rsupm, ZW
+exit_underline_mode, rmul, ue
+exit_upward_mode, rum, ZX
+exit_xon_mode, rmxon, RX
+fixed_pause, pause, PA
+flash_hook, hook, fh
+flash_screen, flash, vb
+form_feed, ff, ff
+from_status_line, fsl, fs
+goto_window, wingo, WG
+hangup, hup, HU
+init_1string, is1, i1
+init_2string, is2, is
+init_3string, is3, i3
+init_file, if, if
+init_prog, iprog, iP
+initialize_color, initc, Ic
+initialize_pair, initp, Ip
+insert_character, ich1, ic
+insert_line, il1, al
+insert_padding, ip, ip
+key_a1, ka1, K1
+key_a3, ka3, K3
+key_b2, kb2, K2
+key_backspace, kbs, kb
+key_beg, kbeg, @1
+key_btab, kcbt, kB
+key_c1, kc1, K4
+key_c3, kc3, K5
+key_cancel, kcan, @2
+key_catab, ktbc, ka
+key_clear, kclr, kC
+key_close, kclo, @3
+key_command, kcmd, @4
+key_copy, kcpy, @5
+key_create, kcrt, @6
+key_ctab, kctab, kt
+key_dc, kdch1, kD
+key_dl, kdl1, kL
+key_down, kcud1, kd
+key_eic, krmir, kM
+key_end, kend, @7
+key_enter, kent, @8
+key_eol, kel, kE
+key_eos, ked, kS
+key_exit, kext, @9
+key_f0, kf0, k0
+key_f1, kf1, k1
+key_f10, kf10, k;
+key_f11, kf11, F1
+key_f12, kf12, F2
+key_f13, kf13, F3
+key_f14, kf14, F4
+key_f15, kf15, F5
+key_f16, kf16, F6
+key_f17, kf17, F7
+key_f18, kf18, F8
+key_f19, kf19, F9
+key_f2, kf2, k2
+key_f20, kf20, FA
+key_f21, kf21, FB
+key_f22, kf22, FC
+key_f23, kf23, FD
+key_f24, kf24, FE
+key_f25, kf25, FF
+key_f26, kf26, FG
+key_f27, kf27, FH
+key_f28, kf28, FI
+key_f29, kf29, FJ
+key_f3, kf3, k3
+key_f30, kf30, FK
+key_f31, kf31, FL
+key_f32, kf32, FM
+key_f33, kf33, FN
+key_f34, kf34, FO
+key_f35, kf35, FP
+key_f36, kf36, FQ
+key_f37, kf37, FR
+key_f38, kf38, FS
+key_f39, kf39, FT
+key_f4, kf4, k4
+key_f40, kf40, FU
+key_f41, kf41, FV
+key_f42, kf42, FW
+key_f43, kf43, FX
+key_f44, kf44, FY
+key_f45, kf45, FZ
+key_f46, kf46, Fa
+key_f47, kf47, Fb
+key_f48, kf48, Fc
+key_f49, kf49, Fd
+key_f5, kf5, k5
+key_f50, kf50, Fe
+key_f51, kf51, Ff
+key_f52, kf52, Fg
+key_f53, kf53, Fh
+key_f54, kf54, Fi
+key_f55, kf55, Fj
+key_f56, kf56, Fk
+key_f57, kf57, Fl
+key_f58, kf58, Fm
+key_f59, kf59, Fn
+key_f6, kf6, k6
+key_f60, kf60, Fo
+key_f61, kf61, Fp
+key_f62, kf62, Fq
+key_f63, kf63, Fr
+key_f7, kf7, k7
+key_f8, kf8, k8
+key_f9, kf9, k9
+key_find, kfnd, @0
+key_help, khlp, %1
+key_home, khome, kh
+key_ic, kich1, kI
+key_il, kil1, kA
+key_left, kcub1, kl
+key_ll, kll, kH
+key_mark, kmrk, %2
+key_message, kmsg, %3
+key_move, kmov, %4
+key_next, knxt, %5
+key_npage, knp, kN
+key_open, kopn, %6
+key_options, kopt, %7
+key_ppage, kpp, kP
+key_previous, kprv, %8
+key_print, kprt, %9
+key_redo, krdo, %0
+key_reference, kref, &1
+key_refresh, krfr, &2
+key_replace, krpl, &3
+key_restart, krst, &4
+key_resume, kres, &5
+key_right, kcuf1, kr
+key_save, ksav, &6
+key_sbeg, kBEG, &9
+key_scancel, kCAN, &0
+key_scommand, kCMD, *1
+key_scopy, kCPY, *2
+key_screate, kCRT, *3
+key_sdc, kDC, *4
+key_sdl, kDL, *5
+key_select, kslt, *6
+key_send, kEND, *7
+key_seol, kEOL, *8
+key_sexit, kEXT, *9
+key_sf, kind, kF
+key_sfind, kFND, *0
+key_shelp, kHLP, #1
+key_shome, kHOM, #2
+key_sic, kIC, #3
+key_sleft, kLFT, #4
+key_smessage, kMSG, %a
+key_smove, kMOV, %b
+key_snext, kNXT, %c
+key_soptions, kOPT, %d
+key_sprevious, kPRV, %e
+key_sprint, kPRT, %f
+key_sr, kri, kR
+key_sredo, kRDO, %g
+key_sreplace, kRPL, %h
+key_sright, kRIT, %i
+key_srsume, kRES, %j
+key_ssave, kSAV, !1
+key_ssuspend, kSPD, !2
+key_stab, khts, kT
+key_sundo, kUND, !3
+key_suspend, kspd, &7
+key_undo, kund, &8
+key_up, kcuu1, ku
+keypad_local, rmkx, ke
+keypad_xmit, smkx, ks
+lab_f0, lf0, l0
+lab_f1, lf1, l1
+lab_f10, lf10, la
+lab_f2, lf2, l2
+lab_f3, lf3, l3
+lab_f4, lf4, l4
+lab_f5, lf5, l5
+lab_f6, lf6, l6
+lab_f7, lf7, l7
+lab_f8, lf8, l8
+lab_f9, lf9, l9
+label_format, fln, Lf
+label_off, rmln, LF
+label_on, smln, LO
+meta_off, rmm, mo
+meta_on, smm, mm
+micro_column_address, mhpa, ZY
+micro_down, mcud1, ZZ
+micro_left, mcub1, Za
+micro_right, mcuf1, Zb
+micro_row_address, mvpa, Zc
+micro_up, mcuu1, Zd
+newline, nel, nw
+order_of_pins, porder, Ze
+orig_colors, oc, oc
+orig_pair, op, op
+pad_char, pad, pc
+parm_dch, dch, DC
+parm_delete_line, dl, DL
+parm_down_cursor, cud, DO
+parm_down_micro, mcud, Zf
+parm_ich, ich, IC
+parm_index, indn, SF
+parm_insert_line, il, AL
+parm_left_cursor, cub, LE
+parm_left_micro, mcub, Zg
+parm_right_cursor, cuf, RI
+parm_right_micro, mcuf, Zh
+parm_rindex, rin, SR
+parm_up_cursor, cuu, UP
+parm_up_micro, mcuu, Zi
+pkey_key, pfkey, pk
+pkey_local, pfloc, pl
+pkey_xmit, pfx, px
+plab_norm, pln, pn
+print_screen, mc0, ps
+prtr_non, mc5p, pO
+prtr_off, mc4, pf
+prtr_on, mc5, po
+pulse, pulse, PU
+quick_dial, qdial, QD
+remove_clock, rmclk, RC
+repeat_char, rep, rp
+req_for_input, rfi, RF
+reset_1string, rs1, r1
+reset_2string, rs2, r2
+reset_3string, rs3, r3
+reset_file, rf, rf
+restore_cursor, rc, rc
+row_address, vpa, cv
+save_cursor, sc, sc
+scroll_forward, ind, sf
+scroll_reverse, ri, sr
+select_char_set, scs, Zj
+set_attributes, sgr, sa
+set_background, setb, Sb
+set_bottom_margin, smgb, Zk
+set_bottom_margin_parm, smgbp, Zl
+set_clock, sclk, SC
+set_color_pair, scp, sp
+set_foreground, setf, Sf
+set_left_margin, smgl, ML
+set_left_margin_parm, smglp, Zm
+set_right_margin, smgr, MR
+set_right_margin_parm, smgrp, Zn
+set_tab, hts, st
+set_top_margin, smgt, Zo
+set_top_margin_parm, smgtp, Zp
+set_window, wind, wi
+start_bit_image, sbim, Zq
+start_char_set_def, scsd, Zr
+stop_bit_image, rbim, Zs
+stop_char_set_def, rcsd, Zt
+subscript_characters, subcs, Zu
+superscript_characters, supcs, Zv
+tab, ht, ta
+these_cause_cr, docr, Zw
+to_status_line, tsl, ts
+tone, tone, TO
+underline_char, uc, uc
+up_half_line, hu, hu
+user0, u0, u0
+user1, u1, u1
+user2, u2, u2
+user3, u3, u3
+user4, u4, u4
+user5, u5, u5
+user6, u6, u6
+user7, u7, u7
+user8, u8, u8
+user9, u9, u9
+wait_tone, wait, WA
+xoff_character, xoffc, XF
+xon_character, xonc, XN
+zero_motion, zerom, Zx
+alt_scancode_esc, scesa, S8
+bit_image_carriage_return, bicr, Yv
+bit_image_newline, binel, Zz
+bit_image_repeat, birep, Xy
+char_set_names, csnm, Zy
+code_set_init, csin, ci
+color_names, colornm, Yw
+define_bit_image_region, defbi, Yx
+device_type, devt, dv
+display_pc_char, dispc, S1
+end_bit_image_region, endbi, Yy
+enter_pc_charset_mode, smpch, S2
+enter_scancode_mode, smsc, S4
+exit_pc_charset_mode, rmpch, S3
+exit_scancode_mode, rmsc, S5
+get_mouse, getm, Gm
+key_mouse, kmous, Km
+mouse_info, minfo, Mi
+pc_term_options, pctrm, S6
+pkey_plab, pfxl, xl
+req_mouse_pos, reqmp, RQ
+scancode_escape, scesc, S7
+set0_des_seq, s0ds, s0
+set1_des_seq, s1ds, s1
+set2_des_seq, s2ds, s2
+set3_des_seq, s3ds, s3
+set_a_background, setab, AB
+set_a_foreground, setaf, AF
+set_color_band, setcolor, Yz
+set_lr_margin, smglr, ML
+set_page_length, slines, YZ
+set_tb_margin, smgtb, MT
+enter_horizontal_hl_mode, ehhlm, Xh
+enter_left_hl_mode, elhlm, Xl
+enter_low_hl_mode, elohlm, Xo
+enter_right_hl_mode, erhlm, Xr
+enter_top_hl_mode, ethlm, Xt
+enter_vertical_hl_mode, evhlm, Xv
+set_a_attributes, sgr1, sA
+set_pglen_inch, slength, sL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/colors.txt	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,265 @@
+#
+# Copyright (c) 2002-2018, the original author or authors.
+#
+# This software is distributable under the BSD license. See the terms of the
+# BSD license in the documentation provided with this software.
+#
+# http://www.opensource.org/licenses/bsd-license.php
+#
+
+black
+maroon
+green
+olive
+navy
+purple
+teal
+silver
+grey
+red
+lime
+yellow
+blue
+fuchsia
+aqua
+white
+grey0
+navyblue
+darkblue
+blue3
+blue3a
+blue1
+darkgreen
+deepskyblue4
+deepskyblue4a
+deepskyblue4b
+dodgerblue3
+dodgerblue2
+green4
+springgreen4
+turquoise4
+deepskyblue3
+deepskyblue3a
+dodgerblue1
+green3
+springgreen3
+darkcyan
+lightseagreen
+deepskyblue2
+deepskyblue1
+green3a
+springgreen3a
+springgreen2
+cyan3
+darkturquoise
+turquoise2
+green1
+springgreen2a
+springgreen1
+mediumspringgreen
+cyan2
+cyan1
+darkred
+deeppink4
+purple4
+purple4a
+purple3
+blueviolet
+orange4
+grey37
+mediumpurple4
+slateblue3
+slateblue3a
+royalblue1
+chartreuse4
+darkseagreen4
+paleturquoise4
+steelblue
+steelblue3
+cornflowerblue
+chartreuse3
+darkseagreen4a
+cadetblue
+cadetbluea
+skyblue3
+steelblue1
+chartreuse3a
+palegreen3
+seagreen3
+aquamarine3
+mediumturquoise
+steelblue1a
+chartreuse2
+seagreen2
+seagreen1
+seagreen1a
+aquamarine1
+darkslategray2
+darkreda
+deeppink4a
+darkmagenta
+darkmagentaa
+darkviolet
+purplea
+orange4a
+lightpink4
+plum4
+mediumpurple3
+mediumpurple3a
+slateblue1
+yellow4
+wheat4
+grey53
+lightslategrey
+mediumpurple
+lightslateblue
+yellow4a
+darkolivegreen3
+darkseagreen
+lightskyblue3
+lightskyblue3a
+skyblue2
+chartreuse2a
+darkolivegreen3a
+palegreen3a
+darkseagreen3
+darkslategray3
+skyblue1
+chartreuse1
+lightgreen
+lightgreena
+palegreen1
+aquamarine1a
+darkslategray1
+red3
+deeppink4b
+mediumvioletred
+magenta3
+darkvioleta
+purpleb
+darkorange3
+indianred
+hotpink3
+mediumorchid3
+mediumorchid
+mediumpurple2
+darkgoldenrod
+lightsalmon3
+rosybrown
+grey63
+mediumpurple2a
+mediumpurple1
+gold3
+darkkhaki
+navajowhite3
+grey69
+lightsteelblue3
+lightsteelblue
+yellow3
+darkolivegreen3b
+darkseagreen3a
+darkseagreen2
+lightcyan3
+lightskyblue1
+greenyellow
+darkolivegreen2
+palegreen1a
+darkseagreen2a
+darkseagreen1
+paleturquoise1
+red3a
+deeppink3
+deeppink3a
+magenta3a
+magenta3b
+magenta2
+darkorange3a
+indianreda
+hotpink3a
+hotpink2
+orchid
+mediumorchid1
+orange3
+lightsalmon3a
+lightpink3
+pink3
+plum3
+violet
+gold3a
+lightgoldenrod3
+tan
+mistyrose3
+thistle3
+plum2
+yellow3a
+khaki3
+lightgoldenrod2
+lightyellow3
+grey84
+lightsteelblue1
+yellow2
+darkolivegreen1
+darkolivegreen1a
+darkseagreen1a
+honeydew2
+lightcyan1
+red1
+deeppink2
+deeppink1
+deeppink1a
+magenta2a
+magenta1
+orangered1
+indianred1
+indianred1a
+hotpink
+hotpinka
+mediumorchid1a
+darkorange
+salmon1
+lightcoral
+palevioletred1
+orchid2
+orchid1
+orange1
+sandybrown
+lightsalmon1
+lightpink1
+pink1
+plum1
+gold1
+lightgoldenrod2a
+lightgoldenrod2b
+navajowhite1
+mistyrose1
+thistle1
+yellow1
+lightgoldenrod1
+khaki1
+wheat1
+cornsilk1
+grey100
+grey3
+grey7
+grey11
+grey15
+grey19
+grey23
+grey27
+grey30
+grey35
+grey39
+grey42
+grey46
+grey50
+grey54
+grey58
+grey62
+grey66
+grey70
+grey74
+grey78
+grey82
+grey85
+grey89
+grey93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/dumb.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,5 @@
+#      Reconstructed via infocmp from file: /usr/share/terminfo/64/dumb
+dumb|80-column dumb tty,
+        am,
+        cols#80,
+        bel=^G, cr=^M, cud1=^J, ind=^J,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/package-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 3.
+ *
+ * @since 3.0
+ */
+package jdk.internal.org.jline.utils;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/screen-256color.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,27 @@
+#	Reconstructed via infocmp from file: /usr/share/terminfo/73/screen-256color
+screen-256color|GNU Screen with 256 colors,
+	am, km, mir, msgr, xenl,
+	colors#256, cols#80, it#8, lines#24, ncv#3, pairs#32767,
+	acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
+	clear=\E[H\E[J, cnorm=\E[34h\E[?25h, cr=^M,
+	csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
+	cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
+	cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\EM,
+	cvvis=\E[34l, dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM,
+	dl1=\E[M, ed=\E[J, el=\E[K, el1=\E[1K, enacs=\E(B\E)0,
+	flash=\Eg, home=\E[H, ht=^I, hts=\EH, ich=\E[%p1%d@,
+	il=\E[%p1%dL, il1=\E[L, ind=^J, initc@, is2=\E)0, kbs=^H,
+	kcbt=\E[Z, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	kdch1=\E[3~, kend=\E[4~, kf1=\EOP, kf10=\E[21~,
+	kf11=\E[23~, kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS,
+	kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~,
+	khome=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
+	nel=\EE, op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM, rmacs=^O,
+	rmcup=\E[?1049l, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[23m,
+	rmul=\E[24m, rs2=\Ec\E[?1000l\E[?25h, sc=\E7,
+	setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
+	setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
+	sgr=\E[0%?%p6%t;1%;%?%p1%t;3%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;,
+	sgr0=\E[m\017, smacs=^N, smcup=\E[?1049h, smir=\E[4h,
+	smkx=\E[?1h\E=, smso=\E[3m, smul=\E[4m, tbc=\E[3g,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/screen.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,26 @@
+#	Reconstructed via infocmp from file: /usr/share/terminfo/73/screen
+screen|VT 100/ANSI X3.64 virtual terminal,
+	am, km, mir, msgr, xenl,
+	colors#8, cols#80, it#8, lines#24, ncv#3, pairs#64,
+	acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
+	clear=\E[H\E[J, cnorm=\E[34h\E[?25h, cr=^M,
+	csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
+	cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
+	cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\EM,
+	cvvis=\E[34l, dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM,
+	dl1=\E[M, ed=\E[J, el=\E[K, el1=\E[1K, enacs=\E(B\E)0,
+	flash=\Eg, home=\E[H, ht=^I, hts=\EH, ich=\E[%p1%d@,
+	il=\E[%p1%dL, il1=\E[L, ind=^J, is2=\E)0, kbs=^H, kcbt=\E[Z,
+	kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	kdch1=\E[3~, kend=\E[4~, kf1=\EOP, kf10=\E[21~,
+	kf11=\E[23~, kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS,
+	kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~,
+	khome=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
+	nel=\EE, op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM, rmacs=^O,
+	rmcup=\E[?1049l, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[23m,
+	rmul=\E[24m, rs2=\Ec\E[?1000l\E[?25h, sc=\E7,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	sgr=\E[0%?%p6%t;1%;%?%p1%t;3%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;,
+	sgr0=\E[m\017, smacs=^N, smcup=\E[?1049h, smir=\E[4h,
+	smkx=\E[?1h\E=, smso=\E[3m, smul=\E[4m, tbc=\E[3g,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-256color.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,27 @@
+windows-256color|windows with 256 colors terminal compatibility,
+	am, mc5i, mir, msgr,
+	colors#256, cols#80, it#8, lines#24, ncv#3, pairs#64,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
+	cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
+	cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
+	cuu=\E[%p1%dA, cuu1=\E[A,
+	il=\E[%p1%dL, il1=\E[L,
+	dl=\E[%p1%dM, dl1=\E[M,
+	ech=\E[%p1%dX,
+	el=\E[K, ed=\E[2K,
+	el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG,
+	ind=^J,
+	invis=\E[8m, kbs=^H, kcbt=\E[Z,
+	kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	khome=\E[H,
+	op=\E[39;49m,
+	rev=\E[7m,
+	rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
+	sgr0=\E[0;10m,
+	smso=\E[7m,
+	smul=\E[4m,
+	kdch1=\E[3~, kich1=\E[2~, kend=\E[4~, knp=\E[6~, kpp=\E[5~,
+	kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~,
+	kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-vtp.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,33 @@
+windows-vtp|windows with virtual terminal processing,
+	am, mc5i, mir, msgr,
+	colors#256, cols#80, it#8, lines#24, ncv#3, pairs#64,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
+	cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
+	cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
+	cuu=\E[%p1%dA, cuu1=\E[A,
+	il=\E[%p1%dL, il1=\E[L,
+	dl=\E[%p1%dM, dl1=\E[M,
+	ech=\E[%p1%dX,
+	el=\E[K, ed=\E[2K,
+	el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG,
+	ind=^J,
+	invis=\E[8m, kbs=^H, kcbt=\E[Z,
+	kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	khome=\E[H,
+	op=\E[39;49m,
+	rev=\E[7m,
+	rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
+	sgr0=\E[0;10m,
+	smso=\E[7m,
+	smul=\E[4m,
+	kdch1=\E[3~, kich1=\E[2~, kend=\E[4~, knp=\E[6~, kpp=\E[5~,
+	kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~,
+	kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
+	smcup=\E[?1049h, rmcup=\E[?1049l, indn=\E[%p1%dS, rin=\E[%p1%dT,
+	ich=\E[%p1%d@, dch=\E[%p1%dP, ech=\E[%p1%dX, il=\E[%p1%dL, dl=\E[%p1%dM,
+	sc=\E7, rc=\E8, cnorm=\E[?12l\E[?25h, civis=\E[?25l, cvvis=\E[?12h\E[?25h,
+	smkx=\E[?1h\E=, rmkx=\E[?1l\E>, u6=\E[%i%d;%dR, u7=\E[6n,
+	hts=\EH, smacs=\E(0, rmacs=\E(B,
+	csr=\E[%i%p1%d;%p2%dr,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,27 @@
+windows|windows terminal compatibility,
+	am, mc5i, mir, msgr,
+	colors#16, cols#80, it#8, lines#24, ncv#3, pairs#64,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
+	cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
+	cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
+	cuu=\E[%p1%dA, cuu1=\E[A,
+	il=\E[%p1%dL, il1=\E[L,
+	dl=\E[%p1%dM, dl1=\E[M,
+	ech=\E[%p1%dX,
+	el=\E[K, ed=\E[2K,
+	el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG,
+	ind=^J,
+	invis=\E[8m, kbs=^H, kcbt=\E[Z,
+	kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	khome=\E[H,
+	op=\E[39;49m,
+	rev=\E[7m,
+	rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
+	sgr0=\E[0;10m,
+	smso=\E[7m,
+	smul=\E[4m,
+	kdch1=\E[3~, kich1=\E[2~, kend=\E[4~, knp=\E[6~, kpp=\E[5~,
+	kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~,
+	kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/xterm-256color.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,51 @@
+#	Reconstructed via infocmp from file: /usr/share/terminfo/78/xterm-256color
+xterm-256color|xterm with 256 colors,
+	am, bce, ccc, km, mc5i, mir, msgr, npc, xenl,
+	colors#256, cols#80, it#8, lines#24, pairs#32767,
+	acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
+	clear=\E[H\E[2J, cnorm=\E[?12l\E[?25h, cr=^M,
+	csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
+	cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
+	cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
+	cvvis=\E[?12;25h, dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM,
+	dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K, el1=\E[1K,
+	flash=\E[?5h$<100/>\E[?5l, home=\E[H, hpa=\E[%i%p1%dG,
+	ht=^I, hts=\EH, ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L,
+	ind=^J, indn=\E[%p1%dS,
+	initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
+	invis=\E[8m, is2=\E[!p\E[?3;4l\E[4l\E>, kDC=\E[3;2~,
+	kEND=\E[1;2F, kHOM=\E[1;2H, kIC=\E[2;2~, kLFT=\E[1;2D,
+	kNXT=\E[6;2~, kPRV=\E[5;2~, kRIT=\E[1;2C, kb2=\EOE, kbs=^H,
+	kcbt=\E[Z, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	kdch1=\E[3~, kend=\EOF, kent=\EOM, kf1=\EOP, kf10=\E[21~,
+	kf11=\E[23~, kf12=\E[24~, kf13=\E[1;2P, kf14=\E[1;2Q,
+	kf15=\E[1;2R, kf16=\E[1;2S, kf17=\E[15;2~, kf18=\E[17;2~,
+	kf19=\E[18;2~, kf2=\EOQ, kf20=\E[19;2~, kf21=\E[20;2~,
+	kf22=\E[21;2~, kf23=\E[23;2~, kf24=\E[24;2~,
+	kf25=\E[1;5P, kf26=\E[1;5Q, kf27=\E[1;5R, kf28=\E[1;5S,
+	kf29=\E[15;5~, kf3=\EOR, kf30=\E[17;5~, kf31=\E[18;5~,
+	kf32=\E[19;5~, kf33=\E[20;5~, kf34=\E[21;5~,
+	kf35=\E[23;5~, kf36=\E[24;5~, kf37=\E[1;6P, kf38=\E[1;6Q,
+	kf39=\E[1;6R, kf4=\EOS, kf40=\E[1;6S, kf41=\E[15;6~,
+	kf42=\E[17;6~, kf43=\E[18;6~, kf44=\E[19;6~,
+	kf45=\E[20;6~, kf46=\E[21;6~, kf47=\E[23;6~,
+	kf48=\E[24;6~, kf49=\E[1;3P, kf5=\E[15~, kf50=\E[1;3Q,
+	kf51=\E[1;3R, kf52=\E[1;3S, kf53=\E[15;3~, kf54=\E[17;3~,
+	kf55=\E[18;3~, kf56=\E[19;3~, kf57=\E[20;3~,
+	kf58=\E[21;3~, kf59=\E[23;3~, kf6=\E[17~, kf60=\E[24;3~,
+	kf61=\E[1;4P, kf62=\E[1;4Q, kf63=\E[1;4R, kf7=\E[18~,
+	kf8=\E[19~, kf9=\E[20~, khome=\EOH, kich1=\E[2~,
+	kind=\E[1;2B, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
+	kri=\E[1;2A, mc0=\E[i, mc4=\E[4i, mc5=\E[5i, meml=\El,
+	memu=\Em, op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM,
+	rin=\E[%p1%dT, rmacs=\E(B, rmam=\E[?7l, rmcup=\E[?1049l,
+	rmir=\E[4l, rmkx=\E[?1l\E>, rmm=\E[?1034l, rmso=\E[27m,
+	rmul=\E[24m, rs1=\Ec, rs2=\E[!p\E[?3;4l\E[4l\E>, sc=\E7,
+	setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
+	setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
+	sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
+	sgr0=\E(B\E[m, smacs=\E(0, smam=\E[?7h, smcup=\E[?1049h,
+	smir=\E[4h, smkx=\E[?1h\E=, smm=\E[?1034h, smso=\E[7m,
+	smul=\E[4m, tbc=\E[3g, u6=\E[%i%d;%dR, u7=\E[6n,
+	u8=\E[?1;2c, u9=\E[c, vpa=\E[%i%p1%dd,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/xterm.caps	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,51 @@
+#	Reconstructed via infocmp from file: /usr/share/terminfo/78/xterm
+xterm|xterm terminal emulator (X Window System),
+	am, bce, km, mc5i, mir, msgr, npc, xenl,
+	colors#8, cols#80, it#8, lines#24, pairs#64,
+	acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+	bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
+	clear=\E[H\E[2J, cnorm=\E[?12l\E[?25h, cr=^M,
+	csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
+	cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
+	cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
+	cvvis=\E[?12;25h, dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM,
+	dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K, el1=\E[1K,
+	flash=\E[?5h$<100/>\E[?5l, home=\E[H, hpa=\E[%i%p1%dG,
+	ht=^I, hts=\EH, ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L,
+	ind=^J, indn=\E[%p1%dS, invis=\E[8m,
+	is2=\E[!p\E[?3;4l\E[4l\E>, kDC=\E[3;2~, kEND=\E[1;2F,
+	kHOM=\E[1;2H, kIC=\E[2;2~, kLFT=\E[1;2D, kNXT=\E[6;2~,
+	kPRV=\E[5;2~, kRIT=\E[1;2C, kb2=\EOE, kbs=^H, kcbt=\E[Z,
+	kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+	kdch1=\E[3~, kend=\EOF, kent=\EOM, kf1=\EOP, kf10=\E[21~,
+	kf11=\E[23~, kf12=\E[24~, kf13=\E[1;2P, kf14=\E[1;2Q,
+	kf15=\E[1;2R, kf16=\E[1;2S, kf17=\E[15;2~, kf18=\E[17;2~,
+	kf19=\E[18;2~, kf2=\EOQ, kf20=\E[19;2~, kf21=\E[20;2~,
+	kf22=\E[21;2~, kf23=\E[23;2~, kf24=\E[24;2~,
+	kf25=\E[1;5P, kf26=\E[1;5Q, kf27=\E[1;5R, kf28=\E[1;5S,
+	kf29=\E[15;5~, kf3=\EOR, kf30=\E[17;5~, kf31=\E[18;5~,
+	kf32=\E[19;5~, kf33=\E[20;5~, kf34=\E[21;5~,
+	kf35=\E[23;5~, kf36=\E[24;5~, kf37=\E[1;6P, kf38=\E[1;6Q,
+	kf39=\E[1;6R, kf4=\EOS, kf40=\E[1;6S, kf41=\E[15;6~,
+	kf42=\E[17;6~, kf43=\E[18;6~, kf44=\E[19;6~,
+	kf45=\E[20;6~, kf46=\E[21;6~, kf47=\E[23;6~,
+	kf48=\E[24;6~, kf49=\E[1;3P, kf5=\E[15~, kf50=\E[1;3Q,
+	kf51=\E[1;3R, kf52=\E[1;3S, kf53=\E[15;3~, kf54=\E[17;3~,
+	kf55=\E[18;3~, kf56=\E[19;3~, kf57=\E[20;3~,
+	kf58=\E[21;3~, kf59=\E[23;3~, kf6=\E[17~, kf60=\E[24;3~,
+	kf61=\E[1;4P, kf62=\E[1;4Q, kf63=\E[1;4R, kf7=\E[18~,
+	kf8=\E[19~, kf9=\E[20~, khome=\EOH, kich1=\E[2~,
+	kind=\E[1;2B, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
+	kri=\E[1;2A, mc0=\E[i, mc4=\E[4i, mc5=\E[5i, meml=\El,
+	memu=\Em, op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM,
+	rin=\E[%p1%dT, rmacs=\E(B, rmam=\E[?7l, rmcup=\E[?1049l,
+	rmir=\E[4l, rmkx=\E[?1l\E>, rmm=\E[?1034l, rmso=\E[27m,
+	rmul=\E[24m, rs1=\Ec, rs2=\E[!p\E[?3;4l\E[4l\E>, sc=\E7,
+	setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+	setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+	setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+	sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
+	sgr0=\E(B\E[m, smacs=\E(0, smam=\E[?7h, smcup=\E[?1049h,
+	smir=\E[4h, smkx=\E[?1h\E=, smm=\E[?1034h, smso=\E[7m,
+	smul=\E[4m, tbc=\E[3g, u6=\E[%i%d;%dR, u7=\E[6n,
+	u8=\E[?1;2c, u9=\E[c, vpa=\E[%i%p1%dd,
--- a/src/jdk.internal.le/share/classes/module-info.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.le/share/classes/module-info.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -29,23 +29,35 @@
  * @since 9
  */
 module jdk.internal.le {
-    exports jdk.internal.jline to
+    exports jdk.internal.org.jline.keymap to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.org.jline.reader to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
-    exports jdk.internal.jline.console to
+    exports jdk.internal.org.jline.reader.impl to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
-    exports jdk.internal.jline.console.completer to
+    exports jdk.internal.org.jline.reader.impl.completer to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.org.jline.reader.impl.history to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
-    exports jdk.internal.jline.console.history to
+    exports jdk.internal.org.jline.terminal.impl to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
-    exports jdk.internal.jline.extra to
+    exports jdk.internal.org.jline.terminal to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.org.jline.utils to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
-    exports jdk.internal.jline.internal to
+    exports jdk.internal.org.jline.terminal.spi to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
+
+    uses jdk.internal.org.jline.terminal.spi.JnaSupport;
+
 }
 
--- a/src/jdk.internal.le/share/legal/jline.md	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.le/share/legal/jline.md	Wed Dec 12 08:38:45 2018 -0500
@@ -1,12 +1,12 @@
-## JLine v2.14.6
+## JLine v3.9.0
 
 ### JLine License
 <pre>
 
-Copyright (c) 2002-2016, the original author or authors.
+Copyright (c) 2002-2018, the original author or authors.
 All rights reserved.
 
-http://www.opensource.org/licenses/bsd-license.php
+https://opensource.org/licenses/BSD-3-Clause
 
 Redistribution and use in source and binary forms, with or
 without modification, are permitted provided that the following
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,42 @@
+package jdk.internal.org.jline.terminal.impl.jna;
+
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
+import jdk.internal.org.jline.terminal.spi.JnaSupport;
+import jdk.internal.org.jline.terminal.spi.Pty;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.function.Function;
+
+public class JnaSupportImpl implements JnaSupport {
+    @Override
+    public Pty current() throws IOException {
+//        return JnaNativePty.current();
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Pty open(Attributes attributes, Size size) throws IOException {
+//        return JnaNativePty.open(attributes, size);
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException {
+        return winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, false);
+    }
+
+    @Override
+    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
+        return winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused, input -> input);
+    }
+
+    @Override
+    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
+        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused, inputStreamWrapper);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/IntByReference.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+class IntByReference {
+
+    public int value;
+
+    public int getValue() {
+        return value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002-2017, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+//import com.sun.jna.LastErrorException;
+//import com.sun.jna.Pointer;
+//import com.sun.jna.ptr.IntByReference;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
+
+import java.io.IOException;
+
+class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
+
+    private final Pointer consoleHandle;
+    private final IntByReference writtenChars = new IntByReference();
+
+    JnaWinConsoleWriter(Pointer consoleHandle) {
+        this.consoleHandle = consoleHandle;
+    }
+
+    @Override
+    protected void writeConsole(char[] text, int len) throws IOException {
+        try {
+            Kernel32.INSTANCE.WriteConsoleW(this.consoleHandle, text, len, this.writtenChars, null);
+        } catch (LastErrorException e) {
+            throw new IOException("Failed to write to console", e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.function.Function;
+import java.util.function.IntConsumer;
+
+//import com.sun.jna.LastErrorException;
+//import com.sun.jna.Pointer;
+//import com.sun.jna.ptr.IntByReference;
+
+import jdk.internal.org.jline.terminal.Cursor;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.utils.InfoCmp;
+import jdk.internal.org.jline.utils.OSUtils;
+
+public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+
+    private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
+    private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
+
+    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, boolean paused, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
+        Writer writer;
+        if (ansiPassThrough) {
+            if (type == null) {
+                type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_256_COLOR : TYPE_WINDOWS;
+            }
+            writer = new JnaWinConsoleWriter(consoleOut);
+        } else {
+            IntByReference mode = new IntByReference();
+            Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode);
+            try {
+                Kernel32.INSTANCE.SetConsoleMode(consoleOut, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+                if (type == null) {
+                    type = TYPE_WINDOWS_VTP;
+                }
+                writer = new JnaWinConsoleWriter(consoleOut);
+            } catch (LastErrorException e) {
+                if (OSUtils.IS_CONEMU) {
+                    if (type == null) {
+                        type = TYPE_WINDOWS_256_COLOR;
+                    }
+                    writer = new JnaWinConsoleWriter(consoleOut);
+                } else {
+                    if (type == null) {
+                        type = TYPE_WINDOWS;
+                    }
+                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(consoleOut)), consoleOut);
+                }
+            }
+        }
+        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, codepage, nativeSignals, signalHandler, inputStreamWrapper);
+        // Start input pump thread
+        if (!paused) {
+            terminal.resume();
+        }
+        return terminal;
+    }
+
+    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
+        super(writer, name, type, encoding, codepage, nativeSignals, signalHandler, inputStreamWrapper);
+        strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
+    }
+
+    @Override
+    protected int getConsoleOutputCP() {
+        return Kernel32.INSTANCE.GetConsoleOutputCP();
+    }
+
+    @Override
+    protected int getConsoleMode() {
+        IntByReference mode = new IntByReference();
+        Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
+        return mode.getValue();
+    }
+
+    @Override
+    protected void setConsoleMode(int mode) {
+        Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
+    }
+
+    public Size getSize() {
+        Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
+        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
+        return new Size(info.dwSize.X, info.dwSize.Y);
+    }
+
+    protected boolean processConsoleInput() throws IOException {
+        Kernel32.INPUT_RECORD event = readConsoleInput(100);
+        if (event == null) {
+            return false;
+        }
+
+        switch (event.EventType) {
+            case Kernel32.INPUT_RECORD.KEY_EVENT:
+                processKeyEvent(event.Event.KeyEvent);
+                return true;
+            case Kernel32.INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
+                raise(Signal.WINCH);
+                return false;
+            case Kernel32.INPUT_RECORD.MOUSE_EVENT:
+                processMouseEvent(event.Event.MouseEvent);
+                return true;
+            case Kernel32.INPUT_RECORD.FOCUS_EVENT:
+                processFocusEvent(event.Event.FocusEvent.bSetFocus);
+                return true;
+            default:
+                // Skip event
+                return false;
+        }
+    }
+
+    private void processKeyEvent(Kernel32.KEY_EVENT_RECORD keyEvent) throws IOException {
+        processKeyEvent(keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
+    }
+
+    private char[] focus = new char[] { '\033', '[', ' ' };
+
+    private void processFocusEvent(boolean hasFocus) throws IOException {
+        if (focusTracking) {
+            focus[2] = hasFocus ? 'I' : 'O';
+            slaveInputPipe.write(focus);
+        }
+    }
+
+    private char[] mouse = new char[] { '\033', '[', 'M', ' ', ' ', ' ' };
+
+    private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IOException {
+        int dwEventFlags = mouseEvent.dwEventFlags;
+        int dwButtonState = mouseEvent.dwButtonState;
+        if (tracking == MouseTracking.Off
+                || tracking == MouseTracking.Normal && dwEventFlags == Kernel32.MOUSE_MOVED
+                || tracking == MouseTracking.Button && dwEventFlags == Kernel32.MOUSE_MOVED && dwButtonState == 0) {
+            return;
+        }
+        int cb = 0;
+        dwEventFlags &= ~ Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
+        if (dwEventFlags == Kernel32.MOUSE_WHEELED) {
+            cb |= 64;
+            if ((dwButtonState >> 16) < 0) {
+                cb |= 1;
+            }
+        } else if (dwEventFlags == Kernel32.MOUSE_HWHEELED) {
+            return;
+        } else if ((dwButtonState & Kernel32.FROM_LEFT_1ST_BUTTON_PRESSED) != 0) {
+            cb |= 0x00;
+        } else if ((dwButtonState & Kernel32.RIGHTMOST_BUTTON_PRESSED) != 0) {
+            cb |= 0x01;
+        } else if ((dwButtonState & Kernel32.FROM_LEFT_2ND_BUTTON_PRESSED) != 0) {
+            cb |= 0x02;
+        } else {
+            cb |= 0x03;
+        }
+        int cx = mouseEvent.dwMousePosition.X;
+        int cy = mouseEvent.dwMousePosition.Y;
+        mouse[3] = (char) (' ' + cb);
+        mouse[4] = (char) (' ' + cx + 1);
+        mouse[5] = (char) (' ' + cy + 1);
+        slaveInputPipe.write(mouse);
+    }
+
+    private final Kernel32.INPUT_RECORD[] inputEvents = new Kernel32.INPUT_RECORD[1];
+    private final IntByReference eventsRead = new IntByReference();
+
+    private Kernel32.INPUT_RECORD readConsoleInput(int dwMilliseconds) throws IOException {
+        if (Kernel32.INSTANCE.WaitForSingleObject(consoleIn, dwMilliseconds) != 0) {
+            return null;
+        }
+        Kernel32.INSTANCE.ReadConsoleInput(consoleIn, inputEvents, 1, eventsRead);
+        if (eventsRead.getValue() == 1) {
+            return inputEvents[0];
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public Cursor getCursorPosition(IntConsumer discarded) {
+        Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
+        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
+        return new Cursor(info.dwCursorPosition.X, info.dwCursorPosition.Y);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,633 @@
+/*
+ * Copyright (c) 2002-2018, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+//OpenJDK changes:
+//-references to JNA types commented out
+//-replacement types provided where needed (IntByReference, LastErrorException, Pointer)
+//-methods not used by JLine commented out
+//-provided an implementation of the interface (Kernel32Impl), backed by a native implementation (Kernel32.cpp)
+
+//import com.sun.jna.LastErrorException;
+//import com.sun.jna.Native;
+//import com.sun.jna.Pointer;
+//import com.sun.jna.Structure;
+//import com.sun.jna.Union;
+//import com.sun.jna.ptr.IntByReference;
+//import com.sun.jna.win32.StdCallLibrary;
+//import com.sun.jna.win32.W32APIOptions;
+
+interface Kernel32 {//extends StdCallLibrary {
+
+    Kernel32 INSTANCE = new Kernel32Impl();
+//    Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
+
+//    Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1L);
+
+    int STD_INPUT_HANDLE =  -10;
+    int STD_OUTPUT_HANDLE = -11;
+    int STD_ERROR_HANDLE =  -12;
+
+    int ENABLE_PROCESSED_INPUT =    0x0001;
+    int ENABLE_LINE_INPUT =         0x0002;
+    int ENABLE_ECHO_INPUT =         0x0004;
+    int ENABLE_WINDOW_INPUT =       0x0008;
+    int ENABLE_MOUSE_INPUT =        0x0010;
+    int ENABLE_INSERT_MODE =        0x0020;
+    int ENABLE_QUICK_EDIT_MODE =    0x0040;
+    int ENABLE_EXTENDED_FLAGS =     0x0080;
+
+    int RIGHT_ALT_PRESSED =     0x0001;
+    int LEFT_ALT_PRESSED =      0x0002;
+    int RIGHT_CTRL_PRESSED =    0x0004;
+    int LEFT_CTRL_PRESSED =     0x0008;
+    int SHIFT_PRESSED =         0x0010;
+
+    int FOREGROUND_BLUE =       0x0001;
+    int FOREGROUND_GREEN =      0x0002;
+    int FOREGROUND_RED =        0x0004;
+    int FOREGROUND_INTENSITY =  0x0008;
+    int BACKGROUND_BLUE =       0x0010;
+    int BACKGROUND_GREEN =      0x0020;
+    int BACKGROUND_RED =        0x0040;
+    int BACKGROUND_INTENSITY =  0x0080;
+
+    // Button state
+    int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001;
+    int RIGHTMOST_BUTTON_PRESSED     = 0x0002;
+    int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004;
+    int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008;
+    int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010;
+
+    // Event flags
+    int MOUSE_MOVED                  = 0x0001;
+    int DOUBLE_CLICK                 = 0x0002;
+    int MOUSE_WHEELED                = 0x0004;
+    int MOUSE_HWHEELED               = 0x0008;
+
+    // DWORD WINAPI WaitForSingleObject(
+    //  _In_ HANDLE hHandle,
+    //  _In_ DWORD  dwMilliseconds
+    // );
+    int WaitForSingleObject(Pointer in_hHandle, int in_dwMilliseconds);
+
+    // HANDLE WINAPI GetStdHandle(
+    // __in DWORD nStdHandle
+    // );
+    Pointer GetStdHandle(int nStdHandle);
+
+//    // BOOL WINAPI AllocConsole(void);
+//    void AllocConsole() throws LastErrorException;
+//
+//    // BOOL WINAPI FreeConsole(void);
+//    void FreeConsole() throws LastErrorException;
+//
+//    // HWND WINAPI GetConsoleWindow(void);
+//    Pointer GetConsoleWindow();
+//
+//    // UINT WINAPI GetConsoleCP(void)
+//    int GetConsoleCP();
+//
+    // UINT WINAPI GetConsoleOutputCP(void)
+    int GetConsoleOutputCP();
+
+    // BOOL WINAPI FillConsoleOutputCharacter(
+    // _In_ HANDLE hConsoleOutput,
+    // _In_ TCHAR cCharacter,
+    // _In_ DWORD nLength,
+    // _In_ COORD dwWriteCoord,
+    // _Out_ LPDWORD lpNumberOfCharsWritten);
+    void FillConsoleOutputCharacter(Pointer in_hConsoleOutput,
+                                    char in_cCharacter, int in_nLength, COORD in_dwWriteCoord,
+                                    IntByReference out_lpNumberOfCharsWritten)
+            throws LastErrorException;
+
+    // BOOL WINAPI FillConsoleOutputAttribute(
+    // _In_ HANDLE hConsoleOutput,
+    // _In_ WORD wAttribute,
+    // _In_ DWORD nLength,
+    // _In_ COORD dwWriteCoord,
+    // _Out_ LPDWORD lpNumberOfAttrsWritten);
+    void FillConsoleOutputAttribute(Pointer in_hConsoleOutput,
+                                    short in_wAttribute, int in_nLength, COORD in_dwWriteCoord,
+                                    IntByReference out_lpNumberOfAttrsWritten)
+            throws LastErrorException;
+//
+////    // BOOL WINAPI GetConsoleCursorInfo(
+////    // _In_ HANDLE hConsoleOutput,
+////    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+////    void GetConsoleCursorInfo(Pointer in_hConsoleOutput,
+////                              CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
+////            throws LastErrorException;
+//
+    // BOOL WINAPI GetConsoleMode(
+    //   _In_   HANDLE hConsoleHandle,
+    //   _Out_  LPDWORD lpMode);
+    void GetConsoleMode(
+            Pointer in_hConsoleOutput,
+            IntByReference out_lpMode)
+            throws LastErrorException;
+
+    // BOOL WINAPI GetConsoleScreenBufferInfo(
+    // _In_   HANDLE hConsoleOutput,
+    // _Out_  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+    void GetConsoleScreenBufferInfo(
+            Pointer in_hConsoleOutput,
+            CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
+            throws LastErrorException;
+//
+//    // BOOL WINAPI GetNumberOfConsoleInputEvents(
+//    // _In_ HANDLE hConsoleInput,
+//    // _Out_ LPDWORD lpcNumberOfEvents);
+//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput,
+//                                       IntByReference out_lpcNumberOfEvents) throws LastErrorException;
+//
+    // BOOL WINAPI ReadConsoleInput(
+    // _In_ HANDLE hConsoleInput,
+    // _Out_ PINPUT_RECORD lpBuffer,
+    // _In_ DWORD nLength,
+    // _Out_ LPDWORD lpNumberOfEventsRead);
+    void ReadConsoleInput(Pointer in_hConsoleOutput,
+                          INPUT_RECORD[] out_lpBuffer, int in_nLength,
+                          IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
+
+//    // BOOL WINAPI SetConsoleCtrlHandler(
+//    // _In_opt_  PHANDLER_ROUTINE HandlerRoutine,
+//    // _In_      BOOL Add);
+//    void SetConsoleCtrlHandler(
+//            Pointer in_opt_HandlerRoutine,
+//            boolean in_Add)
+//            throws LastErrorException;
+//
+//    // BOOL WINAPI ReadConsoleOutput(
+//    // _In_     HANDLE hConsoleOutput,
+//    // _Out_    PCHAR_INFO lpBuffer,
+//    // _In_     COORD dwBufferSize,
+//    // _In_     COORD dwBufferCoord,
+//    // _Inout_  PSMALL_RECT lpReadRegion);
+////    void ReadConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
+////                           COORD in_dwBufferSize, COORD in_dwBufferCoord,
+////                           SMALL_RECT inout_lpReadRegion) throws LastErrorException;
+////    void ReadConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
+////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
+////                            SMALL_RECT inout_lpReadRegion) throws LastErrorException;
+//
+//    // BOOL WINAPI ReadConsoleOutputCharacter(
+//    // _In_   HANDLE hConsoleOutput,
+//    // _Out_  LPTSTR lpCharacter,
+//    // _In_   DWORD nLength,
+//    // _In_   COORD dwReadCoord,
+//    // _Out_  LPDWORD lpNumberOfCharsRead);
+//    void ReadConsoleOutputCharacter(Pointer in_hConsoleOutput,
+//                                    char[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
+//                                    IntByReference out_lpNumberOfCharsRead)
+//            throws LastErrorException;
+//    void ReadConsoleOutputCharacterA(Pointer in_hConsoleOutput,
+//                                     byte[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
+//                                     IntByReference out_lpNumberOfCharsRead)
+//            throws LastErrorException;
+//
+//    // BOOL WINAPI SetConsoleCursorInfo(
+//    // _In_ HANDLE hConsoleOutput,
+//    // _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
+//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput,
+//                              CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
+//            throws LastErrorException;
+//
+//    // BOOL WINAPI SetConsoleCP(
+//    // _In_ UINT wCodePageID);
+//    void SetConsoleCP(int in_wCodePageID) throws LastErrorException;
+//
+//    // BOOL WINAPI SetConsoleOutputCP(
+//    // _In_ UINT wCodePageID);
+//    void SetConsoleOutputCP(int in_wCodePageID) throws LastErrorException;
+//
+    // BOOL WINAPI SetConsoleCursorPosition(
+    // _In_ HANDLE hConsoleOutput,
+    // _In_ COORD dwCursorPosition);
+    void SetConsoleCursorPosition(Pointer in_hConsoleOutput,
+                                  COORD in_dwCursorPosition) throws LastErrorException;
+
+    // BOOL WINAPI SetConsoleMode(
+    //   _In_  HANDLE hConsoleHandle,
+    //   _In_  DWORD dwMode);
+    void SetConsoleMode(
+            Pointer in_hConsoleOutput,
+            int in_dwMode) throws LastErrorException;
+
+//    // BOOL WINAPI SetConsoleScreenBufferSize(
+//    // __in HANDLE hConsoleOutput,
+//    // __in COORD dwSize
+//    // );
+//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput,
+//                                    COORD in_dwSize) throws LastErrorException;
+//
+    // BOOL WINAPI SetConsoleTextAttribute(
+    // _In_ HANDLE hConsoleOutput,
+    // _In_ WORD   wAttributes
+    // );
+    void SetConsoleTextAttribute(Pointer in_hConsoleOutput,
+                                 short in_wAttributes)
+            throws LastErrorException;
+
+    // BOOL WINAPI SetConsoleTitle(
+    // _In_ LPCTSTR lpConsoleTitle
+    // );
+    void SetConsoleTitle(String in_lpConsoleTitle)
+            throws LastErrorException;
+
+//    // BOOL WINAPI SetConsoleWindowInfo(
+//    // _In_ HANDLE hConsoleOutput,
+//    // _In_ BOOL bAbsolute,
+//    // _In_ const SMALL_RECT *lpConsoleWindow);
+//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput,
+//                              boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
+//            throws LastErrorException;
+
+    // BOOL WINAPI WriteConsole(
+    //  _In_             HANDLE  hConsoleOutput,
+    //  _In_       const VOID    *lpBuffer,
+    //  _In_             DWORD   nNumberOfCharsToWrite,
+    //  _Out_            LPDWORD lpNumberOfCharsWritten,
+    //  _Reserved_       LPVOID  lpReserved
+    // );
+    void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite,
+                          IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
+
+//    // BOOL WINAPI WriteConsoleOutput(
+//    // _In_ HANDLE hConsoleOutput,
+//    // _In_ const CHAR_INFO *lpBuffer,
+//    // _In_ COORD dwBufferSize,
+//    // _In_ COORD dwBufferCoord,
+//    // _Inout_ PSMALL_RECT lpWriteRegion);
+////    void WriteConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
+////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
+////                            SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
+////    void WriteConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
+////                             COORD in_dwBufferSize, COORD in_dwBufferCoord,
+////                             SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
+//
+//    // BOOL WINAPI WriteConsoleOutputCharacter(
+//    // _In_ HANDLE hConsoleOutput,
+//    // _In_ LPCTSTR lpCharacter,
+//    // _In_ DWORD nLength,
+//    // _In_ COORD dwWriteCoord,
+//    // _Out_ LPDWORD lpNumberOfCharsWritten);
+//    void WriteConsoleOutputCharacter(Pointer in_hConsoleOutput,
+//                                     char[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
+//                                     IntByReference out_lpNumberOfCharsWritten)
+//            throws LastErrorException;
+//    void WriteConsoleOutputCharacterA(Pointer in_hConsoleOutput,
+//                                      byte[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
+//                                      IntByReference out_lpNumberOfCharsWritten)
+//            throws LastErrorException;
+//
+    // BOOL WINAPI ScrollConsoleScreenBuffer(
+    //     _In_           HANDLE     hConsoleOutput,
+    //     _In_     const SMALL_RECT *lpScrollRectangle,
+    //     _In_opt_ const SMALL_RECT *lpClipRectangle,
+    //     _In_           COORD      dwDestinationOrigin,
+    //     _In_     const CHAR_INFO  *lpFill);
+    void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput,
+                                   SMALL_RECT in_lpScrollRectangle,
+                                   SMALL_RECT in_lpClipRectangle,
+                                   COORD in_dwDestinationOrigin,
+                                   CHAR_INFO in_lpFill)
+            throws LastErrorException;
+
+    // typedef struct _CHAR_INFO {
+    //   union {
+    //     WCHAR UnicodeChar;
+    //     CHAR  AsciiChar;
+    //   } Char;
+    //   WORD  Attributes;
+    // } CHAR_INFO, *PCHAR_INFO;
+    class CHAR_INFO {//extends Structure {
+        public CHAR_INFO() {
+        }
+
+        public CHAR_INFO(char c, short attr) {
+            uChar = new UnionChar(c);
+            Attributes = attr;
+        }
+
+//        public CHAR_INFO(byte c, short attr) {
+//            uChar = new UnionChar(c);
+//            Attributes = attr;
+//        }
+
+        public UnionChar uChar;
+        public short Attributes;
+
+//        public static CHAR_INFO[] createArray(int size) {
+//            return (CHAR_INFO[]) new CHAR_INFO().toArray(size);
+//        }
+//
+//        private static String[] fieldOrder = { "uChar", "Attributes" };
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _CONSOLE_CURSOR_INFO {
+    //   DWORD dwSize;
+    //   BOOL  bVisible;
+    // } CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
+    class CONSOLE_CURSOR_INFO {//extends Structure {
+        public int dwSize;
+        public boolean bVisible;
+
+//        public static class ByReference extends CONSOLE_CURSOR_INFO implements
+//                Structure.ByReference {
+//        }
+//
+//        private static String[] fieldOrder = { "dwSize", "bVisible" };
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
+    //   COORD      dwSize;
+    //   COORD      dwCursorPosition;
+    //   WORD       wAttributes;
+    //   SMALL_RECT srWindow;
+    //   COORD      dwMaximumWindowSize;
+    // } CONSOLE_SCREEN_BUFFER_INFO;
+    class CONSOLE_SCREEN_BUFFER_INFO {//extends Structure {
+        public COORD      dwSize;
+        public COORD      dwCursorPosition;
+        public short      wAttributes;
+        public SMALL_RECT srWindow;
+        public COORD      dwMaximumWindowSize;
+
+//        private static String[] fieldOrder = { "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize" };
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+
+        public int windowWidth() {
+            return this.srWindow.width() + 1;
+        }
+
+        public int windowHeight() {
+            return this.srWindow.height() + 1;
+        }
+    }
+
+    // typedef struct _COORD {
+    //    SHORT X;
+    //    SHORT Y;
+    //  } COORD, *PCOORD;
+    class COORD {//extends Structure implements Structure.ByValue {
+        public COORD() {
+        }
+
+        public COORD(short X, short Y) {
+            this.X = X;
+            this.Y = Y;
+        }
+
+        public short X;
+        public short Y;
+
+//        private static String[] fieldOrder = { "X", "Y" };
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _INPUT_RECORD {
+    //   WORD  EventType;
+    //   union {
+    //     KEY_EVENT_RECORD          KeyEvent;
+    //     MOUSE_EVENT_RECORD        MouseEvent;
+    //     WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+    //     MENU_EVENT_RECORD         MenuEvent;
+    //     FOCUS_EVENT_RECORD        FocusEvent;
+    //   } Event;
+    // } INPUT_RECORD;
+    class INPUT_RECORD {//extends Structure {
+        public static final short KEY_EVENT = 0x0001;
+        public static final short MOUSE_EVENT = 0x0002;
+        public static final short WINDOW_BUFFER_SIZE_EVENT = 0x0004;
+        public static final short MENU_EVENT = 0x0008;
+        public static final short FOCUS_EVENT = 0x0010;
+
+        public short EventType;
+        public EventUnion Event;
+
+        public static class EventUnion {//extends Union {
+            public KEY_EVENT_RECORD KeyEvent;
+            public MOUSE_EVENT_RECORD MouseEvent;
+            public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+            public MENU_EVENT_RECORD MenuEvent;
+            public FOCUS_EVENT_RECORD FocusEvent;
+        }
+
+//        @Override
+//        public void read() {
+//            readField("EventType");
+//            switch (EventType) {
+//                case KEY_EVENT:
+//                    Event.setType(KEY_EVENT_RECORD.class);
+//                    break;
+//                case MOUSE_EVENT:
+//                    Event.setType(MOUSE_EVENT_RECORD.class);
+//                    break;
+//                case WINDOW_BUFFER_SIZE_EVENT:
+//                    Event.setType(WINDOW_BUFFER_SIZE_RECORD.class);
+//                    break;
+//                case MENU_EVENT:
+//                    Event.setType(MENU_EVENT_RECORD.class);
+//                    break;
+//                case FOCUS_EVENT:
+//                    Event.setType(MENU_EVENT_RECORD.class);
+//                    break;
+//            }
+//            super.read();
+//        }
+
+//        private static String[] fieldOrder = {"EventType", "Event"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _KEY_EVENT_RECORD {
+    //   BOOL  bKeyDown;
+    //   WORD  wRepeatCount;
+    //   WORD  wVirtualKeyCode;
+    //   WORD  wVirtualScanCode;
+    //   union {
+    //     WCHAR UnicodeChar;
+    //     CHAR  AsciiChar;
+    //   } uChar;
+    //   DWORD dwControlKeyState;
+    // } KEY_EVENT_RECORD;
+    class KEY_EVENT_RECORD {//extends Structure {
+        public boolean bKeyDown;
+        public short wRepeatCount;
+        public short wVirtualKeyCode;
+        public short wVirtualScanCode;
+        public UnionChar uChar;
+        public int dwControlKeyState;
+
+//        private static String[] fieldOrder = {"bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _MOUSE_EVENT_RECORD {
+    //   COORD dwMousePosition;
+    //   DWORD dwButtonState;
+    //   DWORD dwControlKeyState;
+    //   DWORD dwEventFlags;
+    // } MOUSE_EVENT_RECORD;
+    class MOUSE_EVENT_RECORD {//extends Structure {
+        public COORD dwMousePosition;
+        public int dwButtonState;
+        public int dwControlKeyState;
+        public int dwEventFlags;
+
+//        private static String[] fieldOrder = { "dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _WINDOW_BUFFER_SIZE_RECORD {
+    //   COORD dwSize;
+    // } WINDOW_BUFFER_SIZE_RECORD;
+    class WINDOW_BUFFER_SIZE_RECORD {//extends Structure {
+        public COORD dwSize;
+
+//        private static String[] fieldOrder = {"dwSize"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _MENU_EVENT_RECORD {
+    //   UINT dwCommandId;
+    // } MENU_EVENT_RECORD, *PMENU_EVENT_RECORD;
+    class MENU_EVENT_RECORD {//extends Structure {
+
+        public int dwCommandId;
+
+//        private static String[] fieldOrder = {"dwCommandId"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _FOCUS_EVENT_RECORD {
+    //  BOOL bSetFocus;
+    //} FOCUS_EVENT_RECORD;
+    class FOCUS_EVENT_RECORD {//extends Structure {
+        public boolean bSetFocus;
+
+//        private static String[] fieldOrder = {"bSetFocus"};
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+    }
+
+    // typedef struct _SMALL_RECT {
+    //    SHORT Left;
+    //    SHORT Top;
+    //    SHORT Right;
+    //    SHORT Bottom;
+    //  } SMALL_RECT;
+    class SMALL_RECT {//extends Structure {
+        public SMALL_RECT() {
+        }
+
+        public SMALL_RECT(SMALL_RECT org) {
+            this(org.Top, org.Left, org.Bottom, org.Right);
+        }
+
+        public SMALL_RECT(short Top, short Left, short Bottom, short Right) {
+            this.Top = Top;
+            this.Left = Left;
+            this.Bottom = Bottom;
+            this.Right = Right;
+        }
+
+        public short Left;
+        public short Top;
+        public short Right;
+        public short Bottom;
+
+//        private static String[] fieldOrder = { "Left", "Top", "Right", "Bottom" };
+//
+//        @Override
+//        protected java.util.List<String> getFieldOrder() {
+//            return java.util.Arrays.asList(fieldOrder);
+//        }
+
+        public short width() {
+            return (short)(this.Right - this.Left);
+        }
+
+        public short height() {
+            return (short)(this.Bottom - this.Top);
+        }
+
+    }
+
+    class UnionChar {//extends Union {
+        public UnionChar() {
+        }
+
+        public UnionChar(char c) {
+//            setType(char.class);
+            UnicodeChar = c;
+        }
+
+//        public UnionChar(byte c) {
+//            setType(byte.class);
+//            AsciiChar = c;
+//        }
+
+        public void set(char c) {
+//            setType(char.class);
+            UnicodeChar = c;
+        }
+
+//        public void set(byte c) {
+//            setType(byte.class);
+//            AsciiChar = c;
+//        }
+
+        public char UnicodeChar;
+//        public byte AsciiChar;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO;
+import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO;
+import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD;
+import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD;
+import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT;
+
+public class Kernel32Impl implements Kernel32 {
+
+    static {
+        System.loadLibrary("le");
+        initIDs();
+    }
+
+    private static native void initIDs();
+
+    @Override
+    public native int WaitForSingleObject(Pointer in_hHandle, int in_dwMilliseconds);
+
+    @Override
+    public native Pointer GetStdHandle(int nStdHandle);
+
+    @Override
+    public native int GetConsoleOutputCP();
+
+    @Override
+    public native void FillConsoleOutputCharacter(Pointer in_hConsoleOutput, char in_cCharacter, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfCharsWritten) throws LastErrorException;
+
+    @Override
+    public native void FillConsoleOutputAttribute(Pointer in_hConsoleOutput, short in_wAttribute, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfAttrsWritten) throws LastErrorException;
+
+    @Override
+    public native void GetConsoleMode(Pointer in_hConsoleOutput, IntByReference out_lpMode) throws LastErrorException;
+
+    @Override
+    public native void GetConsoleScreenBufferInfo(Pointer in_hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo) throws LastErrorException;
+
+    @Override
+    public native void ReadConsoleInput(Pointer in_hConsoleOutput, INPUT_RECORD[] out_lpBuffer, int in_nLength, IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
+
+    @Override
+    public native void SetConsoleCursorPosition(Pointer in_hConsoleOutput, COORD in_dwCursorPosition) throws LastErrorException;
+
+    @Override
+    public native void SetConsoleMode(Pointer in_hConsoleOutput, int in_dwMode) throws LastErrorException;
+
+    @Override
+    public native void SetConsoleTextAttribute(Pointer in_hConsoleOutput, short in_wAttributes) throws LastErrorException;
+
+    @Override
+    public native void SetConsoleTitle(String in_lpConsoleTitle) throws LastErrorException;
+
+    @Override
+    public native void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite, IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
+
+    @Override
+    public native void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput, SMALL_RECT in_lpScrollRectangle, SMALL_RECT in_lpClipRectangle, COORD in_dwDestinationOrigin, CHAR_INFO in_lpFill) throws LastErrorException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/LastErrorException.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+@SuppressWarnings("serial")
+class LastErrorException extends RuntimeException{
+
+    public final long lastError;
+
+    public LastErrorException(long lastError) {
+        this.lastError = lastError;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Pointer.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+class Pointer {
+    public final long value;
+
+    public Pointer(long value) {
+        this.value = value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2002-2016, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.org.jline.terminal.impl.jna.win;
+
+import java.io.IOException;
+import java.io.Writer;
+
+//import com.sun.jna.Pointer;
+//import com.sun.jna.ptr.IntByReference;
+import jdk.internal.org.jline.utils.AnsiWriter;
+import jdk.internal.org.jline.utils.Colors;
+
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_BLUE;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_GREEN;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_INTENSITY;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_RED;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_BLUE;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_GREEN;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_INTENSITY;
+import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_RED;
+
+
+/**
+ * A Windows ANSI escape processor, uses JNA to access native platform
+ * API's to change the console attributes.
+ *
+ * @since 1.0
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ * @author Joris Kuipers
+ */
+public final class WindowsAnsiWriter extends AnsiWriter {
+
+    private static final short FOREGROUND_BLACK   = 0;
+    private static final short FOREGROUND_YELLOW  = (short) (FOREGROUND_RED|FOREGROUND_GREEN);
+    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE|FOREGROUND_RED);
+    private static final short FOREGROUND_CYAN    = (short) (FOREGROUND_BLUE|FOREGROUND_GREEN);
+    private static final short FOREGROUND_WHITE   = (short) (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
+
+    private static final short BACKGROUND_BLACK   = 0;
+    private static final short BACKGROUND_YELLOW  = (short) (BACKGROUND_RED|BACKGROUND_GREEN);
+    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE|BACKGROUND_RED);
+    private static final short BACKGROUND_CYAN    = (short) (BACKGROUND_BLUE|BACKGROUND_GREEN);
+    private static final short BACKGROUND_WHITE   = (short) (BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
+
+    private static final short ANSI_FOREGROUND_COLOR_MAP[] = {
+            FOREGROUND_BLACK,
+            FOREGROUND_RED,
+            FOREGROUND_GREEN,
+            FOREGROUND_YELLOW,
+            FOREGROUND_BLUE,
+            FOREGROUND_MAGENTA,
+            FOREGROUND_CYAN,
+            FOREGROUND_WHITE,
+    };
+
+    private static final short ANSI_BACKGROUND_COLOR_MAP[] = {
+            BACKGROUND_BLACK,
+            BACKGROUND_RED,
+            BACKGROUND_GREEN,
+            BACKGROUND_YELLOW,
+            BACKGROUND_BLUE,
+            BACKGROUND_MAGENTA,
+            BACKGROUND_CYAN,
+            BACKGROUND_WHITE,
+    };
+
+    private final static int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
+
+    private final Pointer console;
+
+    private final Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
+    private final short originalColors;
+
+    private boolean negative;
+    private boolean bold;
+    private boolean underline;
+    private short savedX = -1;
+    private short savedY = -1;
+
+    public WindowsAnsiWriter(Writer out, Pointer console) throws IOException {
+        super(out);
+        this.console = console;
+        getConsoleInfo();
+        originalColors = info.wAttributes;
+    }
+
+    private void getConsoleInfo() throws IOException {
+        out.flush();
+        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(console, info);
+        if( negative ) {
+            info.wAttributes = invertAttributeColors(info.wAttributes);
+        }
+    }
+
+    private void applyAttribute() throws IOException {
+        out.flush();
+        short attributes = info.wAttributes;
+        // bold is simulated by high foreground intensity
+        if (bold) {
+            attributes |= FOREGROUND_INTENSITY;
+        }
+        // underline is simulated by high foreground intensity
+        if (underline) {
+            attributes |= BACKGROUND_INTENSITY;
+        }
+        if( negative ) {
+            attributes = invertAttributeColors(attributes);
+        }
+        Kernel32.INSTANCE.SetConsoleTextAttribute(console, attributes);
+    }
+
+    private short invertAttributeColors(short attributes) {
+        // Swap the the Foreground and Background bits.
+        int fg = 0x000F & attributes;
+        fg <<= 4;
+        int bg = 0X00F0 & attributes;
+        bg >>= 4;
+        attributes = (short) ((attributes & 0xFF00) | fg | bg);
+        return attributes;
+    }
+
+    private void applyCursorPosition() throws IOException {
+        info.dwCursorPosition.X = (short) Math.max(0, Math.min(info.dwSize.X - 1, info.dwCursorPosition.X));
+        info.dwCursorPosition.Y = (short) Math.max(0, Math.min(info.dwSize.Y - 1, info.dwCursorPosition.Y));
+        Kernel32.INSTANCE.SetConsoleCursorPosition(console, info.dwCursorPosition);
+    }
+
+    protected void processEraseScreen(int eraseOption) throws IOException {
+        getConsoleInfo();
+        IntByReference written = new IntByReference();
+        switch(eraseOption) {
+            case ERASE_SCREEN:
+                Kernel32.COORD topLeft = new Kernel32.COORD();
+                topLeft.X = 0;
+                topLeft.Y = info.srWindow.Top;
+                int screenLength = info.srWindow.height() * info.dwSize.X;
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', screenLength, topLeft, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, screenLength, topLeft, written);
+                break;
+            case ERASE_SCREEN_TO_BEGINING:
+                Kernel32.COORD topLeft2 = new Kernel32.COORD();
+                topLeft2.X = 0;
+                topLeft2.Y = info.srWindow.Top;
+                int lengthToCursor = (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToCursor, topLeft2, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToCursor, topLeft2, written);
+                break;
+            case ERASE_SCREEN_TO_END:
+                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X +
+                        (info.dwSize.X - info.dwCursorPosition.X);
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToEnd, info.dwCursorPosition, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
+        }
+    }
+
+    protected void processEraseLine(int eraseOption) throws IOException {
+        getConsoleInfo();
+        IntByReference written = new IntByReference();
+        switch(eraseOption) {
+            case ERASE_LINE:
+                Kernel32.COORD leftColCurrRow = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwSize.X, leftColCurrRow, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
+                break;
+            case ERASE_LINE_TO_BEGINING:
+                Kernel32.COORD leftColCurrRow2 = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
+                break;
+            case ERASE_LINE_TO_END:
+                int lengthToLastCol = info.dwSize.X - info.dwCursorPosition.X;
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToLastCol, info.dwCursorPosition, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
+        }
+    }
+
+    protected void processCursorUpLine(int count) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.X = 0;
+        info.dwCursorPosition.Y -= count;
+        applyCursorPosition();
+    }
+
+    protected void processCursorDownLine(int count) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.X = 0;
+        info.dwCursorPosition.Y += count;
+        applyCursorPosition();
+    }
+
+    protected void processCursorLeft(int count) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.X -= count;
+        applyCursorPosition();
+    }
+
+    protected void processCursorRight(int count) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.X += count;
+        applyCursorPosition();
+    }
+
+    protected void processCursorDown(int count) throws IOException {
+        getConsoleInfo();
+        int nb = Math.max(0, info.dwCursorPosition.Y + count - info.dwSize.Y + 1);
+        if (nb != count) {
+            info.dwCursorPosition.Y += count;
+            applyCursorPosition();
+        }
+        if (nb > 0) {
+            Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
+            scroll.Top = 0;
+            Kernel32.COORD org = new Kernel32.COORD();
+            org.X = 0;
+            org.Y = (short)(- nb);
+            Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+            Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+        }
+    }
+
+    protected void processCursorUp(int count) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.Y -= count;
+        applyCursorPosition();
+    }
+
+    protected void processCursorTo(int row, int col) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.Y = (short) (info.srWindow.Top + row - 1);
+        info.dwCursorPosition.X = (short) (col - 1);
+        applyCursorPosition();
+    }
+
+    protected void processCursorToColumn(int x) throws IOException {
+        getConsoleInfo();
+        info.dwCursorPosition.X = (short) (x - 1);
+        applyCursorPosition();
+    }
+
+    @Override
+    protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
+        int color = Colors.roundColor(paletteIndex, 16);
+        info.wAttributes = (short) ((info.wAttributes & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]);
+        info.wAttributes = (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
+        applyAttribute();
+    }
+
+    protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
+        int color = Colors.roundColor(paletteIndex, 16);
+        info.wAttributes = (short)((info.wAttributes & ~0x0070 ) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
+        info.wAttributes = (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
+        applyAttribute();
+    }
+
+    protected void processDefaultTextColor() throws IOException {
+        info.wAttributes = (short)((info.wAttributes & ~0x000F ) | (originalColors & 0x000F));
+        applyAttribute();
+    }
+
+    protected void processDefaultBackgroundColor() throws IOException {
+        info.wAttributes = (short)((info.wAttributes & ~0x00F0 ) | (originalColors & 0x00F0));
+        applyAttribute();
+    }
+
+    protected void processAttributeRest() throws IOException {
+        info.wAttributes = (short)((info.wAttributes & ~0x00FF ) | originalColors);
+        this.negative = false;
+        this.bold = false;
+        this.underline = false;
+        applyAttribute();
+    }
+
+    protected void processSetAttribute(int attribute) throws IOException {
+        switch(attribute) {
+            case ATTRIBUTE_INTENSITY_BOLD:
+                bold = true;
+                applyAttribute();
+                break;
+            case ATTRIBUTE_INTENSITY_NORMAL:
+                bold = false;
+                applyAttribute();
+                break;
+
+            case ATTRIBUTE_UNDERLINE:
+                underline = true;
+                applyAttribute();
+                break;
+            case ATTRIBUTE_UNDERLINE_OFF:
+                underline = false;
+                applyAttribute();
+                break;
+
+            case ATTRIBUTE_NEGATIVE_ON:
+                negative = true;
+                applyAttribute();
+                break;
+            case ATTRIBUTE_NEGATIVE_OFF:
+                negative = false;
+                applyAttribute();
+                break;
+        }
+    }
+
+    protected void processSaveCursorPosition() throws IOException {
+        getConsoleInfo();
+        savedX = info.dwCursorPosition.X;
+        savedY = info.dwCursorPosition.Y;
+    }
+
+    protected void processRestoreCursorPosition() throws IOException {
+        // restore only if there was a save operation first
+        if (savedX != -1 && savedY != -1) {
+            out.flush();
+            info.dwCursorPosition.X = savedX;
+            info.dwCursorPosition.Y = savedY;
+            applyCursorPosition();
+        }
+    }
+
+    @Override
+    protected void processInsertLine(int optionInt) throws IOException {
+        getConsoleInfo();
+        Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
+        scroll.Top = info.dwCursorPosition.Y;
+        Kernel32.COORD org = new Kernel32.COORD();
+        org.X = 0;
+        org.Y = (short)(info.dwCursorPosition.Y + optionInt);
+        Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+        Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+    }
+
+    @Override
+    protected void processDeleteLine(int optionInt) throws IOException {
+        getConsoleInfo();
+        Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
+        scroll.Top = info.dwCursorPosition.Y;
+        Kernel32.COORD org = new Kernel32.COORD();
+        org.X = 0;
+        org.Y = (short)(info.dwCursorPosition.Y - optionInt);
+        Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+        Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+    }
+
+    protected void processChangeWindowTitle(String label) {
+        Kernel32.INSTANCE.SetConsoleTitle(label);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/classes/module-info.java.extra	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+
+provides jdk.internal.org.jline.terminal.spi.JnaSupport with jdk.internal.org.jline.terminal.impl.jna.JnaSupportImpl;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,710 @@
+/*
+ * 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
+ * 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl.h"
+
+#include <stdlib.h>
+#include <wincon.h>
+#include <winuser.h>
+
+static jclass pointerClass;
+static jmethodID pointerConstructor;
+static jfieldID pointerValue;
+
+static jclass intByReferenceClass;
+static jfieldID intByReferenceValue;
+
+static jclass lastErrorExceptionClass;
+static jmethodID lastErrorExceptionConstructor;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO
+static jclass CHAR_INFO_Class;
+static jmethodID CHAR_INFO_Constructor;
+static jfieldID CHAR_INFO_uChar;
+static jfieldID CHAR_INFO_Attributes;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_CURSOR_INFO
+static jclass CONSOLE_CURSOR_INFO_Class;
+static jmethodID CONSOLE_CURSOR_INFO_Constructor;
+static jfieldID CONSOLE_CURSOR_INFO_dwSize;
+static jfieldID CONSOLE_CURSOR_INFO_bVisible;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
+static jclass CONSOLE_SCREEN_BUFFER_INFO_Class;
+static jmethodID CONSOLE_SCREEN_BUFFER_INFO_Constructor;
+static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwSize;
+static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition;
+static jfieldID CONSOLE_SCREEN_BUFFER_INFO_wAttributes;
+static jfieldID CONSOLE_SCREEN_BUFFER_INFO_srWindow;
+static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD
+static jclass COORD_Class;
+static jmethodID COORD_Constructor;
+static jfieldID COORD_X;
+static jfieldID COORD_Y;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD
+static jclass INPUT_RECORD_Class;
+static jmethodID INPUT_RECORD_Constructor;
+static jfieldID INPUT_RECORD_EventType;
+static jfieldID INPUT_RECORD_Event;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD.EventUnion
+static jclass EventUnion_Class;
+static jmethodID EventUnion_Constructor;
+static jfieldID EventUnion_KeyEvent;
+static jfieldID EventUnion_MouseEvent;
+static jfieldID EventUnion_WindowBufferSizeEvent;
+static jfieldID EventUnion_MenuEvent;
+static jfieldID EventUnion_FocusEvent;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.KEY_EVENT_RECORD
+static jclass KEY_EVENT_RECORD_Class;
+static jmethodID KEY_EVENT_RECORD_Constructor;
+static jfieldID KEY_EVENT_RECORD_bKeyDown;
+static jfieldID KEY_EVENT_RECORD_wRepeatCount;
+static jfieldID KEY_EVENT_RECORD_wVirtualKeyCode;
+static jfieldID KEY_EVENT_RECORD_wVirtualScanCode;
+static jfieldID KEY_EVENT_RECORD_uChar;
+static jfieldID KEY_EVENT_RECORD_dwControlKeyState;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MOUSE_EVENT_RECORD
+static jclass MOUSE_EVENT_RECORD_Class;
+static jmethodID MOUSE_EVENT_RECORD_Constructor;
+static jfieldID MOUSE_EVENT_RECORD_dwMousePosition;
+static jfieldID MOUSE_EVENT_RECORD_dwButtonState;
+static jfieldID MOUSE_EVENT_RECORD_dwControlKeyState;
+static jfieldID MOUSE_EVENT_RECORD_dwEventFlags;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.WINDOW_BUFFER_SIZE_RECORD
+static jclass WINDOW_BUFFER_SIZE_RECORD_Class;
+static jmethodID WINDOW_BUFFER_SIZE_RECORD_Constructor;
+static jfieldID WINDOW_BUFFER_SIZE_RECORD_dwSize;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MENU_EVENT_RECORD
+static jclass MENU_EVENT_RECORD_Class;
+static jmethodID MENU_EVENT_RECORD_Constructor;
+static jfieldID MENU_EVENT_RECORD_dwCommandId;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOCUS_EVENT_RECORD
+static jclass FOCUS_EVENT_RECORD_Class;
+static jmethodID FOCUS_EVENT_RECORD_Constructor;
+static jfieldID FOCUS_EVENT_RECORD_bSetFocus;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT
+static jclass SMALL_RECT_Class;
+static jmethodID SMALL_RECT_Constructor;
+static jfieldID SMALL_RECT_Left;
+static jfieldID SMALL_RECT_Top;
+static jfieldID SMALL_RECT_Right;
+static jfieldID SMALL_RECT_Bottom;
+
+//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.UnionChar
+static jclass UnionChar_Class;
+static jmethodID UnionChar_Constructor;
+static jfieldID UnionChar_UnicodeChar;
+
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_initIDs
+  (JNIEnv *env, jclass) {
+    jclass cls;
+    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Pointer");
+    CHECK_NULL(cls);
+    pointerClass = (jclass) env->NewGlobalRef(cls);
+    pointerConstructor = env->GetMethodID(cls, "<init>", "(J)V");
+    CHECK_NULL(pointerConstructor);
+    pointerValue  = env->GetFieldID(cls, "value", "J");
+    CHECK_NULL(pointerValue);
+
+    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/LastErrorException");
+    CHECK_NULL(cls);
+    lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
+    lastErrorExceptionConstructor = env->GetMethodID(cls, "<init>", "(J)V");
+    CHECK_NULL(lastErrorExceptionConstructor);
+
+    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/IntByReference");
+    CHECK_NULL(cls);
+    intByReferenceClass = (jclass) env->NewGlobalRef(cls);
+    intByReferenceValue = env->GetFieldID(cls, "value", "I");
+    CHECK_NULL(intByReferenceValue);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO
+    CHAR_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CHAR_INFO"));
+    CHECK_NULL(CHAR_INFO_Class);
+    CHAR_INFO_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(CHAR_INFO_Constructor);
+    CHAR_INFO_uChar = env->GetFieldID(CHAR_INFO_Class, "uChar", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar;");
+    CHECK_NULL(CHAR_INFO_uChar);
+    CHAR_INFO_Attributes = env->GetFieldID(CHAR_INFO_Class, "Attributes", "S");
+    CHECK_NULL(CHAR_INFO_Attributes);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_CURSOR_INFO
+    CONSOLE_CURSOR_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CONSOLE_CURSOR_INFO"));
+    CHECK_NULL(CONSOLE_CURSOR_INFO_Class);
+    CONSOLE_CURSOR_INFO_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(CONSOLE_CURSOR_INFO_Constructor);
+    CONSOLE_CURSOR_INFO_dwSize = env->GetFieldID(CONSOLE_CURSOR_INFO_Class, "dwSize", "I");
+    CHECK_NULL(CONSOLE_CURSOR_INFO_dwSize);
+    CONSOLE_CURSOR_INFO_bVisible = env->GetFieldID(CONSOLE_CURSOR_INFO_Class, "bVisible", "Z");
+    CHECK_NULL(CONSOLE_CURSOR_INFO_bVisible);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
+    CONSOLE_SCREEN_BUFFER_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CONSOLE_SCREEN_BUFFER_INFO"));
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_Class);
+    CONSOLE_SCREEN_BUFFER_INFO_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_Constructor);
+    CONSOLE_SCREEN_BUFFER_INFO_dwSize = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwSize);
+    CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwCursorPosition", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition);
+    CONSOLE_SCREEN_BUFFER_INFO_wAttributes = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "wAttributes", "S");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_wAttributes);
+    CONSOLE_SCREEN_BUFFER_INFO_srWindow = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "srWindow", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$SMALL_RECT;");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_srWindow);
+    CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwMaximumWindowSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
+    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD
+    COORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD"));
+    CHECK_NULL(COORD_Class);
+    COORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(COORD_Constructor);
+    COORD_X = env->GetFieldID(COORD_Class, "X", "S");
+    CHECK_NULL(COORD_X);
+    COORD_Y = env->GetFieldID(COORD_Class, "Y", "S");
+    CHECK_NULL(COORD_Y);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD
+    INPUT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD"));
+    CHECK_NULL(INPUT_RECORD_Class);
+    INPUT_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(INPUT_RECORD_Constructor);
+    INPUT_RECORD_EventType = env->GetFieldID(INPUT_RECORD_Class, "EventType", "S");
+    CHECK_NULL(INPUT_RECORD_EventType);
+    INPUT_RECORD_Event = env->GetFieldID(INPUT_RECORD_Class, "Event", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD$EventUnion;");
+    CHECK_NULL(INPUT_RECORD_Event);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD.EventUnion
+    EventUnion_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD$EventUnion"));
+    CHECK_NULL(EventUnion_Class);
+    EventUnion_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(EventUnion_Constructor);
+    EventUnion_KeyEvent = env->GetFieldID(EventUnion_Class, "KeyEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$KEY_EVENT_RECORD;");
+    CHECK_NULL(EventUnion_KeyEvent);
+    EventUnion_MouseEvent = env->GetFieldID(EventUnion_Class, "MouseEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MOUSE_EVENT_RECORD;");
+    CHECK_NULL(EventUnion_MouseEvent);
+    EventUnion_WindowBufferSizeEvent = env->GetFieldID(EventUnion_Class, "WindowBufferSizeEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$WINDOW_BUFFER_SIZE_RECORD;");
+    CHECK_NULL(EventUnion_WindowBufferSizeEvent);
+    EventUnion_MenuEvent = env->GetFieldID(EventUnion_Class, "MenuEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MENU_EVENT_RECORD;");
+    CHECK_NULL(EventUnion_MenuEvent);
+    EventUnion_FocusEvent = env->GetFieldID(EventUnion_Class, "FocusEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$FOCUS_EVENT_RECORD;");
+    CHECK_NULL(EventUnion_FocusEvent);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.KEY_EVENT_RECORD
+    KEY_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$KEY_EVENT_RECORD"));
+    CHECK_NULL(KEY_EVENT_RECORD_Class);
+    KEY_EVENT_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(KEY_EVENT_RECORD_Constructor);
+    KEY_EVENT_RECORD_bKeyDown = env->GetFieldID(KEY_EVENT_RECORD_Class, "bKeyDown", "Z");
+    CHECK_NULL(KEY_EVENT_RECORD_bKeyDown);
+    KEY_EVENT_RECORD_wRepeatCount = env->GetFieldID(KEY_EVENT_RECORD_Class, "wRepeatCount", "S");
+    CHECK_NULL(KEY_EVENT_RECORD_wRepeatCount);
+    KEY_EVENT_RECORD_wVirtualKeyCode = env->GetFieldID(KEY_EVENT_RECORD_Class, "wVirtualKeyCode", "S");
+    CHECK_NULL(KEY_EVENT_RECORD_wVirtualKeyCode);
+    KEY_EVENT_RECORD_wVirtualScanCode = env->GetFieldID(KEY_EVENT_RECORD_Class, "wVirtualScanCode", "S");
+    CHECK_NULL(KEY_EVENT_RECORD_wVirtualScanCode);
+    KEY_EVENT_RECORD_uChar = env->GetFieldID(KEY_EVENT_RECORD_Class, "uChar", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar;");
+    CHECK_NULL(KEY_EVENT_RECORD_uChar);
+    KEY_EVENT_RECORD_dwControlKeyState = env->GetFieldID(KEY_EVENT_RECORD_Class, "dwControlKeyState", "I");
+    CHECK_NULL(KEY_EVENT_RECORD_dwControlKeyState);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MOUSE_EVENT_RECORD
+    MOUSE_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MOUSE_EVENT_RECORD"));
+    CHECK_NULL(MOUSE_EVENT_RECORD_Class);
+    MOUSE_EVENT_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(MOUSE_EVENT_RECORD_Constructor);
+    MOUSE_EVENT_RECORD_dwMousePosition = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwMousePosition", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
+    CHECK_NULL(MOUSE_EVENT_RECORD_dwMousePosition);
+    MOUSE_EVENT_RECORD_dwButtonState = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwButtonState", "I");
+    CHECK_NULL(MOUSE_EVENT_RECORD_dwButtonState);
+    MOUSE_EVENT_RECORD_dwControlKeyState = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwControlKeyState", "I");
+    CHECK_NULL(MOUSE_EVENT_RECORD_dwControlKeyState);
+    MOUSE_EVENT_RECORD_dwEventFlags = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwEventFlags", "I");
+    CHECK_NULL(MOUSE_EVENT_RECORD_dwEventFlags);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.WINDOW_BUFFER_SIZE_RECORD
+    WINDOW_BUFFER_SIZE_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$WINDOW_BUFFER_SIZE_RECORD"));
+    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_Class);
+    WINDOW_BUFFER_SIZE_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_Constructor);
+    WINDOW_BUFFER_SIZE_RECORD_dwSize = env->GetFieldID(WINDOW_BUFFER_SIZE_RECORD_Class, "dwSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
+    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_dwSize);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MENU_EVENT_RECORD
+    MENU_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MENU_EVENT_RECORD"));
+    CHECK_NULL(MENU_EVENT_RECORD_Class);
+    MENU_EVENT_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(MENU_EVENT_RECORD_Constructor);
+    MENU_EVENT_RECORD_dwCommandId = env->GetFieldID(MENU_EVENT_RECORD_Class, "dwCommandId", "I");
+    CHECK_NULL(MENU_EVENT_RECORD_dwCommandId);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOCUS_EVENT_RECORD
+    FOCUS_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$FOCUS_EVENT_RECORD"));
+    CHECK_NULL(FOCUS_EVENT_RECORD_Class);
+    FOCUS_EVENT_RECORD_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(FOCUS_EVENT_RECORD_Constructor);
+    FOCUS_EVENT_RECORD_bSetFocus = env->GetFieldID(FOCUS_EVENT_RECORD_Class, "bSetFocus", "Z");
+    CHECK_NULL(FOCUS_EVENT_RECORD_bSetFocus);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT
+    SMALL_RECT_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$SMALL_RECT"));
+    CHECK_NULL(SMALL_RECT_Class);
+    SMALL_RECT_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(SMALL_RECT_Constructor);
+    SMALL_RECT_Left = env->GetFieldID(SMALL_RECT_Class, "Left", "S");
+    CHECK_NULL(SMALL_RECT_Left);
+    SMALL_RECT_Top = env->GetFieldID(SMALL_RECT_Class, "Top", "S");
+    CHECK_NULL(SMALL_RECT_Top);
+    SMALL_RECT_Right = env->GetFieldID(SMALL_RECT_Class, "Right", "S");
+    CHECK_NULL(SMALL_RECT_Right);
+    SMALL_RECT_Bottom = env->GetFieldID(SMALL_RECT_Class, "Bottom", "S");
+    CHECK_NULL(SMALL_RECT_Bottom);
+
+    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.UnionChar
+    UnionChar_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar"));
+    CHECK_NULL(UnionChar_Class);
+    UnionChar_Constructor = env->GetMethodID(cls, "<init>", "()V");
+    CHECK_NULL(UnionChar_Constructor);
+    UnionChar_UnicodeChar = env->GetFieldID(UnionChar_Class, "UnicodeChar", "C");
+    CHECK_NULL(UnionChar_UnicodeChar);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    WaitForSingleObject
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;I)I
+ */
+JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_WaitForSingleObject
+  (JNIEnv *env, jobject kernel, jobject in_hHandle, jint in_dwMilliseconds) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hHandle, pointerValue));
+    return WaitForSingleObject(h, in_dwMilliseconds);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    GetStdHandle
+ * Signature: (I)Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;
+ */
+JNIEXPORT jobject JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetStdHandle
+  (JNIEnv *env, jobject, jint nStdHandle) {
+    return env->NewObject(pointerClass,
+                          pointerConstructor,
+                          nStdHandle);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    GetConsoleOutputCP
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleOutputCP
+  (JNIEnv *, jobject) {
+    return GetConsoleOutputCP();
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    FillConsoleOutputCharacter
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;CILjdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_FillConsoleOutputCharacter
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jchar in_cCharacter, jint in_nLength, jobject in_dwWriteCoord, jobject out_lpNumberOfCharsWritten) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    DWORD written;
+    COORD coord;
+    coord.X = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_X);
+    coord.Y = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_Y);
+    if (!FillConsoleOutputCharacter(h, (CHAR) in_cCharacter, in_nLength, coord, &written)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+    env->SetIntField(out_lpNumberOfCharsWritten, intByReferenceValue, written);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    FillConsoleOutputAttribute
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;SILjdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_FillConsoleOutputAttribute
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jshort in_wAttribute, jint in_nLength, jobject in_dwWriteCoord, jobject out_lpNumberOfAttrsWritten) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    DWORD written;
+    COORD coord;
+    coord.X = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_X);
+    coord.Y = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_Y);
+    if (!FillConsoleOutputAttribute(h, in_wAttribute, in_nLength, coord, &written)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+    env->SetIntField(out_lpNumberOfAttrsWritten, intByReferenceValue, written);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    GetConsoleMode
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleMode
+  (JNIEnv *env, jobject, jobject in_hConsoleOutput, jobject out_lpMode) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    DWORD mode;
+    if (!GetConsoleMode(h, &mode)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+    env->SetIntField(out_lpMode, intByReferenceValue, mode);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    GetConsoleScreenBufferInfo
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/CONSOLE_SCREEN_BUFFER_INFO;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleScreenBufferInfo
+  (JNIEnv *env, jobject, jobject in_hConsoleOutput, jobject/*CONSOLE_SCREEN_BUFFER_INFO*/ out_lpConsoleScreenBufferInfo) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    CONSOLE_SCREEN_BUFFER_INFO buffer;
+    if (!GetConsoleScreenBufferInfo(h, &buffer)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+
+    jobject dwSize = env->NewObject(COORD_Class,
+                                    COORD_Constructor);
+    env->SetIntField(dwSize, COORD_X, buffer.dwSize.X);
+    env->SetIntField(dwSize, COORD_Y, buffer.dwSize.Y);
+    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwSize, dwSize);
+
+    jobject dwCursorPosition = env->NewObject(COORD_Class,
+                                              COORD_Constructor);
+    env->SetIntField(dwCursorPosition, COORD_X, buffer.dwCursorPosition.X);
+    env->SetIntField(dwCursorPosition, COORD_Y, buffer.dwCursorPosition.Y);
+    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition, dwCursorPosition);
+
+    env->SetIntField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_wAttributes, buffer.wAttributes);
+
+    jobject srWindow = env->NewObject(SMALL_RECT_Class,
+                                      SMALL_RECT_Constructor);
+    env->SetIntField(srWindow, SMALL_RECT_Left, buffer.srWindow.Left);
+    env->SetIntField(srWindow, SMALL_RECT_Top, buffer.srWindow.Top);
+    env->SetIntField(srWindow, SMALL_RECT_Right, buffer.srWindow.Right);
+    env->SetIntField(srWindow, SMALL_RECT_Bottom, buffer.srWindow.Bottom);
+    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_srWindow, srWindow);
+
+    jobject dwMaximumWindowSize = env->NewObject(COORD_Class,
+                                                 COORD_Constructor);
+    env->SetIntField(dwMaximumWindowSize, COORD_X, buffer.dwMaximumWindowSize.X);
+    env->SetIntField(dwMaximumWindowSize, COORD_Y, buffer.dwMaximumWindowSize.Y);
+    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize, dwMaximumWindowSize);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    ReadConsoleInput
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;[Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/INPUT_RECORD;ILjdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_ReadConsoleInput
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobjectArray/*INPUT_RECORD[]*/ out_lpBuffer, jint in_nLength, jobject out_lpNumberOfEventsRead) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    INPUT_RECORD *buffer = new INPUT_RECORD[in_nLength];
+    DWORD numberOfEventsRead;
+    if (!ReadConsoleInput(h, buffer, in_nLength, &numberOfEventsRead)) {
+        delete buffer;
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+    for (unsigned int i = 0; i < numberOfEventsRead; i++) {
+        jobject record = env->NewObject(INPUT_RECORD_Class,
+                                        INPUT_RECORD_Constructor);
+        env->SetShortField(record, INPUT_RECORD_EventType, buffer[i].EventType);
+        switch (buffer[i].EventType) {
+            case KEY_EVENT: {
+                jobject keyEvent = env->NewObject(KEY_EVENT_RECORD_Class,
+                                                  KEY_EVENT_RECORD_Constructor);
+                env->SetBooleanField(keyEvent, KEY_EVENT_RECORD_bKeyDown, buffer[i].Event.KeyEvent.bKeyDown);
+                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wRepeatCount, buffer[i].Event.KeyEvent.wRepeatCount);
+                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wVirtualKeyCode, buffer[i].Event.KeyEvent.wVirtualKeyCode);
+                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wVirtualScanCode, buffer[i].Event.KeyEvent.wVirtualScanCode);
+
+                jobject unionChar = env->NewObject(UnionChar_Class,
+                                                   UnionChar_Constructor);
+
+                env->SetIntField(unionChar, UnionChar_UnicodeChar, buffer[i].Event.KeyEvent.uChar.UnicodeChar);
+
+                env->SetObjectField(keyEvent, KEY_EVENT_RECORD_uChar, unionChar);
+
+                env->SetIntField(keyEvent, KEY_EVENT_RECORD_dwControlKeyState, buffer[i].Event.KeyEvent.dwControlKeyState);
+
+                jobject event = env->NewObject(EventUnion_Class,
+                                               EventUnion_Constructor);
+
+                env->SetObjectField(event, EventUnion_KeyEvent, keyEvent);
+                env->SetObjectField(record, INPUT_RECORD_Event, event);
+                break;
+            }
+            case MOUSE_EVENT: {
+                jobject mouseEvent = env->NewObject(MOUSE_EVENT_RECORD_Class,
+                                                    MOUSE_EVENT_RECORD_Constructor);
+
+                jobject dwMousePosition = env->NewObject(COORD_Class,
+                                                         COORD_Constructor);
+                env->SetIntField(dwMousePosition, COORD_X, buffer[i].Event.MouseEvent.dwMousePosition.X);
+                env->SetIntField(dwMousePosition, COORD_Y, buffer[i].Event.MouseEvent.dwMousePosition.Y);
+                env->SetObjectField(mouseEvent, MOUSE_EVENT_RECORD_dwMousePosition, dwMousePosition);
+                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwButtonState, buffer[i].Event.MouseEvent.dwButtonState);
+                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwControlKeyState, buffer[i].Event.MouseEvent.dwControlKeyState);
+                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwEventFlags, buffer[i].Event.MouseEvent.dwEventFlags);
+
+                jobject event = env->NewObject(EventUnion_Class,
+                                               EventUnion_Constructor);
+
+                env->SetObjectField(event, EventUnion_MouseEvent, mouseEvent);
+                env->SetObjectField(record, INPUT_RECORD_Event, event);
+                break;
+            }
+            case WINDOW_BUFFER_SIZE_EVENT: {
+                jobject windowBufferSize = env->NewObject(WINDOW_BUFFER_SIZE_RECORD_Class,
+                                                          WINDOW_BUFFER_SIZE_RECORD_Constructor);
+
+                jobject dwSize = env->NewObject(COORD_Class,
+                                                COORD_Constructor);
+                env->SetIntField(dwSize, COORD_X, buffer[i].Event.WindowBufferSizeEvent.dwSize.X);
+                env->SetIntField(dwSize, COORD_Y, buffer[i].Event.WindowBufferSizeEvent.dwSize.Y);
+                env->SetObjectField(windowBufferSize, WINDOW_BUFFER_SIZE_RECORD_dwSize, dwSize);
+
+                jobject event = env->NewObject(EventUnion_Class,
+                                               EventUnion_Constructor);
+
+                env->SetObjectField(event, EventUnion_WindowBufferSizeEvent, windowBufferSize);
+                env->SetObjectField(record, INPUT_RECORD_Event, event);
+                break;
+            }
+            case MENU_EVENT: {
+                jobject menuEvent = env->NewObject(MENU_EVENT_RECORD_Class,
+                                                          MENU_EVENT_RECORD_Constructor);
+
+                env->SetBooleanField(menuEvent, MENU_EVENT_RECORD_dwCommandId, buffer[i].Event.MenuEvent.dwCommandId);
+
+                jobject event = env->NewObject(EventUnion_Class,
+                                               EventUnion_Constructor);
+
+                env->SetObjectField(event, EventUnion_MenuEvent, menuEvent);
+                env->SetObjectField(record, INPUT_RECORD_Event, event);
+                break;
+            }
+            case FOCUS_EVENT: {
+                jobject focusEvent = env->NewObject(FOCUS_EVENT_RECORD_Class,
+                                                    FOCUS_EVENT_RECORD_Constructor);
+
+                env->SetIntField(focusEvent, FOCUS_EVENT_RECORD_bSetFocus, buffer[i].Event.FocusEvent.bSetFocus);
+
+                jobject event = env->NewObject(EventUnion_Class,
+                                               EventUnion_Constructor);
+
+                env->SetObjectField(event, EventUnion_FocusEvent, focusEvent);
+                env->SetObjectField(record, INPUT_RECORD_Event, event);
+                break;
+            }
+        }
+        env->SetObjectArrayElement(out_lpBuffer, i, record);
+    }
+    env->SetIntField(out_lpNumberOfEventsRead, intByReferenceValue, numberOfEventsRead);
+    delete buffer;
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    SetConsoleCursorPosition
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleCursorPosition
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobject in_dwCursorPosition) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    COORD coord;
+    coord.X = (SHORT) env->GetLongField(in_dwCursorPosition, COORD_X);
+    coord.Y = (SHORT) env->GetLongField(in_dwCursorPosition, COORD_Y);
+    if (!SetConsoleCursorPosition(h, coord)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return;
+    }
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    SetConsoleMode
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;I)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleMode
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jint in_dwMode) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    if (!SetConsoleMode(h, in_dwMode)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    SetConsoleTextAttribute
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;S)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleTextAttribute
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jshort in_wAttributes) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    if (!SetConsoleTextAttribute(h, in_wAttributes)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    SetConsoleTitle
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleTitle
+  (JNIEnv *env, jobject, jstring in_lpConsoleTitle) {
+    const char *chars = env->GetStringUTFChars(in_lpConsoleTitle, NULL);
+    if (!SetConsoleTitle(chars)) {
+        env->ReleaseStringUTFChars(in_lpConsoleTitle, chars);
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+    env->ReleaseStringUTFChars(in_lpConsoleTitle, chars);
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    WriteConsoleW
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;[CILjdk/internal/org/jline/terminal/impl/jna/win/IntByReference;Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_WriteConsoleW
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jcharArray in_lpBuffer, jint in_nNumberOfCharsToWrite, jobject out_lpNumberOfCharsWritten, jobject) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+    jchar *chars = new jchar[in_nNumberOfCharsToWrite];
+    env->GetCharArrayRegion(in_lpBuffer, 0, in_nNumberOfCharsToWrite, chars);
+    DWORD written;
+    if (!WriteConsoleW(h, chars, in_nNumberOfCharsToWrite, &written, NULL)) {
+        delete chars;
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+
+    env->SetIntField(out_lpNumberOfCharsWritten, intByReferenceValue, written);
+    delete chars;
+}
+
+/*
+ * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+ * Method:    ScrollConsoleScreenBuffer
+ * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/SMALL_RECT;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/SMALL_RECT;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/CHAR_INFO;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_ScrollConsoleScreenBuffer
+  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobject in_lpScrollRectangle, jobject in_lpClipRectangle, jobject in_dwDestinationOrigin, jobject in_lpFill) {
+    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
+
+    SMALL_RECT scrollRectangle;
+    scrollRectangle.Left = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Left);
+    scrollRectangle.Top = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Top);
+    scrollRectangle.Right = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Right);
+    scrollRectangle.Bottom = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Bottom);
+
+    SMALL_RECT clipRectangle;
+    clipRectangle.Left = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Left);
+    clipRectangle.Top = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Top);
+    clipRectangle.Right = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Right);
+    clipRectangle.Bottom = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Bottom);
+
+    COORD destinationOrigin;
+    destinationOrigin.X = (SHORT) env->GetLongField(in_dwDestinationOrigin, COORD_X);
+    destinationOrigin.Y = (SHORT) env->GetLongField(in_dwDestinationOrigin, COORD_Y);
+
+    CHAR_INFO charInfo;
+    charInfo.Char.UnicodeChar = env->GetCharField(env->GetObjectField(in_lpFill, CHAR_INFO_uChar), UnionChar_UnicodeChar);
+    charInfo.Attributes = env->GetShortField(in_lpFill, CHAR_INFO_Attributes);
+
+    if (!ScrollConsoleScreenBuffer(h, &scrollRectangle, &clipRectangle, destinationOrigin, &charInfo)) {
+        DWORD error = GetLastError();
+        jobject exc = env->NewObject(lastErrorExceptionClass,
+                                     lastErrorExceptionConstructor,
+                                     (jlong) error);
+        env->Throw((jthrowable) exc);
+        return ;
+    }
+}
--- a/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jdk_internal_jline_WindowsTerminal.h"
-
-#include <stdlib.h>
-#include <Wincon.h>
-#include <Winuser.h>
-
-static jclass recordClass;
-static jmethodID recordConstructor;
-static jclass bufferStateClass;
-static jmethodID bufferStateConstructor;
-
-JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_initIDs
-  (JNIEnv *env, jclass) {
-    jclass cls = env->FindClass("jdk/internal/jline/WindowsTerminal$KEY_EVENT_RECORD");
-    CHECK_NULL(cls);
-    recordClass = (jclass) env->NewGlobalRef(cls);
-    CHECK_NULL(recordClass);
-    recordConstructor = env->GetMethodID(cls, "<init>", "(ZCIII)V");
-    CHECK_NULL(recordConstructor);
-    cls = env->FindClass("jdk/internal/jline/extra/AnsiInterpretingOutputStream$BufferState");
-    CHECK_NULL(cls);
-    bufferStateClass = (jclass) env->NewGlobalRef(cls);
-    CHECK_NULL(bufferStateClass);
-    bufferStateConstructor = env->GetMethodID(cls, "<init>", "(IIII)V");
-    CHECK_NULL(bufferStateConstructor);
-}
-
-JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleMode
-  (JNIEnv *, jobject) {
-    HANDLE hStdIn;
-    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return -1;
-    }
-    DWORD fdwMode;
-    if (! GetConsoleMode(hStdIn, &fdwMode)) {
-        return -1;
-    }
-    return fdwMode;
-}
-
-JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_setConsoleMode
-  (JNIEnv *, jobject, jint mode) {
-    HANDLE hStdIn;
-    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return ;
-    }
-    DWORD fdwMode = mode;
-    SetConsoleMode(hStdIn, fdwMode);
-}
-
-JNIEXPORT jobject JNICALL Java_jdk_internal_jline_WindowsTerminal_readKeyEvent
-  (JNIEnv *env, jobject) {
-    HANDLE hStdIn;
-    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return NULL;
-    }
-    INPUT_RECORD record;
-    DWORD n;
-    while (TRUE) {
-        if (ReadConsoleInputW(hStdIn, &record, 1, &n) == 0) {
-            return NULL;
-        }
-        if (record.EventType == KEY_EVENT) {
-            return env->NewObject(recordClass,
-                                  recordConstructor,
-                                  record.Event.KeyEvent.bKeyDown,
-                                  record.Event.KeyEvent.uChar.UnicodeChar,
-                                  record.Event.KeyEvent.dwControlKeyState,
-                                  record.Event.KeyEvent.wVirtualKeyCode,
-                                  record.Event.KeyEvent.wRepeatCount);
-        }
-        continue;
-    }
-}
-
-JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleOutputCodepage
-  (JNIEnv *, jobject) {
-    return GetConsoleOutputCP();
-}
-
-JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth
-  (JNIEnv *, jobject) {
-    HANDLE hStdOut;
-    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return -1;
-    }
-    CONSOLE_SCREEN_BUFFER_INFO info;
-    if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
-        return -1;
-    }
-    return info.srWindow.Right - info.srWindow.Left;
-}
-
-JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalHeight
-  (JNIEnv *, jobject) {
-    HANDLE hStdOut;
-    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return -1;
-    }
-    CONSOLE_SCREEN_BUFFER_INFO info;
-    if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
-        return -1;
-    }
-    return info.srWindow.Bottom - info.srWindow.Top + 1;
-}
-
-JNIEXPORT jobject JNICALL Java_jdk_internal_jline_WindowsTerminal_getBufferState
-  (JNIEnv *env, jobject) {
-    HANDLE hStdOut;
-    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return NULL;
-    }
-    CONSOLE_SCREEN_BUFFER_INFO info;
-    if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
-        return NULL;
-    }
-    return env->NewObject(bufferStateClass,
-                          bufferStateConstructor,
-                          info.dwCursorPosition.X,
-                          info.dwCursorPosition.Y,
-                          info.dwSize.X,
-                          info.dwSize.Y);
-}
-
-JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_setCursorPosition
-  (JNIEnv *, jobject, jint x, jint y) {
-    HANDLE hStdOut;
-    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return ;
-    }
-    COORD coord = {(SHORT) x, (SHORT) y};
-    SetConsoleCursorPosition(hStdOut, coord);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -61,20 +61,6 @@
     <T> T asObject(Class<T> type, JavaConstant constant);
 
     /**
-     * Gets the object reference a given constant represents if it is of a given type. The constant
-     * must have kind {@link JavaKind#Object}.
-     *
-     * @param type the expected type of the object represented by {@code constant}. If the object is
-     *            required to be of this type, then wrap the call to this method in
-     *            {@link Objects#requireNonNull(Object)}.
-     * @param constant an object constant
-     * @return the object value represented by {@code constant} if it is an
-     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
-     *         {@code null}
-     */
-    Object asObject(ResolvedJavaType type, JavaConstant constant);
-
-    /**
      * Creates a boxed constant for the given kind from an Object. The object needs to be of the
      * Java boxed type corresponding to the kind.
      *
@@ -82,7 +68,13 @@
      * @param value the Java boxed value: a {@link Byte} instance for {@link JavaKind#Byte}, etc.
      * @return the boxed copy of {@code value}
      */
-    JavaConstant forBoxed(JavaKind kind, Object value);
+    default JavaConstant forBoxed(JavaKind kind, Object value) {
+        if (kind == JavaKind.Object) {
+            return forObject(value);
+        } else {
+            return JavaConstant.forBoxedPrimitive(value);
+        }
+    }
 
     /**
      * Gets the value to bind to an injected parameter in a node intrinsic.
@@ -97,7 +89,8 @@
      * Get the original Java class corresponding to a {@link ResolvedJavaType}.
      *
      * @param type the type for which the original Java class is requested
-     * @return the original Java class corresponding to the {@code type} parameter
+     * @return the original Java class corresponding to {@code type} or {@code null} if this object
+     *         cannot map {@link ResolvedJavaType} instances to {@link Class} instances
      */
     Class<?> originalClass(ResolvedJavaType type);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/Fields.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/Fields.java	Wed Dec 12 08:38:45 2018 -0500
@@ -326,7 +326,7 @@
 
     public void appendFields(StringBuilder sb) {
         for (int i = 0; i < offsets.length; i++) {
-            sb.append(i == 0 ? "" : ", ").append(getName(i)).append('@').append(offsets[i]);
+            sb.append(i == 0 ? "" : ", ").append(getDeclaringClass(i).getSimpleName()).append('.').append(getName(i)).append('@').append(offsets[i]);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,6 +24,8 @@
 
 package org.graalvm.compiler.core.common.spi;
 
+import java.util.Arrays;
+
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
@@ -46,9 +48,26 @@
 
     protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) {
         try {
-            this.stringValueField = metaAccess.lookupJavaField(String.class.getDeclaredField("value"));
-            this.stringHashField = metaAccess.lookupJavaField(String.class.getDeclaredField("hash"));
-        } catch (NoSuchFieldException | SecurityException e) {
+            ResolvedJavaType stringType = metaAccess.lookupJavaType(String.class);
+            ResolvedJavaField[] stringFields = stringType.getInstanceFields(false);
+            ResolvedJavaField valueField = null;
+            ResolvedJavaField hashField = null;
+            for (ResolvedJavaField field : stringFields) {
+                if (field.getName().equals("value")) {
+                    valueField = field;
+                } else if (field.getName().equals("hash")) {
+                    hashField = field;
+                }
+            }
+            if (valueField == null) {
+                throw new GraalError("missing field value " + Arrays.toString(stringFields));
+            }
+            if (hashField == null) {
+                throw new GraalError("missing field hash " + Arrays.toString(stringFields));
+            }
+            stringValueField = valueField;
+            stringHashField = hashField;
+        } catch (SecurityException e) {
             throw new GraalError(e);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -31,9 +31,12 @@
 import org.graalvm.compiler.asm.amd64.AMD64Address;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -46,6 +49,7 @@
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.lir.jtt.LIRTest;
 import org.graalvm.compiler.lir.jtt.LIRTestSpecification;
+import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@@ -67,7 +71,6 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Value;
-import org.graalvm.compiler.hotspot.HotSpotBackend;
 
 public class StubAVXTest extends LIRTest {
 
@@ -183,10 +186,16 @@
         }
 
         @Override
-        protected BytecodeProvider getReplacementsBytecodeProvider() {
+        protected void registerSnippet() {
+        }
+
+        @Override
+        protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) {
+            // Build the snippet graph directly since snippet registration is closed at this point.
             ReplacementsImpl d = (ReplacementsImpl) providers.getReplacements();
-            MetaAccessProvider metaAccess = d.providers.getMetaAccess();
-            return new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
+            MetaAccessProvider metaAccess = d.getProviders().getMetaAccess();
+            BytecodeProvider bytecodes = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
+            return d.makeGraph(debug, bytecodes, method, args, null, false, null);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Dec 12 08:38:45 2018 -0500
@@ -150,6 +150,7 @@
             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
                             snippetReflection, wordTypes,
                             plugins);
+            replacements.setProviders(providers);
         }
         try (InitTimer rt = timer("instantiate backend")) {
             return createBackend(config, graalRuntime, providers);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Wed Dec 12 08:38:45 2018 -0500
@@ -410,7 +410,6 @@
                                     "java/lang/StringLatin1.compareToUTF16([B[B)I",
                                     "java/lang/StringUTF16.compareTo([B[B)I",
                                     "java/lang/StringUTF16.compareToLatin1([B[B)I",
-                                    "java/lang/Thread.onSpinWait()V",
                                     "jdk/internal/misc/Unsafe.getAndAddInt(Ljava/lang/Object;JI)I",
                                     "jdk/internal/misc/Unsafe.getAndAddLong(Ljava/lang/Object;JJ)J",
                                     "jdk/internal/misc/Unsafe.getAndSetInt(Ljava/lang/Object;JI)I",
@@ -418,6 +417,7 @@
                                     "jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
                 }
                 add(toBeInvestigated,
+                                "java/lang/Thread.onSpinWait()V",
                                 "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
                                 "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
                                 "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -55,6 +55,11 @@
         public int hashCode() {
             return clazz.hashCode();
         }
+
+        @Override
+        public String toString() {
+            return "Wrapper-" + clazz;
+        }
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,13 +24,14 @@
 
 package org.graalvm.compiler.hotspot.test;
 
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset;
 
 import java.lang.ref.WeakReference;
 
+import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
@@ -38,6 +39,8 @@
 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
 import org.graalvm.compiler.nodes.memory.ReadNode;
 import org.graalvm.compiler.nodes.memory.WriteNode;
@@ -51,6 +54,7 @@
 import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.phases.tiers.MidTierContext;
+import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -71,7 +75,6 @@
 public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
 
     private final GraalHotSpotVMConfig config = runtime().getVMConfig();
-    private static final long referentOffset = referentOffset();
 
     public static class Container {
 
@@ -167,8 +170,20 @@
         testHelper("test5Snippet", config.useG1GC ? 1 : 0);
     }
 
+    @Override
+    protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
+        NodeIntrinsicPluginFactory.InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
+        new PluginFactory_WriteBarrierAdditionTest().registerPlugins(invocationPlugins, injection);
+        super.registerInvocationPlugins(invocationPlugins);
+    }
+
+    @Fold
+    public static boolean useCompressedOops(@Fold.InjectedParameter GraalHotSpotVMConfig config) {
+        return config.useCompressedOops;
+    }
+
     public static Object test5Snippet() throws Exception {
-        return UNSAFE.getObject(wr, config(null).useCompressedOops ? 12L : 16L);
+        return UNSAFE.getObject(wr, useCompressedOops(GraalHotSpotVMConfigBase.INJECTED_VMCONFIG) ? 12L : 16L);
     }
 
     /**
@@ -177,7 +192,7 @@
      */
     @Test
     public void test6() throws Exception {
-        test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(referentOffset), null);
+        test2("testUnsafeLoad", UNSAFE, wr, Long.valueOf(referentOffset(getMetaAccess())), null);
     }
 
     /**
@@ -186,7 +201,7 @@
      */
     @Test
     public void test7() throws Exception {
-        test2("testUnsafeLoad", UNSAFE, con, Long.valueOf(referentOffset), null);
+        test2("testUnsafeLoad", UNSAFE, con, Long.valueOf(referentOffset(getMetaAccess())), null);
     }
 
     /**
@@ -299,7 +314,7 @@
                     Assert.assertTrue(read.getAddress() instanceof OffsetAddressNode);
                     JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant();
                     Assert.assertNotNull(constDisp);
-                    Assert.assertEquals(referentOffset, constDisp.asLong());
+                    Assert.assertEquals(referentOffset(getMetaAccess()), constDisp.asLong());
                     Assert.assertTrue(config.useG1GC);
                     Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType());
                     Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java	Wed Dec 12 08:38:45 2018 -0500
@@ -29,6 +29,8 @@
 
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
+import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
@@ -71,6 +73,8 @@
      */
     public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
     public static final MetaAccessProvider INJECTED_METAACCESS = null;
+    public static final OptionValues INJECTED_OPTIONVALUES = null;
+    public static final IntrinsicContext INJECTED_INTRINSIC_CONTEXT = null;
 
     public final String osName = getHostOSName();
     public final String osArch = getHostArchitectureName();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Wed Dec 12 08:38:45 2018 -0500
@@ -36,8 +36,6 @@
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
-import java.util.stream.Stream;
-import java.util.stream.Stream.Builder;
 
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.Snippet;
@@ -113,13 +111,13 @@
         byte[] dataSection = new byte[data.getSectionSize()];
 
         ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
-        Builder<DataPatch> patchBuilder = Stream.builder();
+        List<DataPatch> patches = new ArrayList<>();
         data.buildDataSection(buffer, (position, vmConstant) -> {
-            patchBuilder.accept(new DataPatch(position, new ConstantReference(vmConstant)));
+            patches.add(new DataPatch(position, new ConstantReference(vmConstant)));
         });
 
         int dataSectionAlignment = data.getSectionAlignment();
-        DataPatch[] dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]);
+        DataPatch[] dataSectionPatches = patches.toArray(new DataPatch[patches.size()]);
 
         int totalFrameSize = compResult.getTotalFrameSize();
         StackSlot customStackArea = compResult.getCustomStackArea();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Wed Dec 12 08:38:45 2018 -0500
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Description;
@@ -328,8 +329,12 @@
             return (T) this;
         } else if (clazz == SnippetReflectionProvider.class) {
             return (T) getHostProviders().getSnippetReflection();
+        } else if (clazz == GraalHotSpotVMConfig.class) {
+            return (T) getVMConfig();
         } else if (clazz == StampProvider.class) {
             return (T) getHostProviders().getStampProvider();
+        } else if (ForeignCallsProvider.class.isAssignableFrom(clazz)) {
+            return (T) getHostProviders().getForeignCalls();
         }
         return null;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java	Wed Dec 12 08:38:45 2018 -0500
@@ -92,6 +92,7 @@
             Iterable<DebugHandlersFactory> factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()));
             lowerer.initialize(options, factories, providers, config);
         }
+        providers.getReplacements().closeSnippetRegistration();
     }
 
     protected CallingConvention makeCallingConvention(StructuredGraph graph, Stub stub) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,7 +26,9 @@
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin;
 import org.graalvm.compiler.hotspot.word.HotSpotOperation;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@@ -40,13 +42,25 @@
  * them.
  */
 public class HotSpotReplacementsImpl extends ReplacementsImpl {
-
     public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
         super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
     }
 
     @Override
-    protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) {
-        return method.getAnnotation(HotSpotOperation.class) != null || super.hasGenericInvocationPluginAnnotation(method);
+    public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
+        return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method);
+    }
+
+    private boolean snippetRegistrationClosed;
+
+    @Override
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
+        assert !snippetRegistrationClosed;
+        super.registerSnippet(method, original, receiver, trackNodeSourcePosition);
+    }
+
+    @Override
+    public void closeSnippetRegistration() {
+        snippetRegistrationClosed = true;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -59,14 +59,11 @@
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode;
-import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
-import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
 import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.nodes.GetObjectAddressNode;
 import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
 import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode;
 import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode;
@@ -90,20 +87,22 @@
 import org.graalvm.compiler.hotspot.replacements.LoadExceptionObjectSnippets;
 import org.graalvm.compiler.hotspot.replacements.MonitorSnippets;
 import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
+import org.graalvm.compiler.hotspot.replacements.ObjectCloneSnippets;
 import org.graalvm.compiler.hotspot.replacements.StringToBytesSnippets;
 import org.graalvm.compiler.hotspot.replacements.UnsafeLoadSnippets;
 import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets;
 import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
-import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
-import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets;
-import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode;
+import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
 import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets;
+import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets;
 import org.graalvm.compiler.hotspot.word.KlassPointer;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
 import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
+import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.FixedNode;
+import org.graalvm.compiler.nodes.GetObjectAddressNode;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.LogicNode;
 import org.graalvm.compiler.nodes.LoweredCallTargetNode;
@@ -159,6 +158,9 @@
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode;
 import org.graalvm.compiler.replacements.nodes.AssertionNode;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
@@ -196,6 +198,9 @@
     protected ResolveConstantSnippets.Templates resolveConstantSnippets;
     protected ProfileSnippets.Templates profileSnippets;
 
+    protected ObjectCloneSnippets.Templates objectCloneSnippets;
+    protected ForeignCallSnippets.Templates foreignCallSnippets;
+
     public DefaultHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
                     HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
         super(metaAccess, foreignCalls, target, runtime.getVMConfig().useCompressedOops);
@@ -221,6 +226,8 @@
         hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
         resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
         profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
+        objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
+        foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
     }
 
     public MonitorSnippets.Templates getMonitorSnippets() {
@@ -286,7 +293,7 @@
             } else if (n instanceof DynamicNewInstanceNode) {
                 DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n;
                 if (newInstanceNode.getClassClass() == null) {
-                    JavaConstant classClassMirror = constantReflection.forObject(Class.class);
+                    JavaConstant classClassMirror = constantReflection.asJavaClass(metaAccess.lookupJavaType(Class.class));
                     ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph);
                     newInstanceNode.setClassClass(classClass);
                 }
@@ -300,7 +307,7 @@
             } else if (n instanceof DynamicNewArrayNode) {
                 DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n;
                 if (dynamicNewArrayNode.getVoidClass() == null) {
-                    JavaConstant voidClassMirror = constantReflection.forObject(void.class);
+                    JavaConstant voidClassMirror = constantReflection.asJavaClass(metaAccess.lookupJavaType(void.class));
                     ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph);
                     dynamicNewArrayNode.setVoidClass(voidClass);
                 }
@@ -770,8 +777,7 @@
 
     @Override
     public int fieldOffset(ResolvedJavaField f) {
-        HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
-        return field.getOffset();
+        return f.getOffset();
     }
 
     @Override
@@ -783,4 +789,14 @@
     protected final JavaKind getStorageKind(ResolvedJavaField field) {
         return field.getJavaKind();
     }
+
+    @Override
+    public ObjectCloneSnippets.Templates getObjectCloneSnippets() {
+        return objectCloneSnippets;
+    }
+
+    @Override
+    public ForeignCallSnippets.Templates getForeignCallSnippets() {
+        return foreignCallSnippets;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Dec 12 08:38:45 2018 -0500
@@ -34,8 +34,6 @@
 import java.lang.invoke.MutableCallSite;
 import java.lang.invoke.VolatileCallSite;
 import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.math.BigInteger;
 import java.util.zip.CRC32;
 
@@ -45,7 +43,6 @@
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
 import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
@@ -66,7 +63,6 @@
 import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
 import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
 import org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions;
-import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
@@ -95,6 +91,7 @@
 import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
 import org.graalvm.compiler.replacements.ReplacementsImpl;
 import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
 import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.graalvm.compiler.word.WordOperationPlugin;
 import org.graalvm.compiler.word.WordTypes;
@@ -458,18 +455,8 @@
         if (config.useMultiplyToLenIntrinsic()) {
             assert config.multiplyToLen != 0L;
             if (Java8OrEarlier) {
-                try {
-                    Method m = BigInteger.class.getDeclaredMethod("multiplyToLen", int[].class, int.class, int[].class, int.class, int[].class);
-                    if (Modifier.isStatic(m.getModifiers())) {
-                        r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
-                                        int[].class);
-                    } else {
-                        r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", Receiver.class, int[].class, int.class, int[].class, int.class,
-                                        int[].class);
-                    }
-                } catch (NoSuchMethodException | SecurityException e) {
-                    throw new GraalError(e);
-                }
+                r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
+                                int[].class);
             } else {
                 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
                                 int[].class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,6 +26,8 @@
 
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.replacements.ObjectCloneSnippets;
+import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 import org.graalvm.compiler.options.OptionValues;
 
@@ -35,4 +37,8 @@
 public interface HotSpotLoweringProvider extends LoweringProvider {
 
     void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config);
+
+    ObjectCloneSnippets.Templates getObjectCloneSnippets();
+
+    ForeignCallSnippets.Templates getForeignCallSnippets();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,6 +26,7 @@
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
@@ -33,6 +34,7 @@
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
 import org.graalvm.compiler.phases.util.Providers;
 
+import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.MetaAccessProvider;
@@ -90,4 +92,53 @@
     public HotSpotWordTypes getWordTypes() {
         return wordTypes;
     }
+
+    @Override
+    public Providers copyWith(MetaAccessProvider substitution) {
+        return new HotSpotProviders(substitution, getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(CodeCacheProvider substitution) {
+        return new HotSpotProviders(getMetaAccess(), (HotSpotCodeCacheProvider) substitution, getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(),
+                        getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(ConstantReflectionProvider substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(ConstantFieldProvider substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(ForeignCallsProvider substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), (HotSpotForeignCallsProvider) substitution, getLowerer(), getReplacements(),
+                        getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(LoweringProvider substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), substitution, getReplacements(), getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    @Override
+    public Providers copyWith(Replacements substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+    }
+
+    public Providers copyWith(Plugins substitution) {
+        return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
+                        getRegisters(), getSnippetReflection(), getWordTypes(), substitution);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -55,21 +55,15 @@
     }
 
     @Override
-    public Object asObject(ResolvedJavaType type, JavaConstant constant) {
-        if (constant.isNull()) {
-            return null;
-        }
-        HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
-        return hsConstant.asObject(type);
-    }
-
-    @Override
     public <T> T asObject(Class<T> type, JavaConstant constant) {
         if (constant.isNull()) {
             return null;
         }
-        HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
-        return hsConstant.asObject(type);
+        if (constant instanceof HotSpotObjectConstant) {
+            HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
+            return hsConstant.asObject(type);
+        }
+        return null;
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java	Wed Dec 12 08:38:45 2018 -0500
@@ -66,7 +66,7 @@
  * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word
  * operations}.
  */
-class HotSpotWordOperationPlugin extends WordOperationPlugin {
+public class HotSpotWordOperationPlugin extends WordOperationPlugin {
     HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) {
         super(snippetReflection, wordTypes);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java	Wed Dec 12 08:38:45 2018 -0500
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
@@ -70,7 +71,7 @@
     }
 
     @NodeIntrinsic
-    public static native KlassPointer initializeKlass(KlassPointer value, Object string);
+    public static native KlassPointer initializeKlass(KlassPointer value, Word string);
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java	Wed Dec 12 08:38:45 2018 -0500
@@ -43,6 +43,7 @@
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.word.Word;
 
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
@@ -79,10 +80,10 @@
     public static native Object resolveObject(Object value, Object symbol);
 
     @NodeIntrinsic
-    public static native KlassPointer resolveKlass(KlassPointer value, Object symbol);
+    public static native KlassPointer resolveKlass(KlassPointer value, Word symbol);
 
     @NodeIntrinsic
-    public static native KlassPointer resolveKlass(KlassPointer value, Object symbol, @ConstantNodeParameter HotSpotConstantLoadAction action);
+    public static native KlassPointer resolveKlass(KlassPointer value, Word symbol, @ConstantNodeParameter HotSpotConstantLoadAction action);
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java	Wed Dec 12 08:38:45 2018 -0500
@@ -43,6 +43,7 @@
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.word.Word;
 
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.Value;
@@ -67,7 +68,7 @@
     }
 
     @NodeIntrinsic
-    public static native MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint, Object methodDescription);
+    public static native MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint, Word methodDescription);
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,7 +24,6 @@
 
 package org.graalvm.compiler.hotspot.phases;
 
-import static jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
 
 import org.graalvm.compiler.core.common.PermanentBailoutException;
@@ -77,6 +76,7 @@
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
 import jdk.vm.ci.runtime.JVMCICompiler;
 
 public class OnStackReplacementPhase extends Phase {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,18 +24,20 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK;
+import static org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions.aesCryptType;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
 import static org.graalvm.compiler.replacements.ReplacementsUtil.getArrayBaseOffset;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
@@ -43,6 +45,7 @@
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 import jdk.internal.vm.compiler.word.Pointer;
@@ -60,28 +63,20 @@
 @ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt", optional = true)
 public class AESCryptSubstitutions {
 
-    static final long kOffset;
-    static final long lastKeyOffset;
-    static final Class<?> AESCryptClass;
-
     /**
      * The AES block size is a constant 128 bits as defined by the
      * <a href="http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf">standard<a/>.
      */
     static final int AES_BLOCK_SIZE_IN_BYTES = 16;
 
-    static {
-        try {
-            // Need to use the system class loader as com.sun.crypto.provider.AESCrypt
-            // is normally loaded by the extension class loader which is not delegated
-            // to by the JVMCI class loader.
-            ClassLoader cl = ClassLoader.getSystemClassLoader();
-            AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl);
-            kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K"));
-            lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey"));
-        } catch (Exception ex) {
-            throw new GraalError(ex);
-        }
+    @Fold
+    static long kOffset(@Fold.InjectedParameter IntrinsicContext context) {
+        return HotSpotReplacementsUtil.getFieldOffset(aesCryptType(context), "K");
+    }
+
+    @Fold
+    static long lastKeyOffset(@Fold.InjectedParameter IntrinsicContext context) {
+        return HotSpotReplacementsUtil.getFieldOffset(aesCryptType(context), "lastKey");
     }
 
     @MethodSubstitution(isStatic = false)
@@ -123,8 +118,8 @@
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) {
         checkArgs(in, inOffset, out, outOffset);
-        Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass);
-        Object kObject = RawLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any());
+        Object realReceiver = PiNode.piCastNonNull(rcvr, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
+        Object kObject = RawLoadNode.load(realReceiver, kOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
         Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int));
         Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + inOffset));
         Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + outOffset));
@@ -132,7 +127,7 @@
             encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr);
         } else {
             if (withOriginalKey) {
-                Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any());
+                Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
                 Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
                 decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr);
             } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,23 +24,24 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
-import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
+import static org.graalvm.compiler.nodes.PiNode.piCastNonNull;
+import static org.graalvm.compiler.nodes.java.InstanceOfNode.doInstanceof;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
-import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.replacements.ReplacementsUtil;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.LocationIdentity;
@@ -48,6 +49,7 @@
 import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 // JaCoCo Exclude
 
@@ -57,38 +59,17 @@
 @ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
 public class CipherBlockChainingSubstitutions {
 
-    private static final long embeddedCipherOffset;
-    private static final long rOffset;
-    private static final Class<?> cipherBlockChainingClass;
-    private static final Class<?> feedbackCipherClass;
-    static {
-        try {
-            // Need to use the system class loader as com.sun.crypto.provider.FeedbackCipher
-            // is normally loaded by the extension class loader which is not delegated
-            // to by the JVMCI class loader.
-            ClassLoader cl = ClassLoader.getSystemClassLoader();
-
-            feedbackCipherClass = Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl);
-            embeddedCipherOffset = UNSAFE.objectFieldOffset(feedbackCipherClass.getDeclaredField("embeddedCipher"));
-
-            cipherBlockChainingClass = Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl);
-            rOffset = UNSAFE.objectFieldOffset(cipherBlockChainingClass.getDeclaredField("r"));
-        } catch (Exception ex) {
-            throw new GraalError(ex);
-        }
-    }
-
     @Fold
-    static Class<?> getAESCryptClass() {
-        return AESCryptSubstitutions.AESCryptClass;
+    static ResolvedJavaType aesCryptType(@Fold.InjectedParameter IntrinsicContext context) {
+        return HotSpotReplacementsUtil.getType(context, "Lcom/sun/crypto/provider/AESCrypt;");
     }
 
     @MethodSubstitution(isStatic = false)
     static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
             return inLength;
         } else {
@@ -96,12 +77,22 @@
         }
     }
 
+    @Fold
+    static long embeddedCipherOffset(@Fold.InjectedParameter IntrinsicContext context) {
+        return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.getType(context, "Lcom/sun/crypto/provider/FeedbackCipher;"), "embeddedCipher");
+    }
+
+    @Fold
+    static long rOffset(@Fold.InjectedParameter IntrinsicContext intrinsicContext) {
+        return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(intrinsicContext), "r");
+    }
+
     @MethodSubstitution(isStatic = false, value = "implEncrypt")
     static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
             return inLength;
         } else {
@@ -111,10 +102,10 @@
 
     @MethodSubstitution(isStatic = false)
     static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
             return inLength;
         } else {
@@ -124,10 +115,10 @@
 
     @MethodSubstitution(isStatic = false)
     static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
             return inLength;
         } else {
@@ -141,10 +132,10 @@
      */
     @MethodSubstitution(isStatic = false, value = "decrypt")
     static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
             return inLength;
         } else {
@@ -157,10 +148,10 @@
      */
     @MethodSubstitution(isStatic = false, value = "implDecrypt")
     static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
-        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
-            Object aesCipher = getAESCryptClass().cast(embeddedCipher);
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        if (in != out && doInstanceof(aesCryptType(INJECTED_INTRINSIC_CONTEXT), embeddedCipher)) {
+            Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
             crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
             return inLength;
         } else {
@@ -170,10 +161,10 @@
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) {
         AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset);
-        Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
-        Object aesCipher = getAESCryptClass().cast(embeddedCipher);
-        Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any());
-        Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any());
+        Object realReceiver = piCastNonNull(rcvr, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object aesCipher = piCastNonNull(embeddedCipher, aesCryptType(INJECTED_INTRINSIC_CONTEXT));
+        Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
+        Object rObject = RawLoadNode.load(realReceiver, rOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
         Pointer kAddr = Word.objectToTrackedPointer(kObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int));
         Pointer rAddr = Word.objectToTrackedPointer(rObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
         Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + inOffset));
@@ -182,7 +173,7 @@
             encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
         } else {
             if (withOriginalKey) {
-                Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any());
+                Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
                 Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte));
                 decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr);
             } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Dec 12 08:38:45 2018 -0500
@@ -27,7 +27,8 @@
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP;
-import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
+
+import java.lang.ref.Reference;
 
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
@@ -40,10 +41,10 @@
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.hotspot.word.KlassPointer;
 import org.graalvm.compiler.nodes.CanonicalizableLocation;
 import org.graalvm.compiler.nodes.CompressionNode;
+import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.NodeView;
@@ -52,6 +53,7 @@
 import org.graalvm.compiler.nodes.extended.LoadHubNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.nodes.extended.StoreHubNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.memory.Access;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
@@ -70,7 +72,10 @@
 import jdk.vm.ci.meta.Assumptions;
 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.UnresolvedJavaType;
 
 //JaCoCo Exclude
 
@@ -133,6 +138,28 @@
         }
     }
 
+    public static ResolvedJavaType methodHolderClass(@Fold.InjectedParameter IntrinsicContext context) {
+        return context.getOriginalMethod().getDeclaringClass();
+    }
+
+    static ResolvedJavaType getType(@Fold.InjectedParameter IntrinsicContext context, String typeName) {
+        try {
+            UnresolvedJavaType unresolved = UnresolvedJavaType.create(typeName);
+            return unresolved.resolve(methodHolderClass(context));
+        } catch (LinkageError e) {
+            throw new GraalError(e);
+        }
+    }
+
+    static int getFieldOffset(ResolvedJavaType type, String fieldName) {
+        for (ResolvedJavaField field : type.getInstanceFields(true)) {
+            if (field.getName().equals(fieldName)) {
+                return field.getOffset();
+            }
+        }
+        throw new GraalError("missing field " + fieldName);
+    }
+
     public static HotSpotJVMCIRuntime runtime() {
         return HotSpotJVMCIRuntime.runtime();
     }
@@ -143,9 +170,8 @@
     }
 
     @Fold
-    public static GraalHotSpotVMConfig config(@InjectedParameter GraalHotSpotVMConfig config) {
-        assert config != null;
-        return config;
+    public static int klassLayoutHelperNeutralValue(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.klassLayoutHelperNeutralValue;
     }
 
     @Fold
@@ -199,13 +225,6 @@
         return config.pendingExceptionOffset;
     }
 
-    public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
-
-    @Fold
-    static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.threadObjectResultOffset;
-    }
-
     /**
      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
      */
@@ -262,17 +281,6 @@
         return thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
     }
 
-    /**
-     * Gets and clears the object result from a runtime call stored in a thread local.
-     *
-     * @return the object that was in the thread local
-     */
-    public static Object getAndClearObjectResult(Word thread) {
-        Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION);
-        thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION);
-        return result;
-    }
-
     /*
      * As far as Java code is concerned this can be considered immutable: it is set just after the
      * JavaThread is created, before it is published. After that, it is never changed.
@@ -307,8 +315,8 @@
     }
 
     @Fold
-    public static int pageSize() {
-        return UNSAFE.pageSize();
+    public static int pageSize(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.vmPageSize;
     }
 
     public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
@@ -348,6 +356,56 @@
         }
     };
 
+    @Fold
+    public static int allocatePrefetchStyle(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.allocatePrefetchStyle;
+    }
+
+    @Fold
+    public static int allocatePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.allocatePrefetchLines;
+    }
+
+    @Fold
+    public static int allocatePrefetchDistance(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.allocatePrefetchDistance;
+    }
+
+    @Fold
+    public static int allocateInstancePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.allocateInstancePrefetchLines;
+    }
+
+    @Fold
+    public static int allocatePrefetchStepSize(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.allocatePrefetchStepSize;
+    }
+
+    @Fold
+    public static int invocationCounterIncrement(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.invocationCounterIncrement;
+    }
+
+    @Fold
+    public static int invocationCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.invocationCounterOffset;
+    }
+
+    @Fold
+    public static int backedgeCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.backedgeCounterOffset;
+    }
+
+    @Fold
+    public static int invocationCounterShift(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.invocationCounterShift;
+    }
+
+    @Fold
+    public static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.stackBias;
+    }
+
     @NodeIntrinsic(value = KlassLayoutHelperNode.class)
     public static native int readLayoutHelper(KlassPointer object);
 
@@ -365,7 +423,7 @@
          * sure these are still ints and haven't changed.
          */
         final int layoutHelper = readLayoutHelper(klassNonNull);
-        final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue;
+        final int layoutHelperNeutralValue = klassLayoutHelperNeutralValue(INJECTED_VMCONFIG);
         return (layoutHelper < layoutHelperNeutralValue);
     }
 
@@ -518,16 +576,16 @@
      * Idiom for making {@link GraalHotSpotVMConfig} a constant.
      */
     @Fold
-    public static GraalHotSpotVMConfig getConfig(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config;
+    public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.objectAlignment;
     }
 
     /**
-     * Calls {@link #arrayAllocationSize(int, int, int, GraalHotSpotVMConfig)} using an injected VM
-     * configuration object.
+     * Calls {@link #arrayAllocationSize(int, int, int, int)} using an injected VM configuration
+     * object.
      */
     public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) {
-        return arrayAllocationSize(length, headerSize, log2ElementSize, getConfig(INJECTED_VMCONFIG));
+        return arrayAllocationSize(length, headerSize, log2ElementSize, objectAlignment(INJECTED_VMCONFIG));
     }
 
     /**
@@ -538,12 +596,11 @@
      * @param length the number of elements in the array
      * @param headerSize the size of the array header
      * @param log2ElementSize log2 of the size of an element in the array
-     * @param config the VM configuration providing the
-     *            {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment requirement}
+     * @param alignment the {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment
+     *            requirement}
      * @return the size of the memory chunk
      */
-    public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, GraalHotSpotVMConfig config) {
-        int alignment = config.objectAlignment;
+    public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, int alignment) {
         int size = (length << log2ElementSize) + headerSize + (alignment - 1);
         int mask = ~(alignment - 1);
         return size & mask;
@@ -786,12 +843,8 @@
     }
 
     @Fold
-    public static long referentOffset() {
-        try {
-            return UNSAFE.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent"));
-        } catch (Exception e) {
-            throw new GraalError(e);
-        }
+    public static long referentOffset(@InjectedParameter MetaAccessProvider metaAccessProvider) {
+        return getFieldOffset(metaAccessProvider.lookupJavaType(Reference.class), "referent");
     }
 
     public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,7 +26,9 @@
 
 import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
 import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
+import static org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode.mark;
 import static org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode.beginLockScope;
 import static org.graalvm.compiler.hotspot.nodes.EndLockScopeNode.endLockScope;
 import static org.graalvm.compiler.hotspot.nodes.VMErrorNode.vmError;
@@ -40,7 +42,6 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockPattern;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.epochMaskInPlace;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockDisplacedMarkOffset;
@@ -53,6 +54,7 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.stackBias;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedMask;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useBiasedLocking;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop;
@@ -69,7 +71,10 @@
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
+import static org.graalvm.compiler.nodes.extended.MembarNode.memoryBarrier;
 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
+import static jdk.internal.vm.compiler.word.WordFactory.unsigned;
+import static jdk.internal.vm.compiler.word.WordFactory.zero;
 
 import java.util.List;
 
@@ -89,7 +94,6 @@
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
-import org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode;
 import org.graalvm.compiler.hotspot.nodes.CurrentLockNode;
 import org.graalvm.compiler.hotspot.nodes.FastAcquireBiasedLockNode;
 import org.graalvm.compiler.hotspot.nodes.MonitorCounterNode;
@@ -219,13 +223,13 @@
     private static final boolean PROFILE_CONTEXT = false;
 
     @Fold
-    static boolean doProfile(OptionValues options) {
+    static boolean doProfile(@Fold.InjectedParameter OptionValues options) {
         return ProfileMonitors.getValue(options);
     }
 
     @Snippet
     public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister,
-                    @ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
+                    @ConstantParameter boolean trace, @ConstantParameter Counters counters) {
         verifyOop(object);
 
         // Load the mark word - this includes a null-check on object
@@ -238,17 +242,17 @@
         trace(trace, "             lock: 0x%016lx\n", lock);
         trace(trace, "             mark: 0x%016lx\n", mark);
 
-        incCounter(options);
+        incCounter();
 
         if (useBiasedLocking(INJECTED_VMCONFIG)) {
-            if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) {
+            if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, counters)) {
                 return;
             }
             // not biased, fall-through
         }
-        if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
+        if (inlineFastLockSupported() && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
             // Inflated case
-            if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) {
+            if (tryEnterInflated(object, lock, mark, threadRegister, trace, counters)) {
                 return;
             }
         } else {
@@ -266,9 +270,9 @@
             // (address of) the lock slot into the object's mark word.
             Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION);
             if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) {
-                traceObject(trace, "+lock{cas}", object, true, options);
+                traceObject(trace, "+lock{cas}", object, true);
                 counters.lockCas.inc();
-                AcquiredCASLockNode.mark(object);
+                mark(object);
                 return;
             } else {
                 trace(trace, "      currentMark: 0x%016lx\n", currentMark);
@@ -287,16 +291,16 @@
                 //
                 // assuming both the stack pointer and page_size have their least
                 // significant 2 bits cleared and page_size is a power of 2
-                final Word alignedMask = WordFactory.unsigned(wordSize() - 1);
-                final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias);
-                if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) {
+                final Word alignedMask = unsigned(wordSize() - 1);
+                final Word stackPointer = registerAsWord(stackPointerRegister).add(stackBias(INJECTED_VMCONFIG));
+                if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize(INJECTED_VMCONFIG))).equal(0))) {
                     // Recursively locked => write 0 to the lock slot
-                    lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), WordFactory.zero(), DISPLACED_MARK_WORD_LOCATION);
-                    traceObject(trace, "+lock{cas:recursive}", object, true, options);
+                    lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), zero(), DISPLACED_MARK_WORD_LOCATION);
+                    traceObject(trace, "+lock{cas:recursive}", object, true);
                     counters.lockCasRecursive.inc();
                     return;
                 }
-                traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options);
+                traceObject(trace, "+lock{stub:failed-cas/stack}", object, true);
                 counters.lockStubFailedCas.inc();
             }
         }
@@ -304,7 +308,7 @@
         monitorenterStubC(MONITORENTER, object, lock);
     }
 
-    private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
+    private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, Counters counters) {
         // See whether the lock is currently biased toward our thread and
         // whether the epoch is still valid.
         // Note that the runtime guarantees sufficient alignment of JavaThread
@@ -321,7 +325,7 @@
         trace(trace, "              tmp: 0x%016lx\n", tmp);
         if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) {
             // Object is already biased to current thread -> done
-            traceObject(trace, "+lock{bias:existing}", object, true, options);
+            traceObject(trace, "+lock{bias:existing}", object, true);
             counters.lockBiasExisting.inc();
             FastAcquireBiasedLockNode.mark(object);
             return true;
@@ -362,14 +366,14 @@
                     trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
                     if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) {
                         // Object is now biased to current thread -> done
-                        traceObject(trace, "+lock{bias:acquired}", object, true, options);
+                        traceObject(trace, "+lock{bias:acquired}", object, true);
                         counters.lockBiasAcquired.inc();
                         return true;
                     }
                     // If the biasing toward our thread failed, this means that another thread
                     // owns the bias and we need to revoke that bias. The revocation will occur
                     // in the interpreter runtime.
-                    traceObject(trace, "+lock{stub:revoke}", object, true, options);
+                    traceObject(trace, "+lock{stub:revoke}", object, true);
                     counters.lockStubRevoke.inc();
                 } else {
                     // At this point we know the epoch has expired, meaning that the
@@ -382,14 +386,14 @@
                     trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
                     if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) {
                         // Object is now biased to current thread -> done
-                        traceObject(trace, "+lock{bias:transfer}", object, true, options);
+                        traceObject(trace, "+lock{bias:transfer}", object, true);
                         counters.lockBiasTransfer.inc();
                         return true;
                     }
                     // If the biasing toward our thread failed, then another thread
                     // succeeded in biasing it toward itself and we need to revoke that
                     // bias. The revocation will occur in the runtime in the slow case.
-                    traceObject(trace, "+lock{stub:epoch-expired}", object, true, options);
+                    traceObject(trace, "+lock{stub:epoch-expired}", object, true);
                     counters.lockStubEpochExpired.inc();
                 }
                 // slow-path runtime-call
@@ -424,19 +428,19 @@
     }
 
     @Fold
-    public static boolean useFastInflatedLocking(OptionValues options) {
+    public static boolean useFastInflatedLocking(@Fold.InjectedParameter OptionValues options) {
         return SimpleFastInflatedLocking.getValue(options);
     }
 
-    private static boolean inlineFastLockSupported(OptionValues options) {
-        return inlineFastLockSupported(INJECTED_VMCONFIG, options);
+    private static boolean inlineFastLockSupported() {
+        return inlineFastLockSupported(INJECTED_VMCONFIG, INJECTED_OPTIONVALUES);
     }
 
     private static boolean inlineFastLockSupported(GraalHotSpotVMConfig config, OptionValues options) {
         return useFastInflatedLocking(options) && monitorMask(config) >= 0 && objectMonitorOwnerOffset(config) >= 0;
     }
 
-    private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
+    private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, Counters counters) {
         // write non-zero value to lock slot
         lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), lock, DISPLACED_MARK_WORD_LOCATION);
         // mark is a pointer to the ObjectMonitor + monitorMask
@@ -447,15 +451,15 @@
             // it appears unlocked (owner == 0)
             if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, registerAsWord(threadRegister), OBJECT_MONITOR_OWNER_LOCATION))) {
                 // success
-                traceObject(trace, "+lock{inflated:cas}", object, true, options);
+                traceObject(trace, "+lock{inflated:cas}", object, true);
                 counters.inflatedCas.inc();
                 return true;
             } else {
-                traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true, options);
+                traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true);
                 counters.inflatedFailedCas.inc();
             }
         } else {
-            traceObject(trace, "+lock{stub:inflated:owned}", object, true, options);
+            traceObject(trace, "+lock{stub:inflated:owned}", object, true);
             counters.inflatedOwned.inc();
         }
         return false;
@@ -465,22 +469,22 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) {
+    public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
         verifyOop(object);
-        incCounter(options);
+        incCounter();
         if (object == null) {
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
         }
         // BeginLockScope nodes do not read from object so a use of object
         // cannot float about the null check above
         final Word lock = beginLockScope(lockDepth);
-        traceObject(trace, "+lock{stub}", object, true, options);
+        traceObject(trace, "+lock{stub}", object, true);
         monitorenterStubC(MONITORENTER, object, lock);
     }
 
     @Snippet
     public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace,
-                    @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
+                    @ConstantParameter Counters counters) {
         trace(trace, "           object: 0x%016lx\n", Word.objectToTrackedPointer(object));
         final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG));
         if (useBiasedLocking(INJECTED_VMCONFIG)) {
@@ -493,8 +497,8 @@
             trace(trace, "             mark: 0x%016lx\n", mark);
             if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) {
                 endLockScope();
-                decCounter(options);
-                traceObject(trace, "-lock{bias}", object, false, options);
+                decCounter();
+                traceObject(trace, "-lock{bias}", object, false);
                 counters.unlockBias.inc();
                 return;
             }
@@ -508,10 +512,10 @@
 
         if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) {
             // Recursive locking => done
-            traceObject(trace, "-lock{recursive}", object, false, options);
+            traceObject(trace, "-lock{recursive}", object, false);
             counters.unlockCasRecursive.inc();
         } else {
-            if (!tryExitInflated(object, mark, lock, threadRegister, trace, options, counters)) {
+            if (!tryExitInflated(object, mark, lock, threadRegister, trace, counters)) {
                 verifyOop(object);
                 // Test if object's mark word is pointing to the displaced mark word, and if so,
                 // restore
@@ -519,18 +523,18 @@
                 // the displaced mark word, do unlocking via runtime call.
                 Pointer objectPointer = Word.objectToTrackedPointer(object);
                 if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), lock, displacedMark, MARK_WORD_LOCATION))) {
-                    traceObject(trace, "-lock{cas}", object, false, options);
+                    traceObject(trace, "-lock{cas}", object, false);
                     counters.unlockCas.inc();
                 } else {
                     // The object's mark word was not pointing to the displaced header
-                    traceObject(trace, "-lock{stub}", object, false, options);
+                    traceObject(trace, "-lock{stub}", object, false);
                     counters.unlockStub.inc();
                     monitorexitStubC(MONITOREXIT, object, lock);
                 }
             }
         }
         endLockScope();
-        decCounter(options);
+        decCounter();
     }
 
     private static boolean inlineFastUnlockSupported(OptionValues options) {
@@ -542,8 +546,8 @@
                         objectMonitorOwnerOffset(config) >= 0 && objectMonitorRecursionsOffset(config) >= 0;
     }
 
-    private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
-        if (!inlineFastUnlockSupported(options)) {
+    private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, Counters counters) {
+        if (!inlineFastUnlockSupported(INJECTED_OPTIONVALUES)) {
             return false;
         }
         if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
@@ -565,15 +569,15 @@
                     // cxq == 0 && entryList == 0
                     // Nobody is waiting, success
                     // release_store
-                    MembarNode.memoryBarrier(LOAD_STORE | STORE_STORE);
-                    monitor.writeWord(ownerOffset, WordFactory.zero());
-                    traceObject(trace, "-lock{inflated:simple}", object, false, options);
+                    memoryBarrier(LOAD_STORE | STORE_STORE);
+                    monitor.writeWord(ownerOffset, zero());
+                    traceObject(trace, "-lock{inflated:simple}", object, false);
                     counters.unlockInflatedSimple.inc();
                     return true;
                 }
             }
             counters.unlockStubInflated.inc();
-            traceObject(trace, "-lock{stub:inflated}", object, false, options);
+            traceObject(trace, "-lock{stub:inflated}", object, false);
             monitorexitStubC(MONITOREXIT, object, lock);
             return true;
         }
@@ -584,17 +588,17 @@
      * Calls straight out to the monitorexit stub.
      */
     @Snippet
-    public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) {
+    public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
         verifyOop(object);
-        traceObject(trace, "-lock{stub}", object, false, options);
+        traceObject(trace, "-lock{stub}", object, false);
         final Word lock = CurrentLockNode.currentLock(lockDepth);
         monitorexitStubC(MONITOREXIT, object, lock);
         endLockScope();
-        decCounter(options);
+        decCounter();
     }
 
-    public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) {
-        if (doProfile(options)) {
+    public static void traceObject(boolean enabled, String action, Object object, boolean enter) {
+        if (doProfile(INJECTED_OPTIONVALUES)) {
             DynamicCounterNode.counter(enter ? "number of monitor enters" : "number of monitor exits", action, 1, PROFILE_CONTEXT);
         }
         if (enabled) {
@@ -622,20 +626,20 @@
     static native void bkpt(Object object, Word mark, Word tmp, Word value);
 
     @Fold
-    static boolean verifyBalancedMonitors(OptionValues options) {
+    static boolean verifyBalancedMonitors(@Fold.InjectedParameter OptionValues options) {
         return VerifyBalancedMonitors.getValue(options);
     }
 
-    public static void incCounter(OptionValues options) {
-        if (verifyBalancedMonitors(options)) {
+    static void incCounter() {
+        if (verifyBalancedMonitors(INJECTED_OPTIONVALUES)) {
             final Word counter = MonitorCounterNode.counter();
             final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
             counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION);
         }
     }
 
-    public static void decCounter(OptionValues options) {
-        if (verifyBalancedMonitors(options)) {
+    public static void decCounter() {
+        if (verifyBalancedMonitors(INJECTED_OPTIONVALUES)) {
             final Word counter = MonitorCounterNode.counter();
             final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
             counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION);
@@ -750,14 +754,12 @@
                 args.addConst("threadRegister", registers.getThreadRegister());
                 args.addConst("stackPointerRegister", registers.getStackPointerRegister());
                 args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph));
-                args.addConst("options", graph.getOptions());
                 args.addConst("counters", counters);
             } else {
                 args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage());
                 args.add("object", monitorenterNode.object());
                 args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth());
                 args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph));
-                args.addConst("options", graph.getOptions());
                 args.addConst("counters", counters);
             }
 
@@ -777,7 +779,6 @@
             args.addConst("lockDepth", monitorexitNode.getMonitorId().getLockDepth());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph));
-            args.addConst("options", graph.getOptions());
             args.addConst("counters", counters);
 
             template(monitorexitNode, args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -28,6 +28,7 @@
 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_OPTIONVALUES;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY_OR_NULL;
@@ -41,10 +42,14 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocateInstancePrefetchLines;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchDistance;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchLines;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchStepSize;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.allocatePrefetchStyle;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayLengthOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeObjectHeader;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.instanceHeaderSize;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized;
@@ -151,7 +156,7 @@
     }
 
     @Fold
-    static String createName(String path, String typeContext, OptionValues options) {
+    static String createName(@Fold.InjectedParameter OptionValues options, String path, String typeContext) {
         switch (ProfileAllocationsContext.getValue(options)) {
             case AllocatingMethod:
                 return "";
@@ -168,34 +173,33 @@
     }
 
     @Fold
-    static boolean doProfile(OptionValues options) {
+    static boolean doProfile(@Fold.InjectedParameter OptionValues options) {
         return ProfileAllocations.getValue(options);
     }
 
     @Fold
-    static boolean withContext(OptionValues options) {
+    static boolean withContext(@Fold.InjectedParameter OptionValues options) {
         ProfileContext context = ProfileAllocationsContext.getValue(options);
         return context == ProfileContext.AllocatingMethod || context == ProfileContext.AllocatedTypesInMethod;
     }
 
-    protected static void profileAllocation(String path, long size, String typeContext, OptionValues options) {
-        if (doProfile(options)) {
-            String name = createName(path, typeContext, options);
+    protected static void profileAllocation(String path, long size, String typeContext) {
+        if (doProfile(INJECTED_OPTIONVALUES)) {
+            String name = createName(INJECTED_OPTIONVALUES, path, typeContext);
 
-            boolean context = withContext(options);
+            boolean context = withContext(INJECTED_OPTIONVALUES);
             DynamicCounterNode.counter("number of bytes allocated", name, size, context);
             DynamicCounterNode.counter("number of allocations", name, 1, context);
         }
     }
 
     public static void emitPrefetchAllocate(Word address, boolean isArray) {
-        GraalHotSpotVMConfig config = config(INJECTED_VMCONFIG);
-        if (config.allocatePrefetchStyle > 0) {
+        if (allocatePrefetchStyle(INJECTED_VMCONFIG) > 0) {
             // Insert a prefetch for each allocation only on the fast-path
             // Generate several prefetch instructions.
-            int lines = isArray ? config.allocatePrefetchLines : config.allocateInstancePrefetchLines;
-            int stepSize = config.allocatePrefetchStepSize;
-            int distance = config.allocatePrefetchDistance;
+            int lines = isArray ? allocatePrefetchLines(INJECTED_VMCONFIG) : allocateInstancePrefetchLines(INJECTED_VMCONFIG);
+            int stepSize = allocatePrefetchStepSize(INJECTED_VMCONFIG);
+            int distance = allocatePrefetchDistance(INJECTED_VMCONFIG);
             ExplodeLoopNode.explodeLoop();
             for (int i = 0; i < lines; i++) {
                 PrefetchAllocateNode.prefetch(OffsetAddressNode.address(address, distance));
@@ -206,13 +210,13 @@
 
     @Snippet
     public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
-                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
+                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
                     @ConstantParameter Counters counters) {
-        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
+        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
     }
 
     public static Object allocateInstanceHelper(int size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents,
-                    Register threadRegister, boolean constantSize, String typeContext, OptionValues options, Counters counters) {
+                    Register threadRegister, boolean constantSize, String typeContext, Counters counters) {
         Object result;
         Word thread = registerAsWord(threadRegister);
         Word top = readTlabTop(thread);
@@ -223,12 +227,13 @@
             emitPrefetchAllocate(newTop, false);
             result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
         } else {
-            if (counters != null && counters.stub != null) {
-                counters.stub.inc();
+            Counters theCounters = counters;
+            if (theCounters != null && theCounters.stub != null) {
+                theCounters.stub.inc();
             }
             result = newInstanceStub(hub);
         }
-        profileAllocation("instance", size, typeContext, options);
+        profileAllocation("instance", size, typeContext);
         return verifyOop(result);
     }
 
@@ -248,18 +253,18 @@
 
     @Snippet
     public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
-                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
+                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
                     @ConstantParameter Counters counters) {
         // Klass must be initialized by the time the first instance is allocated, therefore we can
         // just load it from the corresponding cell and avoid the resolution check. We have to use a
         // fixed load though, to prevent it from floating above the initialization.
         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
-        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
+        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
     }
 
     @Snippet
     public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
-                    @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
+                    @ConstantParameter Counters counters) {
         if (probability(SLOW_PATH_PROBABILITY, type == null)) {
             DeoptimizeNode.deopt(None, RuntimeConstraint);
         }
@@ -269,10 +274,10 @@
             DeoptimizeNode.deopt(None, RuntimeConstraint);
         }
 
-        return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType));
+        return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, counters, nonNullType));
     }
 
-    private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
+    private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, Counters counters, Class<?> nonNullType) {
         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
@@ -291,7 +296,7 @@
                      * FIXME(je,ds): we should actually pass typeContext instead of "" but late
                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
                      */
-                    return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
+                    return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", counters);
                 }
             } else {
                 DeoptimizeNode.deopt(None, RuntimeConstraint);
@@ -308,19 +313,19 @@
     @Snippet
     public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
-                    @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
+                    @ConstantParameter Counters counters) {
         // Primitive array types are eagerly pre-resolved. We can use a floating load.
         KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
-        return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
+        return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, counters);
     }
 
     @Snippet
     public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
-                    @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
+                    @ConstantParameter Counters counters) {
         // Array type would be resolved by dominating resolution.
         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
-        return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
+        return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, counters);
     }
 
     @Snippet
@@ -333,9 +338,19 @@
                     @ConstantParameter Register threadRegister,
                     @ConstantParameter boolean maybeUnroll,
                     @ConstantParameter String typeContext,
-                    @ConstantParameter OptionValues options,
                     @ConstantParameter Counters counters) {
-        Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
+        Object result = allocateArrayImpl(hub,
+                        length,
+                        prototypeMarkWord,
+                        headerSize,
+                        log2ElementSize,
+                        fillContents,
+                        threadRegister,
+                        maybeUnroll,
+                        typeContext,
+                        false,
+
+                        counters);
         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
     }
 
@@ -349,7 +364,7 @@
     }
 
     private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
-                    boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) {
+                    boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, Counters counters) {
         Object result;
         int allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
         Word thread = registerAsWord(threadRegister);
@@ -360,14 +375,15 @@
                         probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
             writeTlabTop(thread, newTop);
             emitPrefetchAllocate(newTop, true);
-            if (counters != null && counters.arrayLoopInit != null) {
-                counters.arrayLoopInit.inc();
+            Counters theCounters = counters;
+            if (theCounters != null && theCounters.arrayLoopInit != null) {
+                theCounters.arrayLoopInit.inc();
             }
             result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters);
         } else {
             result = newArrayStub(hub, length);
         }
-        profileAllocation("array", allocationSize, typeContext, options);
+        profileAllocation("array", allocationSize, typeContext);
         return result;
     }
 
@@ -421,14 +437,14 @@
 
     @Snippet
     public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
-                    @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
+                    @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord,
                     @ConstantParameter Counters counters) {
-        Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, options, counters);
+        Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, counters);
         return result;
     }
 
     private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind,
-                    int knownLayoutHelper, Word prototypeMarkWord, OptionValues options, Counters counters) {
+                    int knownLayoutHelper, Word prototypeMarkWord, Counters counters) {
         /*
          * We only need the dynamic check for void when we have no static information from
          * knownElementKind.
@@ -470,7 +486,7 @@
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
 
-        Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters);
+        Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, counters);
         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
     }
 
@@ -536,13 +552,14 @@
             offset += 4;
         }
         ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset");
+        Counters theCounters = counters;
         if (manualUnroll && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
             ReplacementsUtil.staticAssert(!constantSize, "size shouldn't be constant at instantiation time");
             // This case handles arrays of constant length. Instead of having a snippet variant for
             // each length, generate a chain of stores of maximum length. Once it's inlined the
             // break statement will trim excess stores.
-            if (counters != null && counters.instanceSeqInit != null) {
-                counters.instanceSeqInit.inc();
+            if (theCounters != null && theCounters.instanceSeqInit != null) {
+                theCounters.instanceSeqInit.inc();
             }
 
             explodeLoop();
@@ -556,13 +573,13 @@
             // Use Word instead of int to avoid extension to long in generated code
             Word off = WordFactory.signed(offset);
             if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
-                if (counters != null && counters.instanceSeqInit != null) {
-                    counters.instanceSeqInit.inc();
+                if (theCounters != null && theCounters.instanceSeqInit != null) {
+                    theCounters.instanceSeqInit.inc();
                 }
                 explodeLoop();
             } else {
-                if (counters != null && counters.instanceLoopInit != null) {
-                    counters.instanceLoopInit.inc();
+                if (theCounters != null && theCounters.instanceLoopInit != null) {
+                    theCounters.instanceLoopInit.inc();
                 }
             }
             for (; off.rawValue() < size; off = off.add(8)) {
@@ -694,7 +711,6 @@
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("constantSize", true);
             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
-            args.addConst("options", localOptions);
             args.addConst("counters", counters);
 
             SnippetTemplate template = template(newInstanceNode, args);
@@ -738,7 +754,6 @@
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("maybeUnroll", length.isConstant());
             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
-            args.addConst("options", localOptions);
             args.addConst("counters", counters);
             SnippetTemplate template = template(newArrayNode, args);
             graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
@@ -747,14 +762,12 @@
 
         public void lower(DynamicNewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) {
             Arguments args = new Arguments(allocateInstanceDynamic, newInstanceNode.graph().getGuardsStage(), tool.getLoweringStage());
-            OptionValues localOptions = newInstanceNode.getOptions();
             args.add("type", newInstanceNode.getInstanceType());
             ValueNode classClass = newInstanceNode.getClassClass();
             assert classClass != null;
             args.add("classClass", classClass);
             args.addConst("fillContents", newInstanceNode.fillContents());
             args.addConst("threadRegister", registers.getThreadRegister());
-            args.addConst("options", localOptions);
             args.addConst("counters", counters);
 
             SnippetTemplate template = template(newInstanceNode, args);
@@ -763,7 +776,6 @@
 
         public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) {
             StructuredGraph graph = newArrayNode.graph();
-            OptionValues localOptions = graph.getOptions();
             Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage());
             args.add("elementType", newArrayNode.getElementType());
             ValueNode voidClass = newArrayNode.getVoidClass();
@@ -784,7 +796,6 @@
                 args.addConst("knownLayoutHelper", 0);
             }
             args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
-            args.addConst("options", localOptions);
             args.addConst("counters", counters);
             SnippetTemplate template = template(newArrayNode, args);
             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,13 +24,12 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
-import java.lang.reflect.Method;
-
 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.NodeView;
@@ -45,6 +44,7 @@
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.nodes.type.StampTool;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.replacements.nodes.BasicObjectCloneNode;
 
 import jdk.vm.ci.meta.Assumptions;
@@ -77,11 +77,14 @@
     @SuppressWarnings("try")
     protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
         ResolvedJavaType type = StampTool.typeOrNull(getObject());
+
         if (type != null) {
             if (type.isArray()) {
-                Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
-                if (method != null) {
-                    final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method);
+                HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) tool.getLowerer();
+                ObjectCloneSnippets.Templates objectCloneSnippets = lowerer.getObjectCloneSnippets();
+                SnippetInfo info = objectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
+                if (info != null) {
+                    final ResolvedJavaMethod snippetMethod = info.getMethod();
                     final Replacements replacements = tool.getReplacements();
                     StructuredGraph snippetGraph = null;
                     DebugContext debug = getDebug();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -26,40 +26,40 @@
 
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
 
-import java.lang.reflect.Method;
 import java.util.EnumMap;
 
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.api.replacements.Snippet;
-import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
 import org.graalvm.compiler.nodes.java.NewArrayNode;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.replacements.Snippets;
 
+import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.JavaKind;
 
 public class ObjectCloneSnippets implements Snippets {
 
-    public static final EnumMap<JavaKind, Method> arrayCloneMethods = new EnumMap<>(JavaKind.class);
+    public static class Templates extends AbstractTemplates {
+
+        final EnumMap<JavaKind, SnippetInfo> arrayCloneMethods = new EnumMap<>(JavaKind.class);
 
-    static {
-        arrayCloneMethods.put(JavaKind.Boolean, getCloneMethod("booleanArrayClone", boolean[].class));
-        arrayCloneMethods.put(JavaKind.Byte, getCloneMethod("byteArrayClone", byte[].class));
-        arrayCloneMethods.put(JavaKind.Char, getCloneMethod("charArrayClone", char[].class));
-        arrayCloneMethods.put(JavaKind.Short, getCloneMethod("shortArrayClone", short[].class));
-        arrayCloneMethods.put(JavaKind.Int, getCloneMethod("intArrayClone", int[].class));
-        arrayCloneMethods.put(JavaKind.Float, getCloneMethod("floatArrayClone", float[].class));
-        arrayCloneMethods.put(JavaKind.Long, getCloneMethod("longArrayClone", long[].class));
-        arrayCloneMethods.put(JavaKind.Double, getCloneMethod("doubleArrayClone", double[].class));
-        arrayCloneMethods.put(JavaKind.Object, getCloneMethod("objectArrayClone", Object[].class));
-    }
-
-    private static Method getCloneMethod(String name, Class<?> param) {
-        try {
-            return ObjectCloneSnippets.class.getDeclaredMethod(name, param);
-        } catch (SecurityException | NoSuchMethodException e) {
-            throw new GraalError(e);
+        public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, TargetDescription target) {
+            super(options, factories, providers, providers.getSnippetReflection(), target);
+            arrayCloneMethods.put(JavaKind.Boolean, snippet(ObjectCloneSnippets.class, "booleanArrayClone"));
+            arrayCloneMethods.put(JavaKind.Byte, snippet(ObjectCloneSnippets.class, "byteArrayClone"));
+            arrayCloneMethods.put(JavaKind.Char, snippet(ObjectCloneSnippets.class, "charArrayClone"));
+            arrayCloneMethods.put(JavaKind.Short, snippet(ObjectCloneSnippets.class, "shortArrayClone"));
+            arrayCloneMethods.put(JavaKind.Int, snippet(ObjectCloneSnippets.class, "intArrayClone"));
+            arrayCloneMethods.put(JavaKind.Float, snippet(ObjectCloneSnippets.class, "floatArrayClone"));
+            arrayCloneMethods.put(JavaKind.Long, snippet(ObjectCloneSnippets.class, "longArrayClone"));
+            arrayCloneMethods.put(JavaKind.Double, snippet(ObjectCloneSnippets.class, "doubleArrayClone"));
+            arrayCloneMethods.put(JavaKind.Object, snippet(ObjectCloneSnippets.class, "objectArrayClone"));
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,16 +24,18 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
 import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.replacements.ReplacementsUtil;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.LocationIdentity;
@@ -44,31 +46,19 @@
 @ClassSubstitution(className = "sun.security.provider.SHA2", optional = true)
 public class SHA2Substitutions {
 
-    static final long stateOffset;
-
-    static final Class<?> shaClass;
-
     public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
 
-    static {
-        try {
-            // Need to use the system class loader as com.sun.crypto.provider.AESCrypt
-            // is normally loaded by the extension class loader which is not delegated
-            // to by the JVMCI class loader.
-            ClassLoader cl = ClassLoader.getSystemClassLoader();
-            shaClass = Class.forName("sun.security.provider.SHA2", true, cl);
-            stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
-        } catch (Exception ex) {
-            throw new GraalError(ex);
-        }
-    }
-
     @MethodSubstitution(isStatic = false)
     static void implCompress0(Object receiver, byte[] buf, int ofs) {
-        Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
-        Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
+        Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object state = RawLoadNode.load(realReceiver, stateOffset(INJECTED_INTRINSIC_CONTEXT), JavaKind.Object, LocationIdentity.any());
         Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
         Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
         HotSpotBackend.sha2ImplCompressStub(bufAddr, stateAddr);
     }
+
+    @Fold
+    static long stateOffset(@Fold.InjectedParameter IntrinsicContext context) {
+        return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(context), "state");
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,12 +24,12 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
 import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.PiNode;
@@ -44,31 +44,19 @@
 @ClassSubstitution(className = "sun.security.provider.SHA5", optional = true)
 public class SHA5Substitutions {
 
-    static final long stateOffset;
-
-    static final Class<?> shaClass;
-
     public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
 
-    static {
-        try {
-            // Need to use the system class loader as com.sun.crypto.provider.AESCrypt
-            // is normally loaded by the extension class loader which is not delegated
-            // to by the JVMCI class loader.
-            ClassLoader cl = ClassLoader.getSystemClassLoader();
-            shaClass = Class.forName("sun.security.provider.SHA5", true, cl);
-            stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
-        } catch (Exception ex) {
-            throw new GraalError(ex);
-        }
-    }
-
     @MethodSubstitution(isStatic = false)
     static void implCompress0(Object receiver, byte[] buf, int ofs) {
-        Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
-        Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
+        Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object state = RawLoadNode.load(realReceiver, stateOffset(), JavaKind.Object, LocationIdentity.any());
         Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
         Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
         HotSpotBackend.sha5ImplCompressStub(bufAddr, stateAddr);
     }
+
+    static long stateOffset() {
+        return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT), "state");
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,12 +24,12 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
 import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.PiNode;
@@ -44,31 +44,19 @@
 @ClassSubstitution(className = "sun.security.provider.SHA", optional = true)
 public class SHASubstitutions {
 
-    static final long stateOffset;
-
-    static final Class<?> shaClass;
-
     public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
 
-    static {
-        try {
-            // Need to use the system class loader as com.sun.crypto.provider.AESCrypt
-            // is normally loaded by the extension class loader which is not delegated
-            // to by the JVMCI class loader.
-            ClassLoader cl = ClassLoader.getSystemClassLoader();
-            shaClass = Class.forName("sun.security.provider.SHA", true, cl);
-            stateOffset = UnsafeAccess.UNSAFE.objectFieldOffset(shaClass.getDeclaredField("state"));
-        } catch (Exception ex) {
-            throw new GraalError(ex);
-        }
-    }
-
     @MethodSubstitution(isStatic = false)
     static void implCompress0(Object receiver, byte[] buf, int ofs) {
-        Object realReceiver = PiNode.piCastNonNull(receiver, shaClass);
-        Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any());
+        Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT));
+        Object state = RawLoadNode.load(realReceiver, stateOffset(), JavaKind.Object, LocationIdentity.any());
         Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs));
         Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
         HotSpotBackend.shaImplCompressStub(bufAddr, stateAddr);
     }
+
+    static long stateOffset() {
+        return HotSpotReplacementsUtil.getFieldOffset(HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT), "state");
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,16 +24,17 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
-import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
+import static org.graalvm.compiler.replacements.ReplacementsUtil.getArrayBaseOffset;
 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
 
-import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.debug.StringToBytesNode;
+import org.graalvm.compiler.nodes.extended.RawStoreNode;
 import org.graalvm.compiler.nodes.java.NewArrayNode;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.options.OptionValues;
@@ -56,11 +57,6 @@
 
     public static final LocationIdentity CSTRING_LOCATION = NamedLocationIdentity.immutable("CString location");
 
-    @Fold
-    static long arrayBaseOffset() {
-        return UNSAFE.arrayBaseOffset(char[].class);
-    }
-
     @Snippet
     public static byte[] transform(@ConstantParameter String compilationTimeString) {
         int i = compilationTimeString.length();
@@ -68,7 +64,8 @@
         Word cArray = CStringConstant.cstring(compilationTimeString);
         while (i-- > 0) {
             // array[i] = cArray.readByte(i);
-            UNSAFE.putByte(array, arrayBaseOffset() + i, cArray.readByte(i, CSTRING_LOCATION));
+            RawStoreNode.storeByte(array, getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + i, cArray.readByte(i, CSTRING_LOCATION), JavaKind.Byte,
+                            NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
         }
         return array;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeAccess.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-
-package org.graalvm.compiler.hotspot.replacements;
-
-import java.lang.reflect.Field;
-
-import sun.misc.Unsafe;
-
-/**
- * Package private access to the {@link Unsafe} capability.
- */
-class UnsafeAccess {
-
-    static final Unsafe UNSAFE = initUnsafe();
-
-    private static Unsafe initUnsafe() {
-        try {
-            // Fast path when we are trusted.
-            return Unsafe.getUnsafe();
-        } catch (SecurityException se) {
-            // Slow path when we are not trusted.
-            try {
-                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
-                theUnsafe.setAccessible(true);
-                return (Unsafe) theUnsafe.get(Unsafe.class);
-            } catch (Exception e) {
-                throw new RuntimeException("exception while trying to get Unsafe", e);
-            }
-        }
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset;
 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
 
@@ -48,7 +49,7 @@
     @Snippet
     public static Object lowerUnsafeLoad(Object object, long offset) {
         Object fixedObject = FixedValueAnchorNode.getObject(object);
-        if (object instanceof java.lang.ref.Reference && referentOffset() == offset) {
+        if (object instanceof java.lang.ref.Reference && referentOffset(INJECTED_METAACCESS) == offset) {
             return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.PRECISE);
         } else {
             return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -69,6 +69,7 @@
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.PiNode;
+import org.graalvm.compiler.nodes.SnippetAnchorNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
@@ -313,7 +314,7 @@
     private static void verifyNotArray(Object object) {
         if (object != null) {
             // Manually build the null check and cast because we're in snippet that's lowered late.
-            AssertionNode.assertion(false, !PiNode.piCastNonNull(object, Object.class).getClass().isArray(), "imprecise card mark used with array");
+            AssertionNode.assertion(false, !PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()).getClass().isArray(), "imprecise card mark used with array");
         }
     }
 
@@ -427,7 +428,7 @@
         private final SnippetInfo serialPreciseWriteBarrier = snippet(WriteBarrierSnippets.class, "serialPreciseWriteBarrier", GC_CARD_LOCATION);
         private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
         private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
-        private final SnippetInfo g1ReferentReadBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
+        private final SnippetInfo g1ReferentReadBarrier = g1PreWriteBarrier;
         private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
         private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
         private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,7 +25,10 @@
 package org.graalvm.compiler.hotspot.replacements.profiling;
 
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
@@ -79,11 +82,11 @@
     @Snippet
     public static void profileMethodEntryWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog) {
         if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
-            int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
-            counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
+            int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG)) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog);
+            counters.writeInt(invocationCounterOffset(INJECTED_VMCONFIG), counterValue);
             if (freqLog >= 0) {
                 int mask = notificationMask(freqLog, probLog, stepLog);
-                if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+                if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
                     methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
                 }
             }
@@ -97,10 +100,10 @@
     public static void profileBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog, int bci,
                     int targetBci) {
         if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
-            int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
-            counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
+            int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG)) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog);
+            counters.writeInt(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue);
             int mask = notificationMask(freqLog, probLog, stepLog);
-            if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+            if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
                 methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,7 +25,10 @@
 package org.graalvm.compiler.hotspot.replacements.profiling;
 
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
@@ -72,11 +75,11 @@
 
     @Snippet
     public static void profileMethodEntry(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog) {
-        int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
-        counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
+        int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG)) + invocationCounterIncrement(INJECTED_VMCONFIG) * step;
+        counters.writeInt(invocationCounterOffset(INJECTED_VMCONFIG), counterValue);
         if (freqLog >= 0) {
             final int mask = notificationMask(freqLog, stepLog);
-            if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+            if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
                 methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
             }
         }
@@ -87,10 +90,10 @@
 
     @Snippet
     public static void profileBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, int bci, int targetBci) {
-        int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
-        counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
+        int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG)) + invocationCounterIncrement(INJECTED_VMCONFIG) * step;
+        counters.writeInt(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue);
         final int mask = notificationMask(freqLog, stepLog);
-        if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+        if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) {
             methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.replacements.nodes.CStringConstant;
 import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
 
@@ -67,7 +68,7 @@
     }
 
     protected static Object createException(Register threadRegister, Class<? extends Throwable> exception) {
-        Word message = null;
+        Word message = WordFactory.zero();
         return createException(threadRegister, exception, message);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -87,17 +87,17 @@
             return providers.getRegisters().getThreadRegister();
         }
         assert index == 3;
-        return options;
+        return StubOptions.TraceExceptionHandlerStub.getValue(options);
     }
 
     @Snippet
-    private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
+    private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter boolean logging) {
         Word thread = registerAsWord(threadRegister);
         checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG));
         checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception);
         writeExceptionOop(thread, exception);
         writeExceptionPc(thread, exceptionPc);
-        if (logging(options)) {
+        if (logging) {
             printf("handling exception %p (", Word.objectToTrackedPointer(exception).rawValue());
             decipher(Word.objectToTrackedPointer(exception).rawValue());
             printf(") at %p (", exceptionPc.rawValue());
@@ -110,7 +110,7 @@
 
         Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread);
 
-        if (logging(options)) {
+        if (logging) {
             printf("handler for exception %p at %p is at %p (", Word.objectToTrackedPointer(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue());
             decipher(handlerPc.rawValue());
             printf(")\n");
@@ -143,11 +143,6 @@
         }
     }
 
-    @Fold
-    static boolean logging(OptionValues options) {
-        return StubOptions.TraceExceptionHandlerStub.getValue(options);
-    }
-
     /**
      * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build
      * where the ASSERT mechanism is enabled.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallSnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+
+package org.graalvm.compiler.hotspot.stubs;
+
+import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
+import static org.graalvm.compiler.hotspot.stubs.StubUtil.fatal;
+
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode;
+import org.graalvm.compiler.hotspot.word.KlassPointer;
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.PiNode;
+import org.graalvm.compiler.nodes.SnippetAnchorNode;
+import org.graalvm.compiler.nodes.extended.GuardingNode;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.Snippets;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
+
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.DeoptimizationAction;
+
+public class ForeignCallSnippets implements Snippets {
+
+    public static class Templates extends AbstractTemplates {
+
+        final SnippetInfo handlePendingException = snippet(ForeignCallSnippets.class, "handlePendingException");
+        final SnippetInfo getAndClearObjectResult = snippet(ForeignCallSnippets.class, "getAndClearObjectResult", OBJECT_RESULT_LOCATION);
+        final SnippetInfo verifyObject = snippet(ForeignCallSnippets.class, "verifyObject");
+
+        public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, TargetDescription target) {
+            super(options, factories, providers, providers.getSnippetReflection(), target);
+        }
+    }
+
+    /**
+     * See {@link ForeignCallStub#getGraph}.
+     */
+    @Snippet
+    public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
+        if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
+            if (isObjectResult) {
+                getAndClearObjectResult(thread);
+            }
+            DeoptimizeCallerNode.deopt(DeoptimizationAction.None, RuntimeConstraint);
+        }
+    }
+
+    /**
+     * Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
+     */
+    @Snippet
+    public static Object verifyObject(Object object) {
+        if (verifyOops(INJECTED_VMCONFIG)) {
+            Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
+            verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
+
+            Pointer oop = Word.objectToTrackedPointer(object);
+            if (object != null) {
+                GuardingNode anchorNode = SnippetAnchorNode.anchor();
+                // make sure object is 'reasonable'
+                if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
+                    fatal("oop not in heap: %p", oop.rawValue());
+                }
+
+                KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
+                if (klass.isNull()) {
+                    fatal("klass for oop %p is null", oop.rawValue());
+                }
+            }
+        }
+        return object;
+    }
+
+    @Fold
+    static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.verifyOopCounterAddress;
+    }
+
+    @Fold
+    static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.verifyOopMask;
+    }
+
+    @Fold
+    static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.verifyOopBits;
+    }
+
+    /**
+     * Gets and clears the object result from a runtime call stored in a thread local.
+     *
+     * @return the object that was in the thread local
+     */
+    @Snippet
+    public static Object getAndClearObjectResult(Word thread) {
+        Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION);
+        thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION);
+        return result;
+    }
+
+    public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
+
+    @Fold
+    static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.threadObjectResultOffset;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,11 +24,14 @@
 
 package org.graalvm.compiler.hotspot.stubs;
 
+import static jdk.vm.ci.code.BytecodeFrame.UNKNOWN_BCI;
 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall;
 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee;
 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
+import static org.graalvm.compiler.nodes.CallTargetNode.InvokeKind.Static;
+import static org.graalvm.compiler.nodes.ConstantNode.forBoolean;
 
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.LIRKind;
@@ -43,10 +46,10 @@
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
+import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
-import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil;
-import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets.Templates;
 import org.graalvm.compiler.nodes.InvokeNode;
 import org.graalvm.compiler.nodes.ParameterNode;
 import org.graalvm.compiler.nodes.ReturnNode;
@@ -76,8 +79,8 @@
  * deoptimization while the call is in progress. And since these are foreign/runtime calls on slow
  * paths, we don't want to force the register allocator to spill around the call. As such, this stub
  * saves and restores all allocatable registers. It also
- * {@linkplain StubUtil#handlePendingException(Word, boolean, boolean) handles} any exceptions
- * raised during the foreign call.
+ * {@linkplain ForeignCallSnippets#handlePendingException handles} any exceptions raised during the
+ * foreign call.
  */
 public class ForeignCallStub extends Stub {
 
@@ -112,9 +115,10 @@
                         PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutability, killedLocations));
         this.jvmciRuntime = runtime;
         this.prependThread = prependThread;
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
         Class<?>[] targetParameterTypes = createTargetParameters(descriptor);
         ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
-        target = HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), targetSig, address,
+        target = HotSpotForeignCallLinkageImpl.create(metaAccess, providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), targetSig, address,
                         DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutability, killedLocations);
     }
 
@@ -234,16 +238,21 @@
         // Do we want to clear the pending exception?
         boolean shouldClearException = linkage.isReexecutable() || linkage.isReexecutableOnlyAfterException();
         try {
-            ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
+            HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
+            Templates foreignCallSnippets = lowerer.getForeignCallSnippets();
+            ResolvedJavaMethod handlePendingException = foreignCallSnippets.handlePendingException.getMethod();
+            ResolvedJavaMethod getAndClearObjectResult = foreignCallSnippets.getAndClearObjectResult.getMethod();
+            ResolvedJavaMethod verifyObject = foreignCallSnippets.verifyObject.getMethod();
+            ResolvedJavaMethod thisMethod = getGraphMethod();
             GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString());
             StructuredGraph graph = kit.getGraph();
             ParameterNode[] params = createParameters(kit, args);
             ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
             ValueNode result = createTargetCall(kit, params, thread);
-            kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(shouldClearException, graph), ConstantNode.forBoolean(isObjectResult, graph));
+            createStaticInvoke(kit, handlePendingException, thread, forBoolean(shouldClearException, graph), forBoolean(isObjectResult, graph));
             if (isObjectResult) {
-                InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
-                result = kit.createInvoke(StubUtil.class, "verifyObject", object);
+                InvokeNode object = createStaticInvoke(kit, getAndClearObjectResult, thread);
+                result = createStaticInvoke(kit, verifyObject, object);
             }
             kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
             debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
@@ -258,6 +267,27 @@
         }
     }
 
+    private static InvokeNode createStaticInvoke(GraphKit kit, ResolvedJavaMethod method, ValueNode... args) {
+        return kit.createInvoke(method, Static, null, UNKNOWN_BCI, args);
+    }
+
+    private ResolvedJavaMethod getGraphMethod() {
+        ResolvedJavaMethod thisMethod = null;
+        for (ResolvedJavaMethod method : providers.getMetaAccess().lookupJavaType(ForeignCallStub.class).getDeclaredMethods()) {
+            if (method.getName().equals("getGraph")) {
+                if (thisMethod == null) {
+                    thisMethod = method;
+                } else {
+                    throw new InternalError("getGraph is ambiguous");
+                }
+            }
+        }
+        if (thisMethod == null) {
+            throw new InternalError("Can't find getGraph");
+        }
+        return thisMethod;
+    }
+
     private ParameterNode[] createParameters(GraphKit kit, Class<?>[] args) {
         ParameterNode[] params = new ParameterNode[args.length];
         ResolvedJavaType accessingClass = providers.getMetaAccess().lookupJavaType(getClass());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,43 +24,30 @@
 
 package org.graalvm.compiler.hotspot.stubs;
 
-import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
-
-import java.lang.reflect.Method;
-
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
 import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
-import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.java.GraphBuilderPhase;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.ParameterNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
 import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
 import org.graalvm.compiler.replacements.SnippetTemplate;
 import org.graalvm.compiler.replacements.Snippets;
 
 import jdk.vm.ci.meta.Local;
 import jdk.vm.ci.meta.LocalVariableTable;
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
@@ -92,40 +79,21 @@
      */
     public SnippetStub(Class<? extends Snippets> snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
         super(options, providers, linkage);
-        Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null);
-        this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod);
+        this.method = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName);
+        registerSnippet();
+    }
+
+    protected void registerSnippet() {
+        providers.getReplacements().registerSnippet(method, null, null, false);
     }
 
     @Override
     @SuppressWarnings("try")
     protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) {
-        Plugins defaultPlugins = providers.getGraphBuilderPlugins();
-        MetaAccessProvider metaAccess = providers.getMetaAccess();
-        SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();
-
-        Plugins plugins = new Plugins(defaultPlugins);
-        plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection));
-        GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
-
-        // @formatter:off
         // Stubs cannot have optimistic assumptions since they have
         // to be valid for the entire run of the VM.
-        final StructuredGraph graph = new StructuredGraph.Builder(options, debug).
-                        method(method).
-                        compilationId(compilationId).
-                        setIsSubstitution(true).
-                        build();
-        // @formatter:on
+        final StructuredGraph graph = buildInitialGraph(debug, compilationId, makeConstArgs());
         try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) {
-            graph.disableUnsafeAccessTracking();
-
-            IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING);
-            GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(),
-                            providers.getConstantReflection(), providers.getConstantFieldProvider(),
-                            config, OptimisticOptimizations.NONE,
-                            initialIntrinsicContext);
-            instance.apply(graph);
-
             for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
                 int index = param.index();
                 if (method.getParameterAnnotation(NonNullParameter.class, index) != null) {
@@ -146,8 +114,8 @@
         return graph;
     }
 
-    protected BytecodeProvider getReplacementsBytecodeProvider() {
-        return providers.getReplacements().getDefaultReplacementBytecodeProvider();
+    protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) {
+        return providers.getReplacements().getSnippet(method, args, false, null).copyWithIdentifier(compilationId, debug);
     }
 
     protected boolean checkConstArg(int index, String expectedName) {
@@ -191,4 +159,8 @@
     public String toString() {
         return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">";
     }
+
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,13 +24,6 @@
 
 package org.graalvm.compiler.hotspot.stubs;
 
-import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
 import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
 
 import java.lang.reflect.Method;
@@ -44,20 +37,12 @@
 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode;
 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
 import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
-import org.graalvm.compiler.hotspot.word.KlassPointer;
-import org.graalvm.compiler.nodes.PiNode;
-import org.graalvm.compiler.nodes.SnippetAnchorNode;
-import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.replacements.Log;
 import org.graalvm.compiler.word.Word;
-import jdk.internal.vm.compiler.word.Pointer;
 import jdk.internal.vm.compiler.word.WordFactory;
 
-import jdk.vm.ci.meta.DeoptimizationAction;
-
 //JaCoCo Exclude
 
 /**
@@ -96,15 +81,6 @@
         return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
     }
 
-    public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
-        if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
-            if (isObjectResult) {
-                getAndClearObjectResult(thread);
-            }
-            DeoptimizeCallerNode.deopt(DeoptimizationAction.None, RuntimeConstraint);
-        }
-    }
-
     /**
      * Determines if this is a HotSpot build where the ASSERT mechanism is enabled.
      */
@@ -232,46 +208,6 @@
     }
 
     /**
-     * Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
-     */
-    public static Object verifyObject(Object object) {
-        if (verifyOops(INJECTED_VMCONFIG)) {
-            Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
-            verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
-
-            Pointer oop = Word.objectToTrackedPointer(object);
-            if (object != null) {
-                GuardingNode anchorNode = SnippetAnchorNode.anchor();
-                // make sure object is 'reasonable'
-                if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
-                    fatal("oop not in heap: %p", oop.rawValue());
-                }
-
-                KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
-                if (klass.isNull()) {
-                    fatal("klass for oop %p is null", oop.rawValue());
-                }
-            }
-        }
-        return object;
-    }
-
-    @Fold
-    static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.verifyOopCounterAddress;
-    }
-
-    @Fold
-    static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.verifyOopMask;
-    }
-
-    @Fold
-    static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.verifyOopBits;
-    }
-
-    /**
      * Print {@code number} as decimal string to {@code buffer}.
      *
      * @param buffer
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.stubs;
 
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES;
 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
 import static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
@@ -77,14 +78,13 @@
         if (index == 2) {
             return providers.getRegisters().getThreadRegister();
         }
-        assert index == 3;
-        return options;
+        throw new InternalError();
     }
 
     @Snippet
-    private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
+    private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) {
         Pointer exceptionOop = Word.objectToTrackedPointer(exception);
-        if (logging(options)) {
+        if (logging(INJECTED_OPTIONVALUES)) {
             printf("unwinding exception %p (", exceptionOop.rawValue());
             decipher(exceptionOop.rawValue());
             printf(") at %p (", returnAddress.rawValue());
@@ -97,7 +97,7 @@
 
         Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress);
 
-        if (logging(options)) {
+        if (logging(INJECTED_OPTIONVALUES)) {
             printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue());
             decipher(handlerInCallerPc.rawValue());
             printf(")\n");
@@ -107,7 +107,7 @@
     }
 
     @Fold
-    static boolean logging(OptionValues options) {
+    static boolean logging(@Fold.InjectedParameter OptionValues options) {
         return StubOptions.TraceUnwindStub.getValue(options);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.stubs;
 
-import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject;
+import static org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets.verifyObject;
 
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Wed Dec 12 08:38:45 2018 -0500
@@ -38,11 +38,11 @@
  * {@link GraphEncoder} for a description of the encoding format. Use {@link GraphDecoder} for
  * decoding.
  */
-public final class EncodedGraph {
+public class EncodedGraph {
 
     private final byte[] encoding;
     private final int startOffset;
-    private final Object[] objects;
+    protected final Object[] objects;
     private final NodeClass<?>[] types;
     private final Assumptions assumptions;
     private final List<ResolvedJavaMethod> inlinedMethods;
@@ -82,10 +82,18 @@
         return startOffset;
     }
 
-    public Object[] getObjects() {
+    protected Object[] getObjects() {
         return objects;
     }
 
+    public int getNumObjects() {
+        return objects.length;
+    }
+
+    public Object getObject(int i) {
+        return objects[i];
+    }
+
     public NodeClass<?>[] getNodeClasses() {
         return types;
     }
@@ -109,4 +117,9 @@
     public boolean hasUnsafeAccess() {
         return hasUnsafeAccess;
     }
+
+    @SuppressWarnings("unused")
+    public boolean isCallToOriginal(ResolvedJavaMethod callTarget) {
+        return false;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java	Wed Dec 12 08:38:45 2018 -0500
@@ -27,8 +27,6 @@
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
 
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
@@ -51,9 +49,11 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 
-//JaCoCo Exclude
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
-import jdk.vm.ci.meta.ResolvedJavaType;
+//JaCoCo Exclude
 
 /**
  * A node that changes the type of its input, usually narrowing it. For example, a {@link PiNode}
@@ -281,12 +281,12 @@
      * Changes the stamp of an object to represent a given type and to indicate that the object is
      * not null.
      */
-    public static Object piCastNonNull(Object object, @ConstantNodeParameter Class<?> toType) {
+    public static Object piCastNonNull(Object object, @ConstantNodeParameter ResolvedJavaType toType) {
         return piCast(object, toType, false, true);
     }
 
     @NodeIntrinsic
-    public static native Object piCast(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
+    public static native Object piCast(Object object, @ConstantNodeParameter ResolvedJavaType toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
 
     /**
      * A placeholder node in a snippet that will be replaced with a {@link PiNode} when the snippet
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java	Wed Dec 12 08:38:45 2018 -0500
@@ -83,6 +83,9 @@
     @NodeIntrinsic
     public static native Object storeChar(Object object, long offset, char value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
 
+    @NodeIntrinsic
+    public static native Object storeByte(Object object, long offset, byte value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
+
     public boolean needsBarrier() {
         return needsBarrier;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java	Wed Dec 12 08:38:45 2018 -0500
@@ -43,15 +43,20 @@
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.UnaryOpLogicNode;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.ConditionalNode;
 import org.graalvm.compiler.nodes.calc.IsNullNode;
 import org.graalvm.compiler.nodes.extended.AnchoringNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.type.StampTool;
 
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.TriState;
 
 /**
@@ -218,6 +223,17 @@
         return checkedStamp;
     }
 
+    @NodeIntrinsic
+    public static native boolean doInstanceof(@ConstantNodeParameter ResolvedJavaType type, Object object);
+
+    @SuppressWarnings("unused")
+    static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ResolvedJavaType type, ValueNode object) {
+        InstanceOfNode node = new InstanceOfNode(StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), type)), object, null, null);
+        node = b.add(node);
+        b.addPush(JavaKind.Int, ConditionalNode.create(node, NodeView.DEFAULT));
+        return true;
+    }
+
     @Override
     public TriState implies(boolean thisNegated, LogicNode other) {
         if (other instanceof InstanceOfNode) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java	Wed Dec 12 08:38:45 2018 -0500
@@ -32,6 +32,7 @@
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
 import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -57,6 +58,11 @@
     }
 
     @Override
+    public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
+        return delegate.getIntrinsifyingPlugin(method);
+    }
+
+    @Override
     public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
         return delegate.getSnippet(method, args, trackNodeSourcePosition, replaceePosition);
     }
@@ -67,8 +73,8 @@
     }
 
     @Override
-    public void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition) {
-        delegate.registerSnippet(method, trackNodeSourcePosition);
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
+        delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java	Wed Dec 12 08:38:45 2018 -0500
@@ -33,6 +33,7 @@
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 import org.graalvm.compiler.options.OptionValues;
 
@@ -52,6 +53,11 @@
     GraphBuilderConfiguration.Plugins getGraphBuilderPlugins();
 
     /**
+     * Gets the plugin type that intrinsifies calls to {@code method}.
+     */
+    Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method);
+
+    /**
      * Gets the snippet graph derived from a given method.
      *
      * @param args arguments to the snippet if available, otherwise {@code null}
@@ -75,7 +81,7 @@
     /**
      * Registers a method as snippet.
      */
-    void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition);
+    void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition);
 
     /**
      * Gets a graph that is a substitution for a given method.
@@ -138,4 +144,13 @@
      * {@link Replacements#registerSnippetTemplateCache(SnippetTemplateCache)}.
      */
     <T extends SnippetTemplateCache> T getSnippetTemplateCache(Class<T> templatesClass);
+
+    /**
+     * Notifies this method that no further snippets will be registered via {@link #registerSnippet}
+     * or {@link #registerSnippetTemplateCache}.
+     *
+     * This is a hook for an implementation to check for or forbid late registration.
+     */
+    default void closeSnippetRegistration() {
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/SuppressFBWarnings.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,42 @@
+/*
+ * 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
+ * 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.
+ */
+
+
+package org.graalvm.compiler.options;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+public @interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java	Wed Dec 12 08:38:45 2018 -0500
@@ -109,34 +109,42 @@
     }
 
     public Providers copyWith(MetaAccessProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(substitution, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
     }
 
     public Providers copyWith(CodeCacheProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, substitution, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
     }
 
     public Providers copyWith(ConstantReflectionProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
     }
 
     public Providers copyWith(ConstantFieldProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider);
     }
 
     public Providers copyWith(ForeignCallsProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, substitution, lowerer, replacements, stampProvider);
     }
 
     public Providers copyWith(LoweringProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, substitution, replacements, stampProvider);
     }
 
     public Providers copyWith(Replacements substitution) {
+        assert this.getClass() == Providers.class : "must override in " + getClass();
         return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider);
     }
 
     public Providers copyWith(StampProvider substitution) {
+        assert this.getClass() == Providers.class : "must override";
         return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, substitution);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java	Wed Dec 12 08:38:45 2018 -0500
@@ -82,9 +82,12 @@
     public enum WellKnownDependency {
         CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"),
         META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"),
+        ASSUMPTIONS("b.getAssumptions()", "jdk.vm.ci.meta.Assumptions"),
+        OPTIONVALUES("b.getOptions()", "org.graalvm.compiler.options.OptionValues"),
         INJECTED_STAMP(new InjectedStampDependency()),
         SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")),
         STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"),
+        INTRINSIC_CONTEXT("b.getIntrinsic()", "org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext"),
         STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph");
 
         private final String expr;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java	Wed Dec 12 08:38:45 2018 -0500
@@ -245,20 +245,29 @@
             }
 
             if (method.getParameters().size() < 2) {
+                nonMatches.put(method, "Too few arguments");
                 continue;
             }
 
             VariableElement firstArg = method.getParameters().get(0);
             if (!isTypeCompatible(firstArg.asType(), processor.getType(GRAPH_BUILDER_CONTEXT_CLASS_NAME))) {
+                nonMatches.put(method, "First argument isn't of type GraphBuilderContext");
                 continue;
             }
 
             VariableElement secondArg = method.getParameters().get(1);
             if (!isTypeCompatible(secondArg.asType(), processor.getType(RESOLVED_JAVA_METHOD_CLASS_NAME))) {
+                nonMatches.put(method, "Second argument isn't of type ResolvedJavaMethod");
                 continue;
             }
 
             if (method.getReturnType().getKind() != TypeKind.BOOLEAN) {
+                nonMatches.put(method, "Doesn't return boolean");
+                continue;
+            }
+
+            if (!method.getModifiers().contains(Modifier.STATIC)) {
+                nonMatches.put(method, "Method is non-static");
                 continue;
             }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -38,7 +38,7 @@
      */
     protected final ClassfileBytecodeProvider getSystemClassLoaderBytecodeProvider() {
         ReplacementsImpl d = (ReplacementsImpl) getReplacements();
-        MetaAccessProvider metaAccess = d.providers.getMetaAccess();
+        MetaAccessProvider metaAccess = d.getProviders().getMetaAccess();
         ClassfileBytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader());
         return bytecodeProvider;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -39,7 +39,7 @@
     protected SnippetsTest() {
         ReplacementsImpl d = (ReplacementsImpl) getReplacements();
         bytecodeProvider = getSystemClassLoaderBytecodeProvider();
-        installer = new ReplacementsImpl(getInitialOptions(), null, d.providers, d.snippetReflection, bytecodeProvider, d.target);
+        installer = new ReplacementsImpl(getInitialOptions(), null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target);
         installer.setGraphBuilderPlugins(d.getGraphBuilderPlugins());
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -93,6 +93,7 @@
             needCheckNode = false;
         } else {
             List<String> vmArgs = GraalServices.getInputArguments();
+            Assume.assumeTrue(vmArgs != null);
             for (String vmArg : vmArgs) {
                 if (vmArg.equals(DISABLE_COMPACTSTRINGS_FLAG)) {
                     needCheckNode = false;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Wed Dec 12 08:38:45 2018 -0500
@@ -83,6 +83,7 @@
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.Signature;
 
 /**
@@ -218,11 +219,12 @@
     }
 
     public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, boolean isStatic) {
+        ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(declaringClass);
         ResolvedJavaMethod method = null;
-        for (Method m : declaringClass.getDeclaredMethods()) {
+        for (ResolvedJavaMethod m : type.getDeclaredMethods()) {
             if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) {
                 assert method == null : "found more than one method in " + declaringClass + " named " + name;
-                method = providers.getMetaAccess().lookupJavaMethod(m);
+                method = m;
             }
         }
         GraalError.guarantee(method != null, "Could not find %s.%s (%s)", declaringClass, name, isStatic ? "static" : "non-static");
@@ -356,7 +358,8 @@
         Plugins plugins = new Plugins(graphBuilderPlugins);
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
 
-        StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).build();
+        StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(
+                        invoke.graph().trackNodeSourcePosition()).setIsSubstitution(true).build();
         IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING);
         GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config,
                         OptimisticOptimizations.NONE,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java	Wed Dec 12 08:38:45 2018 -0500
@@ -76,6 +76,8 @@
             return type.cast(foreignCalls);
         } else if (type.equals(SnippetReflectionProvider.class)) {
             return type.cast(snippetReflection);
+        } else if (type.equals(WordTypes.class)) {
+            return type.cast(wordTypes);
         } else {
             throw new GraalError("Cannot handle injected argument of type %s.", type.getName());
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Wed Dec 12 08:38:45 2018 -0500
@@ -419,10 +419,18 @@
         protected FixedWithNextNode lastInstr;
         protected ValueNode pushedNode;
         protected boolean invokeConsumed;
+        protected final InvokeKind invokeKind;
+        protected final JavaType invokeReturnType;
 
         public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) {
+            this(inlineScope, lastInstr, null, null);
+        }
+
+        public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr, InvokeKind invokeKind, JavaType invokeReturnType) {
             super(inlineScope, inlineScope.invokeData != null ? inlineScope.invokeData.invoke : null);
             this.lastInstr = lastInstr;
+            this.invokeKind = invokeKind;
+            this.invokeReturnType = invokeReturnType;
         }
 
         @Override
@@ -483,6 +491,22 @@
         }
 
         @Override
+        public InvokeKind getInvokeKind() {
+            if (invokeKind != null) {
+                return invokeKind;
+            }
+            return super.getInvokeKind();
+        }
+
+        @Override
+        public JavaType getInvokeReturnType() {
+            if (invokeReturnType != null) {
+                return invokeReturnType;
+            }
+            return super.getInvokeReturnType();
+        }
+
+        @Override
         public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
             if (invokeConsumed) {
                 throw unimplemented("handleReplacedInvoke can be called only once");
@@ -727,7 +751,9 @@
         invoke.asNode().replaceAtPredecessor(null);
 
         PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, loopExplosionPlugin, arguments);
-        PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);
+
+        JavaType returnType = targetMethod.getSignature().getReturnType(methodScope.method.getDeclaringClass());
+        PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor, callTarget.invokeKind(), returnType);
         InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
 
         if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Wed Dec 12 08:38:45 2018 -0500
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.replacements;
 
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
 import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache;
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
@@ -72,6 +73,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
@@ -98,7 +100,16 @@
 public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
 
     protected final OptionValues options;
-    public final Providers providers;
+
+    public Providers getProviders() {
+        return providers;
+    }
+
+    public void setProviders(Providers providers) {
+        this.providers = providers.copyWith(this);
+    }
+
+    protected Providers providers;
     public final SnippetReflectionProvider snippetReflection;
     public final TargetDescription target;
     private GraphBuilderConfiguration.Plugins graphBuilderPlugins;
@@ -130,12 +141,15 @@
         return graphBuilderPlugins;
     }
 
-    protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) {
-        return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null;
-    }
-
-    protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) {
-        return method.getAnnotation(Word.Operation.class) != null;
+    @Override
+    public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
+        if (method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null) {
+            return GeneratedInvocationPlugin.class;
+        }
+        if (method.getAnnotation(Word.Operation.class) != null) {
+            return WordOperationPlugin.class;
+        }
+        return null;
     }
 
     private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
@@ -163,7 +177,8 @@
             // Force inlining when parsing replacements
             return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider);
         } else {
-            assert method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(),
+            assert IS_BUILDING_NATIVE_IMAGE || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s",
+                            NodeIntrinsic.class.getSimpleName(),
                             method.format("%h.%n"), b);
         }
         return null;
@@ -174,13 +189,15 @@
         if (b.parsingIntrinsic()) {
             IntrinsicContext intrinsic = b.getIntrinsic();
             if (!intrinsic.isCallToOriginal(method)) {
-                if (hasGeneratedInvocationPluginAnnotation(method)) {
-                    throw new GraalError("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName());
+                Class<? extends GraphBuilderPlugin> pluginClass = getIntrinsifyingPlugin(method);
+                if (pluginClass != null) {
+                    String methodDesc = method.format("%H.%n(%p)");
+                    throw new GraalError("Call to %s should have been intrinsified by a %s. " +
+                                    "This is typically caused by Eclipse failing to run an annotation " +
+                                    "processor. This can usually be fixed by forcing Eclipse to rebuild " +
+                                    "the source file in which %s is declared",
+                                    methodDesc, pluginClass.getSimpleName(), methodDesc);
                 }
-                if (hasGenericInvocationPluginAnnotation(method)) {
-                    throw new GraalError("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName());
-                }
-
                 throw new GraalError("All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s",
                                 intrinsic.getIntrinsicMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)"));
             }
@@ -213,7 +230,7 @@
 
     private static final AtomicInteger nextDebugContextId = new AtomicInteger();
 
-    protected DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
+    public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
         DebugContext outer = DebugContext.forCurrentThread();
         Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet());
         List<DebugHandlersFactory> factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory);
@@ -249,7 +266,7 @@
     }
 
     @Override
-    public void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition) {
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
         // No initialization needed as snippet graphs are created on demand in getSnippet
     }
 
@@ -386,7 +403,7 @@
          */
         protected final ResolvedJavaMethod substitutedMethod;
 
-        protected GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) {
+        public GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) {
             this.replacements = replacements;
             this.method = substitute;
             this.substitutedMethod = substitutedMethod;
@@ -488,13 +505,15 @@
 
                 IntrinsicContext initialIntrinsicContext = null;
                 Snippet snippetAnnotation = method.getAnnotation(Snippet.class);
-                if (snippetAnnotation == null) {
+                MethodSubstitution methodAnnotation = method.getAnnotation(MethodSubstitution.class);
+                if (methodAnnotation == null && snippetAnnotation == null) {
                     // Post-parse inlined intrinsic
                     initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING);
                 } else {
                     // Snippet
                     ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
-                    initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING, snippetAnnotation.allowPartialIntrinsicArgumentMismatch());
+                    initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING,
+                                    snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true);
                 }
 
                 createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), replacements.providers.getConstantFieldProvider(), config,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java	Wed Dec 12 08:38:45 2018 -0500
@@ -51,6 +51,18 @@
         }
     }
 
+    public static void staticAssert(boolean condition, String message, Object arg1) {
+        if (REPLACEMENTS_ASSERTIONS_ENABLED) {
+            AssertionNode.assertion(true, condition, message, arg1, "");
+        }
+    }
+
+    public static void staticAssert(boolean condition, String message, Object arg1, Object arg2) {
+        if (REPLACEMENTS_ASSERTIONS_ENABLED) {
+            AssertionNode.assertion(true, condition, message, arg1, arg2);
+        }
+    }
+
     /**
      * Asserts that condition evaluates to true at runtime. This is intended to be used within
      * snippets or stubs, and will lead to a VM error if it fails.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Wed Dec 12 08:38:45 2018 -0500
@@ -64,6 +64,7 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.core.common.type.TypeReference;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
@@ -170,7 +171,7 @@
     public abstract static class SnippetInfo {
 
         protected final ResolvedJavaMethod method;
-        protected ResolvedJavaMethod original;
+        protected final ResolvedJavaMethod original;
         protected final LocationIdentity[] privateLocations;
         protected final Object receiver;
 
@@ -269,8 +270,9 @@
 
         protected abstract Lazy lazy();
 
-        protected SnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
+        protected SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
             this.method = method;
+            this.original = original;
             this.privateLocations = privateLocations;
             instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName());
             instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName());
@@ -285,10 +287,6 @@
             return lazy().constantParameters.length;
         }
 
-        public void setOriginalMethod(ResolvedJavaMethod original) {
-            this.original = original;
-        }
-
         public boolean isConstantParameter(int paramIdx) {
             return lazy().constantParameters[paramIdx];
         }
@@ -318,8 +316,8 @@
     protected static class LazySnippetInfo extends SnippetInfo {
         protected final AtomicReference<Lazy> lazy = new AtomicReference<>(null);
 
-        protected LazySnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
-            super(method, privateLocations, receiver);
+        protected LazySnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
+            super(method, original, privateLocations, receiver);
         }
 
         @Override
@@ -334,8 +332,8 @@
     protected static class EagerSnippetInfo extends SnippetInfo {
         protected final Lazy lazy;
 
-        protected EagerSnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations, Object receiver) {
-            super(method, privateLocations, receiver);
+        protected EagerSnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver) {
+            super(method, original, privateLocations, receiver);
             lazy = new Lazy(method);
         }
 
@@ -642,28 +640,45 @@
             return null;
         }
 
+        public static ResolvedJavaMethod findMethod(MetaAccessProvider metaAccess, Class<?> declaringClass, String methodName) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(declaringClass);
+            ResolvedJavaMethod result = null;
+            for (ResolvedJavaMethod m : type.getDeclaredMethods()) {
+                if (m.getName().equals(methodName)) {
+                    if (!Assertions.assertionsEnabled()) {
+                        return m;
+                    } else {
+                        assert result == null : "multiple definitions found";
+                        result = m;
+                    }
+                }
+            }
+            if (result == null) {
+                throw new GraalError("Could not find method in " + declaringClass + " named " + methodName);
+            }
+            return result;
+        }
+
         protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, LocationIdentity... initialPrivateLocations) {
-            return snippet(declaringClass, methodName, null, initialPrivateLocations);
+            return snippet(declaringClass, methodName, null, null, initialPrivateLocations);
         }
 
         /**
          * Finds the unique method in {@code declaringClass} named {@code methodName} annotated by
          * {@link Snippet} and returns a {@link SnippetInfo} value describing it. There must be
-         * exactly one snippet method in {@code declaringClass}.
+         * exactly one snippet method in {@code declaringClass} with a given name.
          */
-        protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, Object receiver, LocationIdentity... initialPrivateLocations) {
+        protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName, ResolvedJavaMethod original, Object receiver, LocationIdentity... initialPrivateLocations) {
             assert methodName != null;
-            Method method = findMethod(declaringClass, methodName, null);
-            assert method != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName;
-            assert method.getAnnotation(Snippet.class) != null : method + " must be annotated with @" + Snippet.class.getSimpleName();
-            assert findMethod(declaringClass, methodName, method) == null : "found more than one method named " + methodName + " in " + declaringClass;
-            ResolvedJavaMethod javaMethod = providers.getMetaAccess().lookupJavaMethod(method);
-            providers.getReplacements().registerSnippet(javaMethod, GraalOptions.TrackNodeSourcePosition.getValue(options));
+            ResolvedJavaMethod javaMethod = findMethod(providers.getMetaAccess(), declaringClass, methodName);
+            assert javaMethod != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName;
+            assert javaMethod.getAnnotation(Snippet.class) != null : javaMethod + " must be annotated with @" + Snippet.class.getSimpleName();
+            providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options));
             LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations;
             if (GraalOptions.EagerSnippets.getValue(options)) {
-                return new EagerSnippetInfo(javaMethod, privateLocations, receiver);
+                return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver);
             } else {
-                return new LazySnippetInfo(javaMethod, privateLocations, receiver);
+                return new LazySnippetInfo(javaMethod, original, privateLocations, receiver);
             }
         }
 
@@ -1038,7 +1053,7 @@
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     Mark mark = snippetCopy.getMark();
                     LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase());
-                    new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark);
+                    new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark, false);
                     loop.deleteUnusedNodes();
                 }
                 GraphUtil.removeFixedWithUnusedInputs(explodeLoop);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java	Wed Dec 12 08:38:45 2018 -0500
@@ -30,7 +30,6 @@
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
 
-import java.lang.reflect.Method;
 import java.util.EnumMap;
 
 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
@@ -290,7 +289,7 @@
                 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
             }
         } else {
-            ReplacementsUtil.staticAssert(false, "unknown array type check");
+            ReplacementsUtil.staticAssert(false, "unknown array type check ", arrayTypeCheck);
         }
     }
 
@@ -384,8 +383,7 @@
         }
 
         protected SnippetInfo snippet(ArrayCopySnippets receiver, String methodName) {
-            SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, receiver, LocationIdentity.any());
-            info.setOriginalMethod(originalArraycopy());
+            SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, originalArraycopy(), receiver, LocationIdentity.any());
             return info;
         }
 
@@ -577,13 +575,11 @@
 
         private ResolvedJavaMethod originalArraycopy() throws GraalError {
             if (originalArraycopy == null) {
-                Method method;
                 try {
-                    method = System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
-                } catch (NoSuchMethodException | SecurityException e) {
+                    originalArraycopy = findMethod(providers.getMetaAccess(), System.class, "arraycopy");
+                } catch (SecurityException e) {
                     throw new GraalError(e);
                 }
-                originalArraycopy = providers.getMetaAccess().lookupJavaMethod(method);
             }
             return originalArraycopy;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java	Wed Dec 12 08:38:45 2018 -0500
@@ -56,11 +56,11 @@
     protected final boolean compileTimeAssertion;
     protected final String message;
 
-    public AssertionNode(boolean compileTimeAssertion, ValueNode condition, String message) {
+    public AssertionNode(boolean compileTimeAssertion, ValueNode condition, String message, Object arg1, Object arg2) {
         super(TYPE, StampFactory.forVoid());
         this.condition = condition;
         this.compileTimeAssertion = compileTimeAssertion;
-        this.message = message;
+        this.message = message + arg1 + arg2;
     }
 
     public ValueNode condition() {
@@ -112,5 +112,14 @@
     }
 
     @NodeIntrinsic
-    public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message);
+    public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message, @ConstantNodeParameter Object arg1,
+                    @ConstantNodeParameter Object arg2);
+
+    public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message) {
+        assertion(compileTimeAssertion, condition, message, "", "");
+    }
+
+    public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean condition, @ConstantNodeParameter String message, @ConstantNodeParameter Object arg1) {
+        assertion(compileTimeAssertion, condition, message, arg1, "");
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Wed Dec 12 08:38:45 2018 -0500
@@ -223,19 +223,17 @@
                 "jszip-utils/dist/jszip-utils.min.js",
                 "jszip-utils/dist/jszip-utils-ie.js",
                 "jszip-utils/dist/jszip-utils-ie.min.js",
-                "images/ui-bg_flat_0_aaaaaa_40x100.png",
+                "images/ui-bg_glass_65_dadada_1x400.png",
                 "images/ui-icons_454545_256x240.png",
                 "images/ui-bg_glass_95_fef1ec_1x400.png",
                 "images/ui-bg_glass_75_dadada_1x400.png",
                 "images/ui-bg_highlight-soft_75_cccccc_1x100.png",
                 "images/ui-icons_888888_256x240.png",
                 "images/ui-icons_2e83ff_256x240.png",
-                "images/ui-bg_glass_65_ffffff_1x400.png",
                 "images/ui-icons_cd0a0a_256x240.png",
                 "images/ui-bg_glass_55_fbf9ee_1x400.png",
                 "images/ui-icons_222222_256x240.png",
-                "images/ui-bg_glass_75_e6e6e6_1x400.png",
-                "images/ui-bg_flat_75_ffffff_40x100.png");
+                "images/ui-bg_glass_75_e6e6e6_1x400.png");
         DocFile f;
         for (String file : files) {
             DocPath filePath = DocPaths.JQUERY_FILES.resolve(file);
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_75_ffffff_40x100.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_65_dadada_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_65_ffffff_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_75_dadada_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_95_fef1ec_1x400.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-icons_222222_256x240.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-icons_2e83ff_256x240.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-icons_454545_256x240.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-icons_888888_256x240.png has changed
Binary file src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-icons_cd0a0a_256x240.png has changed
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css	Wed Dec 12 08:38:45 2018 -0500
@@ -1,8 +1,8 @@
-/*! jQuery UI - v1.11.4 - 2015-05-20
+/*! jQuery UI - v1.12.1 - 2018-12-06
 * http://jqueryui.com
 * Includes: core.css, autocomplete.css, menu.css, theme.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=custom-theme&bgImgOpacityError=95&bgImgOpacityHighlight=55&bgImgOpacityActive=65&bgImgOpacityHover=75&bgImgOpacityDefault=75&bgImgOpacityContent=75&bgImgOpacityHeader=75&cornerRadiusShadow=8px&offsetLeftShadow=-8px&offsetTopShadow=-8px&thicknessShadow=8px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=%23aaaaaa&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=%23aaaaaa&iconColorError=%23cd0a0a&fcError=%23cd0a0a&borderColorError=%23cd0a0a&bgTextureError=glass&bgColorError=%23fef1ec&iconColorHighlight=%232e83ff&fcHighlight=%23363636&borderColorHighlight=%23fcefa1&bgTextureHighlight=glass&bgColorHighlight=%23fbf9ee&iconColorActive=%23454545&fcActive=%23212121&borderColorActive=%23aaaaaa&bgTextureActive=glass&bgColorActive=%23dadada&iconColorHover=%23454545&fcHover=%23212121&borderColorHover=%23999999&bgTextureHover=glass&bgColorHover=%23dadada&iconColorDefault=%23888888&fcDefault=%23555555&borderColorDefault=%23d3d3d3&bgTextureDefault=glass&bgColorDefault=%23e6e6e6&iconColorContent=%23222222&fcContent=%23222222&borderColorContent=%23aaaaaa&bgTextureContent=flat&bgColorContent=%23ffffff&iconColorHeader=%23222222&fcHeader=%23222222&borderColorHeader=%23aaaaaa&bgTextureHeader=highlight_soft&bgColorHeader=%23cccccc&cornerRadius=4px&fwDefault=normal&fsDefault=1.1em&ffDefault=Verdana%2CArial%2Csans-serif
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
 
 /* Layout helpers
 ----------------------------------*/
@@ -38,9 +38,6 @@
 .ui-helper-clearfix:after {
 	clear: both;
 }
-.ui-helper-clearfix {
-	min-height: 0; /* support: IE7 */
-}
 .ui-helper-zfix {
 	width: 100%;
 	height: 100%;
@@ -60,20 +57,27 @@
 ----------------------------------*/
 .ui-state-disabled {
 	cursor: default !important;
+	pointer-events: none;
 }
 
 
 /* Icons
 ----------------------------------*/
-
-/* states and images */
 .ui-icon {
-	display: block;
+	display: inline-block;
+	vertical-align: middle;
+	margin-top: -.25em;
+	position: relative;
 	text-indent: -99999px;
 	overflow: hidden;
 	background-repeat: no-repeat;
 }
 
+.ui-widget-icon-block {
+	left: 50%;
+	margin-left: -8px;
+	display: block;
+}
 
 /* Misc visuals
 ----------------------------------*/
@@ -97,20 +101,21 @@
 	padding: 0;
 	margin: 0;
 	display: block;
-	outline: none;
+	outline: 0;
 }
 .ui-menu .ui-menu {
 	position: absolute;
 }
 .ui-menu .ui-menu-item {
-	position: relative;
 	margin: 0;
-	padding: 3px 1em 3px .4em;
 	cursor: pointer;
-	min-height: 0; /* support: IE7 */
 	/* support: IE10, see #8844 */
 	list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
 }
+.ui-menu .ui-menu-item-wrapper {
+	position: relative;
+	padding: 3px 1em 3px .4em;
+}
 .ui-menu .ui-menu-divider {
 	margin: 5px 0;
 	height: 0;
@@ -127,7 +132,7 @@
 .ui-menu-icons {
 	position: relative;
 }
-.ui-menu-icons .ui-menu-item {
+.ui-menu-icons .ui-menu-item-wrapper {
 	padding-left: 2em;
 }
 
@@ -162,9 +167,12 @@
 	font-family: Verdana,Arial,sans-serif;
 	font-size: 1em;
 }
+.ui-widget.ui-widget-content {
+	border: 1px solid #d3d3d3;
+}
 .ui-widget-content {
 	border: 1px solid #aaaaaa;
-	background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
+	background: #ffffff;
 	color: #222222;
 }
 .ui-widget-content a {
@@ -184,7 +192,13 @@
 ----------------------------------*/
 .ui-state-default,
 .ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
+.ui-widget-header .ui-state-default,
+.ui-button,
+
+/* We use html here because we need a greater specificity to make sure disabled
+works properly when clicked or hovered */
+html .ui-button.ui-state-disabled:hover,
+html .ui-button.ui-state-disabled:active {
 	border: 1px solid #d3d3d3;
 	background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
 	font-weight: normal;
@@ -192,7 +206,11 @@
 }
 .ui-state-default a,
 .ui-state-default a:link,
-.ui-state-default a:visited {
+.ui-state-default a:visited,
+a.ui-button,
+a:link.ui-button,
+a:visited.ui-button,
+.ui-button {
 	color: #555555;
 	text-decoration: none;
 }
@@ -201,7 +219,9 @@
 .ui-widget-header .ui-state-hover,
 .ui-state-focus,
 .ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
+.ui-widget-header .ui-state-focus,
+.ui-button:hover,
+.ui-button:focus {
 	border: 1px solid #999999;
 	background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
 	font-weight: normal;
@@ -214,18 +234,32 @@
 .ui-state-focus a,
 .ui-state-focus a:hover,
 .ui-state-focus a:link,
-.ui-state-focus a:visited {
+.ui-state-focus a:visited,
+a.ui-button:hover,
+a.ui-button:focus {
 	color: #212121;
 	text-decoration: none;
 }
+
+.ui-visual-focus {
+	box-shadow: 0 0 3px 1px rgb(94, 158, 214);
+}
 .ui-state-active,
 .ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
+.ui-widget-header .ui-state-active,
+a.ui-button:active,
+.ui-button:active,
+.ui-button.ui-state-active:hover {
 	border: 1px solid #aaaaaa;
-	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+	background: #dadada url("images/ui-bg_glass_65_dadada_1x400.png") 50% 50% repeat-x;
 	font-weight: normal;
 	color: #212121;
 }
+.ui-icon-background,
+.ui-state-active .ui-icon-background {
+	border: #aaaaaa;
+	background-color: #212121;
+}
 .ui-state-active a,
 .ui-state-active a:link,
 .ui-state-active a:visited {
@@ -242,6 +276,10 @@
 	background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
 	color: #363636;
 }
+.ui-state-checked {
+	border: 1px solid #fcefa1;
+	background: #fbf9ee;
+}
 .ui-state-highlight a,
 .ui-widget-content .ui-state-highlight a,
 .ui-widget-header .ui-state-highlight a {
@@ -302,41 +340,45 @@
 .ui-widget-header .ui-icon {
 	background-image: url("images/ui-icons_222222_256x240.png");
 }
-.ui-state-default .ui-icon {
-	background-image: url("images/ui-icons_888888_256x240.png");
-}
 .ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
+.ui-state-focus .ui-icon,
+.ui-button:hover .ui-icon,
+.ui-button:focus .ui-icon {
 	background-image: url("images/ui-icons_454545_256x240.png");
 }
-.ui-state-active .ui-icon {
+.ui-state-active .ui-icon,
+.ui-button:active .ui-icon {
 	background-image: url("images/ui-icons_454545_256x240.png");
 }
-.ui-state-highlight .ui-icon {
+.ui-state-highlight .ui-icon,
+.ui-button .ui-state-highlight.ui-icon {
 	background-image: url("images/ui-icons_2e83ff_256x240.png");
 }
 .ui-state-error .ui-icon,
 .ui-state-error-text .ui-icon {
 	background-image: url("images/ui-icons_cd0a0a_256x240.png");
 }
+.ui-button .ui-icon {
+	background-image: url("images/ui-icons_888888_256x240.png");
+}
 
 /* positioning */
 .ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-caret-1-n { background-position: 0 0; }
+.ui-icon-caret-1-ne { background-position: -16px 0; }
+.ui-icon-caret-1-e { background-position: -32px 0; }
+.ui-icon-caret-1-se { background-position: -48px 0; }
+.ui-icon-caret-1-s { background-position: -65px 0; }
+.ui-icon-caret-1-sw { background-position: -80px 0; }
+.ui-icon-caret-1-w { background-position: -96px 0; }
+.ui-icon-caret-1-nw { background-position: -112px 0; }
+.ui-icon-caret-2-n-s { background-position: -128px 0; }
+.ui-icon-caret-2-e-w { background-position: -144px 0; }
 .ui-icon-triangle-1-n { background-position: 0 -16px; }
 .ui-icon-triangle-1-ne { background-position: -16px -16px; }
 .ui-icon-triangle-1-e { background-position: -32px -16px; }
 .ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-s { background-position: -65px -16px; }
 .ui-icon-triangle-1-sw { background-position: -80px -16px; }
 .ui-icon-triangle-1-w { background-position: -96px -16px; }
 .ui-icon-triangle-1-nw { background-position: -112px -16px; }
@@ -346,7 +388,7 @@
 .ui-icon-arrow-1-ne { background-position: -16px -32px; }
 .ui-icon-arrow-1-e { background-position: -32px -32px; }
 .ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-s { background-position: -65px -32px; }
 .ui-icon-arrow-1-sw { background-position: -80px -32px; }
 .ui-icon-arrow-1-w { background-position: -96px -32px; }
 .ui-icon-arrow-1-nw { background-position: -112px -32px; }
@@ -358,7 +400,7 @@
 .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
 .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
 .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
 .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
 .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
 .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
@@ -530,15 +572,11 @@
 
 /* Overlays */
 .ui-widget-overlay {
-	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+	background: #aaaaaa;
 	opacity: .3;
 	filter: Alpha(Opacity=30); /* support: IE8 */
 }
 .ui-widget-shadow {
-	margin: -8px 0 0 -8px;
-	padding: 8px;
-	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
-	opacity: .3;
-	filter: Alpha(Opacity=30); /* support: IE8 */
-	border-radius: 8px;
+	-webkit-box-shadow: -8px -8px 8px #aaaaaa;
+	box-shadow: -8px -8px 8px #aaaaaa;
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js	Wed Dec 12 08:38:45 2018 -0500
@@ -1,7 +1,7 @@
-/*! jQuery UI - v1.11.4 - 2015-05-20
+/*! jQuery UI - v1.12.1 - 2018-12-06
 * http://jqueryui.com
-* Includes: core.js, widget.js, position.js, autocomplete.js, menu.js
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+* Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
 
 (function( factory ) {
 	if ( typeof define === "function" && define.amd ) {
@@ -14,319 +14,36 @@
 		factory( jQuery );
 	}
 }(function( $ ) {
+
+$.ui = $.ui || {};
+
+var version = $.ui.version = "1.12.1";
+
+
 /*!
- * jQuery UI Core 1.11.4
+ * jQuery UI Widget 1.12.1
  * http://jqueryui.com
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license.
  * http://jquery.org/license
- *
- * http://api.jqueryui.com/category/ui-core/
  */
 
-
-// $.ui might exist from components with no dependencies, e.g., $.ui.position
-$.ui = $.ui || {};
-
-$.extend( $.ui, {
-	version: "1.11.4",
-
-	keyCode: {
-		BACKSPACE: 8,
-		COMMA: 188,
-		DELETE: 46,
-		DOWN: 40,
-		END: 35,
-		ENTER: 13,
-		ESCAPE: 27,
-		HOME: 36,
-		LEFT: 37,
-		PAGE_DOWN: 34,
-		PAGE_UP: 33,
-		PERIOD: 190,
-		RIGHT: 39,
-		SPACE: 32,
-		TAB: 9,
-		UP: 38
-	}
-});
-
-// plugins
-$.fn.extend({
-	scrollParent: function( includeHidden ) {
-		var position = this.css( "position" ),
-			excludeStaticParent = position === "absolute",
-			overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
-			scrollParent = this.parents().filter( function() {
-				var parent = $( this );
-				if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
-					return false;
-				}
-				return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
-			}).eq( 0 );
-
-		return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
-	},
-
-	uniqueId: (function() {
-		var uuid = 0;
-
-		return function() {
-			return this.each(function() {
-				if ( !this.id ) {
-					this.id = "ui-id-" + ( ++uuid );
-				}
-			});
-		};
-	})(),
-
-	removeUniqueId: function() {
-		return this.each(function() {
-			if ( /^ui-id-\d+$/.test( this.id ) ) {
-				$( this ).removeAttr( "id" );
-			}
-		});
-	}
-});
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
-	var map, mapName, img,
-		nodeName = element.nodeName.toLowerCase();
-	if ( "area" === nodeName ) {
-		map = element.parentNode;
-		mapName = map.name;
-		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
-			return false;
-		}
-		img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
-		return !!img && visible( img );
-	}
-	return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
-		!element.disabled :
-		"a" === nodeName ?
-			element.href || isTabIndexNotNaN :
-			isTabIndexNotNaN) &&
-		// the element and all of its ancestors must be visible
-		visible( element );
-}
-
-function visible( element ) {
-	return $.expr.filters.visible( element ) &&
-		!$( element ).parents().addBack().filter(function() {
-			return $.css( this, "visibility" ) === "hidden";
-		}).length;
-}
-
-$.extend( $.expr[ ":" ], {
-	data: $.expr.createPseudo ?
-		$.expr.createPseudo(function( dataName ) {
-			return function( elem ) {
-				return !!$.data( elem, dataName );
-			};
-		}) :
-		// support: jQuery <1.8
-		function( elem, i, match ) {
-			return !!$.data( elem, match[ 3 ] );
-		},
-
-	focusable: function( element ) {
-		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
-	},
-
-	tabbable: function( element ) {
-		var tabIndex = $.attr( element, "tabindex" ),
-			isTabIndexNaN = isNaN( tabIndex );
-		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
-	}
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
-	$.each( [ "Width", "Height" ], function( i, name ) {
-		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
-			type = name.toLowerCase(),
-			orig = {
-				innerWidth: $.fn.innerWidth,
-				innerHeight: $.fn.innerHeight,
-				outerWidth: $.fn.outerWidth,
-				outerHeight: $.fn.outerHeight
-			};
-
-		function reduce( elem, size, border, margin ) {
-			$.each( side, function() {
-				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
-				if ( border ) {
-					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
-				}
-				if ( margin ) {
-					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
-				}
-			});
-			return size;
-		}
-
-		$.fn[ "inner" + name ] = function( size ) {
-			if ( size === undefined ) {
-				return orig[ "inner" + name ].call( this );
-			}
-
-			return this.each(function() {
-				$( this ).css( type, reduce( this, size ) + "px" );
-			});
-		};
-
-		$.fn[ "outer" + name] = function( size, margin ) {
-			if ( typeof size !== "number" ) {
-				return orig[ "outer" + name ].call( this, size );
-			}
-
-			return this.each(function() {
-				$( this).css( type, reduce( this, size, true, margin ) + "px" );
-			});
-		};
-	});
-}
-
-// support: jQuery <1.8
-if ( !$.fn.addBack ) {
-	$.fn.addBack = function( selector ) {
-		return this.add( selector == null ?
-			this.prevObject : this.prevObject.filter( selector )
-		);
-	};
-}
-
-// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
-if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
-	$.fn.removeData = (function( removeData ) {
-		return function( key ) {
-			if ( arguments.length ) {
-				return removeData.call( this, $.camelCase( key ) );
-			} else {
-				return removeData.call( this );
-			}
-		};
-	})( $.fn.removeData );
-}
-
-// deprecated
-$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
-
-$.fn.extend({
-	focus: (function( orig ) {
-		return function( delay, fn ) {
-			return typeof delay === "number" ?
-				this.each(function() {
-					var elem = this;
-					setTimeout(function() {
-						$( elem ).focus();
-						if ( fn ) {
-							fn.call( elem );
-						}
-					}, delay );
-				}) :
-				orig.apply( this, arguments );
-		};
-	})( $.fn.focus ),
-
-	disableSelection: (function() {
-		var eventType = "onselectstart" in document.createElement( "div" ) ?
-			"selectstart" :
-			"mousedown";
-
-		return function() {
-			return this.bind( eventType + ".ui-disableSelection", function( event ) {
-				event.preventDefault();
-			});
-		};
-	})(),
-
-	enableSelection: function() {
-		return this.unbind( ".ui-disableSelection" );
-	},
-
-	zIndex: function( zIndex ) {
-		if ( zIndex !== undefined ) {
-			return this.css( "zIndex", zIndex );
-		}
-
-		if ( this.length ) {
-			var elem = $( this[ 0 ] ), position, value;
-			while ( elem.length && elem[ 0 ] !== document ) {
-				// Ignore z-index if position is set to a value where z-index is ignored by the browser
-				// This makes behavior of this function consistent across browsers
-				// WebKit always returns auto if the element is positioned
-				position = elem.css( "position" );
-				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
-					// IE returns 0 when zIndex is not specified
-					// other browsers return a string
-					// we ignore the case of nested elements with an explicit value of 0
-					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
-					value = parseInt( elem.css( "zIndex" ), 10 );
-					if ( !isNaN( value ) && value !== 0 ) {
-						return value;
-					}
-				}
-				elem = elem.parent();
-			}
-		}
-
-		return 0;
-	}
-});
-
-// $.ui.plugin is deprecated. Use $.widget() extensions instead.
-$.ui.plugin = {
-	add: function( module, option, set ) {
-		var i,
-			proto = $.ui[ module ].prototype;
-		for ( i in set ) {
-			proto.plugins[ i ] = proto.plugins[ i ] || [];
-			proto.plugins[ i ].push( [ option, set[ i ] ] );
-		}
-	},
-	call: function( instance, name, args, allowDisconnected ) {
-		var i,
-			set = instance.plugins[ name ];
-
-		if ( !set ) {
-			return;
-		}
-
-		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
-			return;
-		}
-
-		for ( i = 0; i < set.length; i++ ) {
-			if ( instance.options[ set[ i ][ 0 ] ] ) {
-				set[ i ][ 1 ].apply( instance.element, args );
-			}
-		}
-	}
-};
-
-
-/*!
- * jQuery UI Widget 1.11.4
- * http://jqueryui.com
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/jQuery.widget/
- */
-
-
-var widget_uuid = 0,
-	widget_slice = Array.prototype.slice;
-
-$.cleanData = (function( orig ) {
+//>>label: Widget
+//>>group: Core
+//>>description: Provides a factory for creating stateful widgets with a common API.
+//>>docs: http://api.jqueryui.com/jQuery.widget/
+//>>demos: http://jqueryui.com/widget/
+
+
+
+var widgetUuid = 0;
+var widgetSlice = Array.prototype.slice;
+
+$.cleanData = ( function( orig ) {
 	return function( elems ) {
 		var events, elem, i;
-		for ( i = 0; (elem = elems[i]) != null; i++ ) {
+		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
 			try {
 
 				// Only trigger remove when necessary to save time
@@ -335,29 +52,34 @@
 					$( elem ).triggerHandler( "remove" );
 				}
 
-			// http://bugs.jquery.com/ticket/8235
+			// Http://bugs.jquery.com/ticket/8235
 			} catch ( e ) {}
 		}
 		orig( elems );
 	};
-})( $.cleanData );
+} )( $.cleanData );
 
 $.widget = function( name, base, prototype ) {
-	var fullName, existingConstructor, constructor, basePrototype,
-		// proxiedPrototype allows the provided prototype to remain unmodified
-		// so that it can be used as a mixin for multiple widgets (#8876)
-		proxiedPrototype = {},
-		namespace = name.split( "." )[ 0 ];
-
+	var existingConstructor, constructor, basePrototype;
+
+	// ProxiedPrototype allows the provided prototype to remain unmodified
+	// so that it can be used as a mixin for multiple widgets (#8876)
+	var proxiedPrototype = {};
+
+	var namespace = name.split( "." )[ 0 ];
 	name = name.split( "." )[ 1 ];
-	fullName = namespace + "-" + name;
+	var fullName = namespace + "-" + name;
 
 	if ( !prototype ) {
 		prototype = base;
 		base = $.Widget;
 	}
 
-	// create selector for plugin
+	if ( $.isArray( prototype ) ) {
+		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
+	}
+
+	// Create selector for plugin
 	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
 		return !!$.data( elem, fullName );
 	};
@@ -365,30 +87,35 @@
 	$[ namespace ] = $[ namespace ] || {};
 	existingConstructor = $[ namespace ][ name ];
 	constructor = $[ namespace ][ name ] = function( options, element ) {
-		// allow instantiation without "new" keyword
+
+		// Allow instantiation without "new" keyword
 		if ( !this._createWidget ) {
 			return new constructor( options, element );
 		}
 
-		// allow instantiation without initializing for simple inheritance
+		// Allow instantiation without initializing for simple inheritance
 		// must use "new" keyword (the code above always passes args)
 		if ( arguments.length ) {
 			this._createWidget( options, element );
 		}
 	};
-	// extend with the existing constructor to carry over any static properties
+
+	// Extend with the existing constructor to carry over any static properties
 	$.extend( constructor, existingConstructor, {
 		version: prototype.version,
-		// copy the object used to create the prototype in case we need to
+
+		// Copy the object used to create the prototype in case we need to
 		// redefine the widget later
 		_proto: $.extend( {}, prototype ),
-		// track widgets that inherit from this widget in case this widget is
+
+		// Track widgets that inherit from this widget in case this widget is
 		// redefined after a widget inherits from it
 		_childConstructors: []
-	});
+	} );
 
 	basePrototype = new base();
-	// we need to make the options hash a property directly on the new instance
+
+	// We need to make the options hash a property directly on the new instance
 	// otherwise we'll modify the options hash on the prototype that we're
 	// inheriting from
 	basePrototype.options = $.widget.extend( {}, basePrototype.options );
@@ -397,17 +124,19 @@
 			proxiedPrototype[ prop ] = value;
 			return;
 		}
-		proxiedPrototype[ prop ] = (function() {
-			var _super = function() {
-					return base.prototype[ prop ].apply( this, arguments );
-				},
-				_superApply = function( args ) {
-					return base.prototype[ prop ].apply( this, args );
-				};
+		proxiedPrototype[ prop ] = ( function() {
+			function _super() {
+				return base.prototype[ prop ].apply( this, arguments );
+			}
+
+			function _superApply( args ) {
+				return base.prototype[ prop ].apply( this, args );
+			}
+
 			return function() {
-				var __super = this._super,
-					__superApply = this._superApply,
-					returnValue;
+				var __super = this._super;
+				var __superApply = this._superApply;
+				var returnValue;
 
 				this._super = _super;
 				this._superApply = _superApply;
@@ -419,19 +148,20 @@
 
 				return returnValue;
 			};
-		})();
-	});
+		} )();
+	} );
 	constructor.prototype = $.widget.extend( basePrototype, {
+
 		// TODO: remove support for widgetEventPrefix
 		// always use the name + a colon as the prefix, e.g., draggable:start
 		// don't prefix for widgets that aren't DOM-based
-		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
+		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
 	}, proxiedPrototype, {
 		constructor: constructor,
 		namespace: namespace,
 		widgetName: name,
 		widgetFullName: fullName
-	});
+	} );
 
 	// If this widget is being redefined then we need to find all widgets that
 	// are inheriting from it and redefine all of them so that they inherit from
@@ -441,11 +171,13 @@
 		$.each( existingConstructor._childConstructors, function( i, child ) {
 			var childPrototype = child.prototype;
 
-			// redefine the child widget using the same prototype that was
+			// Redefine the child widget using the same prototype that was
 			// originally used, but inherit from the new version of the base
-			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
-		});
-		// remove the list of existing child constructors from the old constructor
+			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
+				child._proto );
+		} );
+
+		// Remove the list of existing child constructors from the old constructor
 		// so the old child constructors can be garbage collected
 		delete existingConstructor._childConstructors;
 	} else {
@@ -458,21 +190,25 @@
 };
 
 $.widget.extend = function( target ) {
-	var input = widget_slice.call( arguments, 1 ),
-		inputIndex = 0,
-		inputLength = input.length,
-		key,
-		value;
+	var input = widgetSlice.call( arguments, 1 );
+	var inputIndex = 0;
+	var inputLength = input.length;
+	var key;
+	var value;
+
 	for ( ; inputIndex < inputLength; inputIndex++ ) {
 		for ( key in input[ inputIndex ] ) {
 			value = input[ inputIndex ][ key ];
 			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+
 				// Clone objects
 				if ( $.isPlainObject( value ) ) {
 					target[ key ] = $.isPlainObject( target[ key ] ) ?
 						$.widget.extend( {}, target[ key ], value ) :
+
 						// Don't extend strings, arrays, etc. with objects
 						$.widget.extend( {}, value );
+
 				// Copy everything else by reference
 				} else {
 					target[ key ] = value;
@@ -486,41 +222,55 @@
 $.widget.bridge = function( name, object ) {
 	var fullName = object.prototype.widgetFullName || name;
 	$.fn[ name ] = function( options ) {
-		var isMethodCall = typeof options === "string",
-			args = widget_slice.call( arguments, 1 ),
-			returnValue = this;
+		var isMethodCall = typeof options === "string";
+		var args = widgetSlice.call( arguments, 1 );
+		var returnValue = this;
 
 		if ( isMethodCall ) {
-			this.each(function() {
-				var methodValue,
-					instance = $.data( this, fullName );
-				if ( options === "instance" ) {
-					returnValue = instance;
-					return false;
-				}
-				if ( !instance ) {
-					return $.error( "cannot call methods on " + name + " prior to initialization; " +
-						"attempted to call method '" + options + "'" );
-				}
-				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
-					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
-				}
-				methodValue = instance[ options ].apply( instance, args );
-				if ( methodValue !== instance && methodValue !== undefined ) {
-					returnValue = methodValue && methodValue.jquery ?
-						returnValue.pushStack( methodValue.get() ) :
-						methodValue;
-					return false;
-				}
-			});
+
+			// If this is an empty collection, we need to have the instance method
+			// return undefined instead of the jQuery instance
+			if ( !this.length && options === "instance" ) {
+				returnValue = undefined;
+			} else {
+				this.each( function() {
+					var methodValue;
+					var instance = $.data( this, fullName );
+
+					if ( options === "instance" ) {
+						returnValue = instance;
+						return false;
+					}
+
+					if ( !instance ) {
+						return $.error( "cannot call methods on " + name +
+							" prior to initialization; " +
+							"attempted to call method '" + options + "'" );
+					}
+
+					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
+						return $.error( "no such method '" + options + "' for " + name +
+							" widget instance" );
+					}
+
+					methodValue = instance[ options ].apply( instance, args );
+
+					if ( methodValue !== instance && methodValue !== undefined ) {
+						returnValue = methodValue && methodValue.jquery ?
+							returnValue.pushStack( methodValue.get() ) :
+							methodValue;
+						return false;
+					}
+				} );
+			}
 		} else {
 
 			// Allow multiple hashes to be passed on init
 			if ( args.length ) {
-				options = $.widget.extend.apply( null, [ options ].concat(args) );
+				options = $.widget.extend.apply( null, [ options ].concat( args ) );
 			}
 
-			this.each(function() {
+			this.each( function() {
 				var instance = $.data( this, fullName );
 				if ( instance ) {
 					instance.option( options || {} );
@@ -530,7 +280,7 @@
 				} else {
 					$.data( this, fullName, new object( options, this ) );
 				}
-			});
+			} );
 		}
 
 		return returnValue;
@@ -544,21 +294,25 @@
 	widgetName: "widget",
 	widgetEventPrefix: "",
 	defaultElement: "<div>",
+
 	options: {
+		classes: {},
 		disabled: false,
 
-		// callbacks
+		// Callbacks
 		create: null
 	},
+
 	_createWidget: function( options, element ) {
 		element = $( element || this.defaultElement || this )[ 0 ];
 		this.element = $( element );
-		this.uuid = widget_uuid++;
+		this.uuid = widgetUuid++;
 		this.eventNamespace = "." + this.widgetName + this.uuid;
 
 		this.bindings = $();
 		this.hoverable = $();
 		this.focusable = $();
+		this.classesElementLookup = {};
 
 		if ( element !== this ) {
 			$.data( element, this.widgetFullName, this );
@@ -568,13 +322,15 @@
 						this.destroy();
 					}
 				}
-			});
+			} );
 			this.document = $( element.style ?
-				// element within the document
+
+				// Element within the document
 				element.ownerDocument :
-				// element is window or document
+
+				// Element is window or document
 				element.document || element );
-			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
+			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
 		}
 
 		this.options = $.widget.extend( {},
@@ -583,36 +339,46 @@
 			options );
 
 		this._create();
+
+		if ( this.options.disabled ) {
+			this._setOptionDisabled( this.options.disabled );
+		}
+
 		this._trigger( "create", null, this._getCreateEventData() );
 		this._init();
 	},
-	_getCreateOptions: $.noop,
+
+	_getCreateOptions: function() {
+		return {};
+	},
+
 	_getCreateEventData: $.noop,
+
 	_create: $.noop,
+
 	_init: $.noop,
 
 	destroy: function() {
+		var that = this;
+
 		this._destroy();
-		// we can probably remove the unbind calls in 2.0
+		$.each( this.classesElementLookup, function( key, value ) {
+			that._removeClass( value, key );
+		} );
+
+		// We can probably remove the unbind calls in 2.0
 		// all event bindings should go through this._on()
 		this.element
-			.unbind( this.eventNamespace )
-			.removeData( this.widgetFullName )
-			// support: jquery <1.6.3
-			// http://bugs.jquery.com/ticket/9413
-			.removeData( $.camelCase( this.widgetFullName ) );
+			.off( this.eventNamespace )
+			.removeData( this.widgetFullName );
 		this.widget()
-			.unbind( this.eventNamespace )
-			.removeAttr( "aria-disabled" )
-			.removeClass(
-				this.widgetFullName + "-disabled " +
-				"ui-state-disabled" );
-
-		// clean up events and states
-		this.bindings.unbind( this.eventNamespace );
-		this.hoverable.removeClass( "ui-state-hover" );
-		this.focusable.removeClass( "ui-state-focus" );
+			.off( this.eventNamespace )
+			.removeAttr( "aria-disabled" );
+
+		// Clean up events and states
+		this.bindings.off( this.eventNamespace );
 	},
+
 	_destroy: $.noop,
 
 	widget: function() {
@@ -620,18 +386,20 @@
 	},
 
 	option: function( key, value ) {
-		var options = key,
-			parts,
-			curOption,
-			i;
+		var options = key;
+		var parts;
+		var curOption;
+		var i;
 
 		if ( arguments.length === 0 ) {
-			// don't return a reference to the internal hash
+
+			// Don't return a reference to the internal hash
 			return $.widget.extend( {}, this.options );
 		}
 
 		if ( typeof key === "string" ) {
-			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+
+			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
 			options = {};
 			parts = key.split( "." );
 			key = parts.shift();
@@ -658,6 +426,7 @@
 
 		return this;
 	},
+
 	_setOptions: function( options ) {
 		var key;
 
@@ -667,42 +436,152 @@
 
 		return this;
 	},
+
 	_setOption: function( key, value ) {
+		if ( key === "classes" ) {
+			this._setOptionClasses( value );
+		}
+
 		this.options[ key ] = value;
 
 		if ( key === "disabled" ) {
-			this.widget()
-				.toggleClass( this.widgetFullName + "-disabled", !!value );
-
-			// If the widget is becoming disabled, then nothing is interactive
-			if ( value ) {
-				this.hoverable.removeClass( "ui-state-hover" );
-				this.focusable.removeClass( "ui-state-focus" );
-			}
+			this._setOptionDisabled( value );
 		}
 
 		return this;
 	},
 
+	_setOptionClasses: function( value ) {
+		var classKey, elements, currentElements;
+
+		for ( classKey in value ) {
+			currentElements = this.classesElementLookup[ classKey ];
+			if ( value[ classKey ] === this.options.classes[ classKey ] ||
+					!currentElements ||
+					!currentElements.length ) {
+				continue;
+			}
+
+			// We are doing this to create a new jQuery object because the _removeClass() call
+			// on the next line is going to destroy the reference to the current elements being
+			// tracked. We need to save a copy of this collection so that we can add the new classes
+			// below.
+			elements = $( currentElements.get() );
+			this._removeClass( currentElements, classKey );
+
+			// We don't use _addClass() here, because that uses this.options.classes
+			// for generating the string of classes. We want to use the value passed in from
+			// _setOption(), this is the new value of the classes option which was passed to
+			// _setOption(). We pass this value directly to _classes().
+			elements.addClass( this._classes( {
+				element: elements,
+				keys: classKey,
+				classes: value,
+				add: true
+			} ) );
+		}
+	},
+
+	_setOptionDisabled: function( value ) {
+		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
+
+		// If the widget is becoming disabled, then nothing is interactive
+		if ( value ) {
+			this._removeClass( this.hoverable, null, "ui-state-hover" );
+			this._removeClass( this.focusable, null, "ui-state-focus" );
+		}
+	},
+
 	enable: function() {
-		return this._setOptions({ disabled: false });
+		return this._setOptions( { disabled: false } );
+	},
+
+	disable: function() {
+		return this._setOptions( { disabled: true } );
 	},
-	disable: function() {
-		return this._setOptions({ disabled: true });
+
+	_classes: function( options ) {
+		var full = [];
+		var that = this;
+
+		options = $.extend( {
+			element: this.element,
+			classes: this.options.classes || {}
+		}, options );
+
+		function processClassString( classes, checkOption ) {
+			var current, i;
+			for ( i = 0; i < classes.length; i++ ) {
+				current = that.classesElementLookup[ classes[ i ] ] || $();
+				if ( options.add ) {
+					current = $( $.unique( current.get().concat( options.element.get() ) ) );
+				} else {
+					current = $( current.not( options.element ).get() );
+				}
+				that.classesElementLookup[ classes[ i ] ] = current;
+				full.push( classes[ i ] );
+				if ( checkOption && options.classes[ classes[ i ] ] ) {
+					full.push( options.classes[ classes[ i ] ] );
+				}
+			}
+		}
+
+		this._on( options.element, {
+			"remove": "_untrackClassesElement"
+		} );
+
+		if ( options.keys ) {
+			processClassString( options.keys.match( /\S+/g ) || [], true );
+		}
+		if ( options.extra ) {
+			processClassString( options.extra.match( /\S+/g ) || [] );
+		}
+
+		return full.join( " " );
+	},
+
+	_untrackClassesElement: function( event ) {
+		var that = this;
+		$.each( that.classesElementLookup, function( key, value ) {
+			if ( $.inArray( event.target, value ) !== -1 ) {
+				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
+			}
+		} );
+	},
+
+	_removeClass: function( element, keys, extra ) {
+		return this._toggleClass( element, keys, extra, false );
+	},
+
+	_addClass: function( element, keys, extra ) {
+		return this._toggleClass( element, keys, extra, true );
+	},
+
+	_toggleClass: function( element, keys, extra, add ) {
+		add = ( typeof add === "boolean" ) ? add : extra;
+		var shift = ( typeof element === "string" || element === null ),
+			options = {
+				extra: shift ? keys : extra,
+				keys: shift ? element : keys,
+				element: shift ? this.element : element,
+				add: add
+			};
+		options.element.toggleClass( this._classes( options ), add );
+		return this;
 	},
 
 	_on: function( suppressDisabledCheck, element, handlers ) {
-		var delegateElement,
-			instance = this;
-
-		// no suppressDisabledCheck flag, shuffle arguments
+		var delegateElement;
+		var instance = this;
+
+		// No suppressDisabledCheck flag, shuffle arguments
 		if ( typeof suppressDisabledCheck !== "boolean" ) {
 			handlers = element;
 			element = suppressDisabledCheck;
 			suppressDisabledCheck = false;
 		}
 
-		// no element argument, shuffle and use this.element
+		// No element argument, shuffle and use this.element
 		if ( !handlers ) {
 			handlers = element;
 			element = this.element;
@@ -714,39 +593,41 @@
 
 		$.each( handlers, function( event, handler ) {
 			function handlerProxy() {
-				// allow widgets to customize the disabled handling
+
+				// Allow widgets to customize the disabled handling
 				// - disabled as an array instead of boolean
 				// - disabled class as method for disabling individual parts
 				if ( !suppressDisabledCheck &&
 						( instance.options.disabled === true ||
-							$( this ).hasClass( "ui-state-disabled" ) ) ) {
+						$( this ).hasClass( "ui-state-disabled" ) ) ) {
 					return;
 				}
 				return ( typeof handler === "string" ? instance[ handler ] : handler )
 					.apply( instance, arguments );
 			}
 
-			// copy the guid so direct unbinding works
+			// Copy the guid so direct unbinding works
 			if ( typeof handler !== "string" ) {
 				handlerProxy.guid = handler.guid =
 					handler.guid || handlerProxy.guid || $.guid++;
 			}
 
-			var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
-				eventName = match[1] + instance.eventNamespace,
-				selector = match[2];
+			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
+			var eventName = match[ 1 ] + instance.eventNamespace;
+			var selector = match[ 2 ];
+
 			if ( selector ) {
-				delegateElement.delegate( selector, eventName, handlerProxy );
+				delegateElement.on( eventName, selector, handlerProxy );
 			} else {
-				element.bind( eventName, handlerProxy );
+				element.on( eventName, handlerProxy );
 			}
-		});
+		} );
 	},
 
 	_off: function( element, eventName ) {
-		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
+		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
 			this.eventNamespace;
-		element.unbind( eventName ).undelegate( eventName );
+		element.off( eventName ).off( eventName );
 
 		// Clear the stack to avoid memory leaks (#10056)
 		this.bindings = $( this.bindings.not( element ).get() );
@@ -767,40 +648,41 @@
 		this.hoverable = this.hoverable.add( element );
 		this._on( element, {
 			mouseenter: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-hover" );
+				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
 			},
 			mouseleave: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-hover" );
+				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
 			}
-		});
+		} );
 	},
 
 	_focusable: function( element ) {
 		this.focusable = this.focusable.add( element );
 		this._on( element, {
 			focusin: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-focus" );
+				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
 			},
 			focusout: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-focus" );
+				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
 			}
-		});
+		} );
 	},
 
 	_trigger: function( type, event, data ) {
-		var prop, orig,
-			callback = this.options[ type ];
+		var prop, orig;
+		var callback = this.options[ type ];
 
 		data = data || {};
 		event = $.Event( event );
 		event.type = ( type === this.widgetEventPrefix ?
 			type :
 			this.widgetEventPrefix + type ).toLowerCase();
-		// the original event may come from any element
+
+		// The original event may come from any element
 		// so we need to reset the target on the new event
 		event.target = this.element[ 0 ];
 
-		// copy original event properties over to the new event
+		// Copy original event properties over to the new event
 		orig = event.originalEvent;
 		if ( orig ) {
 			for ( prop in orig ) {
@@ -812,7 +694,7 @@
 
 		this.element.trigger( event, data );
 		return !( $.isFunction( callback ) &&
-			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
+			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
 			event.isDefaultPrevented() );
 	}
 };
@@ -822,42 +704,47 @@
 		if ( typeof options === "string" ) {
 			options = { effect: options };
 		}
-		var hasOptions,
-			effectName = !options ?
-				method :
-				options === true || typeof options === "number" ?
-					defaultEffect :
-					options.effect || defaultEffect;
+
+		var hasOptions;
+		var effectName = !options ?
+			method :
+			options === true || typeof options === "number" ?
+				defaultEffect :
+				options.effect || defaultEffect;
+
 		options = options || {};
 		if ( typeof options === "number" ) {
 			options = { duration: options };
 		}
+
 		hasOptions = !$.isEmptyObject( options );
 		options.complete = callback;
+
 		if ( options.delay ) {
 			element.delay( options.delay );
 		}
+
 		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
 			element[ method ]( options );
 		} else if ( effectName !== method && element[ effectName ] ) {
 			element[ effectName ]( options.duration, options.easing, callback );
 		} else {
-			element.queue(function( next ) {
+			element.queue( function( next ) {
 				$( this )[ method ]();
 				if ( callback ) {
 					callback.call( element[ 0 ] );
 				}
 				next();
-			});
+			} );
 		}
 	};
-});
+} );
 
 var widget = $.widget;
 
 
 /*!
- * jQuery UI Position 1.11.4
+ * jQuery UI Position 1.12.1
  * http://jqueryui.com
  *
  * Copyright jQuery Foundation and other contributors
@@ -867,14 +754,17 @@
  * http://api.jqueryui.com/position/
  */
 
-(function() {
-
-$.ui = $.ui || {};
-
-var cachedScrollbarWidth, supportsOffsetFractions,
+//>>label: Position
+//>>group: Core
+//>>description: Positions elements relative to other elements.
+//>>docs: http://api.jqueryui.com/position/
+//>>demos: http://jqueryui.com/position/
+
+
+( function() {
+var cachedScrollbarWidth,
 	max = Math.max,
 	abs = Math.abs,
-	round = Math.round,
 	rhorizontal = /left|center|right/,
 	rvertical = /top|center|bottom/,
 	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
@@ -894,7 +784,7 @@
 }
 
 function getDimensions( elem ) {
-	var raw = elem[0];
+	var raw = elem[ 0 ];
 	if ( raw.nodeType === 9 ) {
 		return {
 			width: elem.width(),
@@ -929,8 +819,10 @@
 			return cachedScrollbarWidth;
 		}
 		var w1, w2,
-			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
-			innerDiv = div.children()[0];
+			div = $( "<div " +
+				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
+				"<div style='height:100px;width:auto;'></div></div>" ),
+			innerDiv = div.children()[ 0 ];
 
 		$( "body" ).append( div );
 		w1 = innerDiv.offsetWidth;
@@ -939,12 +831,12 @@
 		w2 = innerDiv.offsetWidth;
 
 		if ( w1 === w2 ) {
-			w2 = div[0].clientWidth;
+			w2 = div[ 0 ].clientWidth;
 		}
 
 		div.remove();
 
-		return (cachedScrollbarWidth = w1 - w2);
+		return ( cachedScrollbarWidth = w1 - w2 );
 	},
 	getScrollInfo: function( within ) {
 		var overflowX = within.isWindow || within.isDocument ? "" :
@@ -952,9 +844,9 @@
 			overflowY = within.isWindow || within.isDocument ? "" :
 				within.element.css( "overflow-y" ),
 			hasOverflowX = overflowX === "scroll" ||
-				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
+				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
 			hasOverflowY = overflowY === "scroll" ||
-				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
+				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
 		return {
 			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
 			height: hasOverflowX ? $.position.scrollbarWidth() : 0
@@ -962,20 +854,18 @@
 	},
 	getWithinInfo: function( element ) {
 		var withinElement = $( element || window ),
-			isWindow = $.isWindow( withinElement[0] ),
-			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
+			isWindow = $.isWindow( withinElement[ 0 ] ),
+			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
+			hasOffset = !isWindow && !isDocument;
 		return {
 			element: withinElement,
 			isWindow: isWindow,
 			isDocument: isDocument,
-			offset: withinElement.offset() || { left: 0, top: 0 },
+			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
 			scrollLeft: withinElement.scrollLeft(),
 			scrollTop: withinElement.scrollTop(),
-
-			// support: jQuery 1.6.x
-			// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
-			width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
-			height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
+			width: withinElement.outerWidth(),
+			height: withinElement.outerHeight()
 		};
 	}
 };
@@ -985,7 +875,7 @@
 		return _position.apply( this, arguments );
 	}
 
-	// make a copy, we don't want to modify arguments
+	// Make a copy, we don't want to modify arguments
 	options = $.extend( {}, options );
 
 	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
@@ -996,24 +886,26 @@
 		offsets = {};
 
 	dimensions = getDimensions( target );
-	if ( target[0].preventDefault ) {
-		// force left top to allow flipping
+	if ( target[ 0 ].preventDefault ) {
+
+		// Force left top to allow flipping
 		options.at = "left top";
 	}
 	targetWidth = dimensions.width;
 	targetHeight = dimensions.height;
 	targetOffset = dimensions.offset;
-	// clone to reuse original targetOffset later
+
+	// Clone to reuse original targetOffset later
 	basePosition = $.extend( {}, targetOffset );
 
-	// force my and at to have valid horizontal and vertical positions
+	// Force my and at to have valid horizontal and vertical positions
 	// if a value is missing or invalid, it will be converted to center
 	$.each( [ "my", "at" ], function() {
 		var pos = ( options[ this ] || "" ).split( " " ),
 			horizontalOffset,
 			verticalOffset;
 
-		if ( pos.length === 1) {
+		if ( pos.length === 1 ) {
 			pos = rhorizontal.test( pos[ 0 ] ) ?
 				pos.concat( [ "center" ] ) :
 				rvertical.test( pos[ 0 ] ) ?
@@ -1023,7 +915,7 @@
 		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
 		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
 
-		// calculate offsets
+		// Calculate offsets
 		horizontalOffset = roffset.exec( pos[ 0 ] );
 		verticalOffset = roffset.exec( pos[ 1 ] );
 		offsets[ this ] = [
@@ -1031,14 +923,14 @@
 			verticalOffset ? verticalOffset[ 0 ] : 0
 		];
 
-		// reduce to just the positions without the offsets
+		// Reduce to just the positions without the offsets
 		options[ this ] = [
 			rposition.exec( pos[ 0 ] )[ 0 ],
 			rposition.exec( pos[ 1 ] )[ 0 ]
 		];
-	});
-
-	// normalize collision option
+	} );
+
+	// Normalize collision option
 	if ( collision.length === 1 ) {
 		collision[ 1 ] = collision[ 0 ];
 	}
@@ -1059,15 +951,17 @@
 	basePosition.left += atOffset[ 0 ];
 	basePosition.top += atOffset[ 1 ];
 
-	return this.each(function() {
+	return this.each( function() {
 		var collisionPosition, using,
 			elem = $( this ),
 			elemWidth = elem.outerWidth(),
 			elemHeight = elem.outerHeight(),
 			marginLeft = parseCss( this, "marginLeft" ),
 			marginTop = parseCss( this, "marginTop" ),
-			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
-			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
+			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
+				scrollInfo.width,
+			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
+				scrollInfo.height,
 			position = $.extend( {}, basePosition ),
 			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
 
@@ -1086,12 +980,6 @@
 		position.left += myOffset[ 0 ];
 		position.top += myOffset[ 1 ];
 
-		// if the browser doesn't support fractions, then round for consistent results
-		if ( !supportsOffsetFractions ) {
-			position.left = round( position.left );
-			position.top = round( position.top );
-		}
-
 		collisionPosition = {
 			marginLeft: marginLeft,
 			marginTop: marginTop
@@ -1112,12 +1000,13 @@
 					at: options.at,
 					within: within,
 					elem: elem
-				});
+				} );
 			}
-		});
+		} );
 
 		if ( options.using ) {
-			// adds feedback as second argument to using callback, if present
+
+			// Adds feedback as second argument to using callback, if present
 			using = function( props ) {
 				var left = targetOffset.left - position.left,
 					right = left + targetWidth - elemWidth,
@@ -1157,7 +1046,7 @@
 		}
 
 		elem.offset( $.extend( position, { using: using } ) );
-	});
+	} );
 };
 
 $.ui.position = {
@@ -1171,16 +1060,20 @@
 				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
 				newOverRight;
 
-			// element is wider than within
+			// Element is wider than within
 			if ( data.collisionWidth > outerWidth ) {
-				// element is initially over the left side of within
+
+				// Element is initially over the left side of within
 				if ( overLeft > 0 && overRight <= 0 ) {
-					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
+					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
+						withinOffset;
 					position.left += overLeft - newOverRight;
-				// element is initially over right side of within
+
+				// Element is initially over right side of within
 				} else if ( overRight > 0 && overLeft <= 0 ) {
 					position.left = withinOffset;
-				// element is initially over both left and right sides of within
+
+				// Element is initially over both left and right sides of within
 				} else {
 					if ( overLeft > overRight ) {
 						position.left = withinOffset + outerWidth - data.collisionWidth;
@@ -1188,13 +1081,16 @@
 						position.left = withinOffset;
 					}
 				}
-			// too far left -> align with left edge
+
+			// Too far left -> align with left edge
 			} else if ( overLeft > 0 ) {
 				position.left += overLeft;
-			// too far right -> align with right edge
+
+			// Too far right -> align with right edge
 			} else if ( overRight > 0 ) {
 				position.left -= overRight;
-			// adjust based on position and margin
+
+			// Adjust based on position and margin
 			} else {
 				position.left = max( position.left - collisionPosLeft, position.left );
 			}
@@ -1208,16 +1104,20 @@
 				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
 				newOverBottom;
 
-			// element is taller than within
+			// Element is taller than within
 			if ( data.collisionHeight > outerHeight ) {
-				// element is initially over the top of within
+
+				// Element is initially over the top of within
 				if ( overTop > 0 && overBottom <= 0 ) {
-					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
+					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
+						withinOffset;
 					position.top += overTop - newOverBottom;
-				// element is initially over bottom of within
+
+				// Element is initially over bottom of within
 				} else if ( overBottom > 0 && overTop <= 0 ) {
 					position.top = withinOffset;
-				// element is initially over both top and bottom of within
+
+				// Element is initially over both top and bottom of within
 				} else {
 					if ( overTop > overBottom ) {
 						position.top = withinOffset + outerHeight - data.collisionHeight;
@@ -1225,13 +1125,16 @@
 						position.top = withinOffset;
 					}
 				}
-			// too far up -> align with top
+
+			// Too far up -> align with top
 			} else if ( overTop > 0 ) {
 				position.top += overTop;
-			// too far down -> align with bottom edge
+
+			// Too far down -> align with bottom edge
 			} else if ( overBottom > 0 ) {
 				position.top -= overBottom;
-			// adjust based on position and margin
+
+			// Adjust based on position and margin
 			} else {
 				position.top = max( position.top - collisionPosTop, position.top );
 			}
@@ -1261,12 +1164,14 @@
 				newOverLeft;
 
 			if ( overLeft < 0 ) {
-				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
+				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
+					outerWidth - withinOffset;
 				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
 					position.left += myOffset + atOffset + offset;
 				}
 			} else if ( overRight > 0 ) {
-				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
+				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
+					atOffset + offset - offsetLeft;
 				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
 					position.left += myOffset + atOffset + offset;
 				}
@@ -1295,12 +1200,14 @@
 				newOverTop,
 				newOverBottom;
 			if ( overTop < 0 ) {
-				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
+				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
+					outerHeight - withinOffset;
 				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
 					position.top += myOffset + atOffset + offset;
 				}
 			} else if ( overBottom > 0 ) {
-				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
+				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
+					offset - offsetTop;
 				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
 					position.top += myOffset + atOffset + offset;
 				}
@@ -1319,79 +1226,152 @@
 	}
 };
 
-// fraction support test
-(function() {
-	var testElement, testElementParent, testElementStyle, offsetLeft, i,
-		body = document.getElementsByTagName( "body" )[ 0 ],
-		div = document.createElement( "div" );
-
-	//Create a "fake body" for testing based on method used in jQuery.support
-	testElement = document.createElement( body ? "div" : "body" );
-	testElementStyle = {
-		visibility: "hidden",
-		width: 0,
-		height: 0,
-		border: 0,
-		margin: 0,
-		background: "none"
-	};
-	if ( body ) {
-		$.extend( testElementStyle, {
-			position: "absolute",
-			left: "-1000px",
-			top: "-1000px"
-		});
-	}
-	for ( i in testElementStyle ) {
-		testElement.style[ i ] = testElementStyle[ i ];
-	}
-	testElement.appendChild( div );
-	testElementParent = body || document.documentElement;
-	testElementParent.insertBefore( testElement, testElementParent.firstChild );
-
-	div.style.cssText = "position: absolute; left: 10.7432222px;";
-
-	offsetLeft = $( div ).offset().left;
-	supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
-
-	testElement.innerHTML = "";
-	testElementParent.removeChild( testElement );
-})();
-
-})();
+} )();
 
 var position = $.ui.position;
 
 
 /*!
- * jQuery UI Menu 1.11.4
+ * jQuery UI Keycode 1.12.1
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Keycode
+//>>group: Core
+//>>description: Provide keycodes as keynames
+//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
+
+
+var keycode = $.ui.keyCode = {
+	BACKSPACE: 8,
+	COMMA: 188,
+	DELETE: 46,
+	DOWN: 40,
+	END: 35,
+	ENTER: 13,
+	ESCAPE: 27,
+	HOME: 36,
+	LEFT: 37,
+	PAGE_DOWN: 34,
+	PAGE_UP: 33,
+	PERIOD: 190,
+	RIGHT: 39,
+	SPACE: 32,
+	TAB: 9,
+	UP: 38
+};
+
+
+/*!
+ * jQuery UI Unique ID 1.12.1
  * http://jqueryui.com
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license.
  * http://jquery.org/license
- *
- * http://api.jqueryui.com/menu/
  */
 
-
-var menu = $.widget( "ui.menu", {
-	version: "1.11.4",
+//>>label: uniqueId
+//>>group: Core
+//>>description: Functions to generate and remove uniqueId's
+//>>docs: http://api.jqueryui.com/uniqueId/
+
+
+
+var uniqueId = $.fn.extend( {
+	uniqueId: ( function() {
+		var uuid = 0;
+
+		return function() {
+			return this.each( function() {
+				if ( !this.id ) {
+					this.id = "ui-id-" + ( ++uuid );
+				}
+			} );
+		};
+	} )(),
+
+	removeUniqueId: function() {
+		return this.each( function() {
+			if ( /^ui-id-\d+$/.test( this.id ) ) {
+				$( this ).removeAttr( "id" );
+			}
+		} );
+	}
+} );
+
+
+
+var safeActiveElement = $.ui.safeActiveElement = function( document ) {
+	var activeElement;
+
+	// Support: IE 9 only
+	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
+	try {
+		activeElement = document.activeElement;
+	} catch ( error ) {
+		activeElement = document.body;
+	}
+
+	// Support: IE 9 - 11 only
+	// IE may return null instead of an element
+	// Interestingly, this only seems to occur when NOT in an iframe
+	if ( !activeElement ) {
+		activeElement = document.body;
+	}
+
+	// Support: IE 11 only
+	// IE11 returns a seemingly empty object in some cases when accessing
+	// document.activeElement from an <iframe>
+	if ( !activeElement.nodeName ) {
+		activeElement = document.body;
+	}
+
+	return activeElement;
+};
+
+
+/*!
+ * jQuery UI Menu 1.12.1
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Menu
+//>>group: Widgets
+//>>description: Creates nestable menus.
+//>>docs: http://api.jqueryui.com/menu/
+//>>demos: http://jqueryui.com/menu/
+//>>css.structure: ../../themes/base/core.css
+//>>css.structure: ../../themes/base/menu.css
+//>>css.theme: ../../themes/base/theme.css
+
+
+
+var widgetsMenu = $.widget( "ui.menu", {
+	version: "1.12.1",
 	defaultElement: "<ul>",
 	delay: 300,
 	options: {
 		icons: {
-			submenu: "ui-icon-carat-1-e"
+			submenu: "ui-icon-caret-1-e"
 		},
 		items: "> *",
 		menus: "ul",
 		position: {
-			my: "left-1 top",
+			my: "left top",
 			at: "right top"
 		},
 		role: "menu",
 
-		// callbacks
+		// Callbacks
 		blur: null,
 		focus: null,
 		select: null
@@ -1405,20 +1385,14 @@
 		this.mouseHandled = false;
 		this.element
 			.uniqueId()
-			.addClass( "ui-menu ui-widget ui-widget-content" )
-			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
-			.attr({
+			.attr( {
 				role: this.options.role,
 				tabIndex: 0
-			});
-
-		if ( this.options.disabled ) {
-			this.element
-				.addClass( "ui-state-disabled" )
-				.attr( "aria-disabled", "true" );
-		}
-
-		this._on({
+			} );
+
+		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
+		this._on( {
+
 			// Prevent focus from sticking to links inside menu after clicking
 			// them (focus should always stay on UL during navigation).
 			"mousedown .ui-menu-item": function( event ) {
@@ -1426,6 +1400,7 @@
 			},
 			"click .ui-menu-item": function( event ) {
 				var target = $( event.target );
+				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
 				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
 					this.select( event );
 
@@ -1437,7 +1412,8 @@
 					// Open submenu on click
 					if ( target.has( ".ui-menu" ).length ) {
 						this.expand( event );
-					} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
+					} else if ( !this.element.is( ":focus" ) &&
+							active.closest( ".ui-menu" ).length ) {
 
 						// Redirect focus to the menu
 						this.element.trigger( "focus", [ true ] );
@@ -1451,21 +1427,32 @@
 				}
 			},
 			"mouseenter .ui-menu-item": function( event ) {
+
 				// Ignore mouse events while typeahead is active, see #10458.
 				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
 				// is over an item in the menu
 				if ( this.previousFilter ) {
 					return;
 				}
-				var target = $( event.currentTarget );
+
+				var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
+					target = $( event.currentTarget );
+
+				// Ignore bubbled events on parent items, see #11641
+				if ( actualTarget[ 0 ] !== target[ 0 ] ) {
+					return;
+				}
+
 				// Remove ui-state-active class from siblings of the newly focused menu item
 				// to avoid a jump caused by adjacent elements both having a class with a border
-				target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
+				this._removeClass( target.siblings().children( ".ui-state-active" ),
+					null, "ui-state-active" );
 				this.focus( event, target );
 			},
 			mouseleave: "collapseAll",
 			"mouseleave .ui-menu": "collapseAll",
 			focus: function( event, keepActiveItem ) {
+
 				// If there's already an active item, keep it active
 				// If not, activate the first item
 				var item = this.active || this.element.find( this.options.items ).eq( 0 );
@@ -1475,14 +1462,18 @@
 				}
 			},
 			blur: function( event ) {
-				this._delay(function() {
-					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
+				this._delay( function() {
+					var notContained = !$.contains(
+						this.element[ 0 ],
+						$.ui.safeActiveElement( this.document[ 0 ] )
+					);
+					if ( notContained ) {
 						this.collapseAll( event );
 					}
-				});
+				} );
 			},
 			keydown: "_keydown"
-		});
+		} );
 
 		this.refresh();
 
@@ -1496,43 +1487,31 @@
 				// Reset the mouseHandled flag
 				this.mouseHandled = false;
 			}
-		});
+		} );
 	},
 
 	_destroy: function() {
+		var items = this.element.find( ".ui-menu-item" )
+				.removeAttr( "role aria-disabled" ),
+			submenus = items.children( ".ui-menu-item-wrapper" )
+				.removeUniqueId()
+				.removeAttr( "tabIndex role aria-haspopup" );
+
 		// Destroy (sub)menus
 		this.element
 			.removeAttr( "aria-activedescendant" )
 			.find( ".ui-menu" ).addBack()
-				.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
-				.removeAttr( "role" )
-				.removeAttr( "tabIndex" )
-				.removeAttr( "aria-labelledby" )
-				.removeAttr( "aria-expanded" )
-				.removeAttr( "aria-hidden" )
-				.removeAttr( "aria-disabled" )
+				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
+					"tabIndex" )
 				.removeUniqueId()
 				.show();
 
-		// Destroy menu items
-		this.element.find( ".ui-menu-item" )
-			.removeClass( "ui-menu-item" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-disabled" )
-			.removeUniqueId()
-			.removeClass( "ui-state-hover" )
-			.removeAttr( "tabIndex" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-haspopup" )
-			.children().each( function() {
-				var elem = $( this );
-				if ( elem.data( "ui-menu-submenu-carat" ) ) {
-					elem.remove();
-				}
-			});
-
-		// Destroy menu dividers
-		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
+		submenus.children().each( function() {
+			var elem = $( this );
+			if ( elem.data( "ui-menu-submenu-caret" ) ) {
+				elem.remove();
+			}
+		} );
 	},
 
 	_keydown: function( event ) {
@@ -1576,9 +1555,12 @@
 		default:
 			preventDefault = false;
 			prev = this.previousFilter || "";
-			character = String.fromCharCode( event.keyCode );
 			skip = false;
 
+			// Support number pad values
+			character = event.keyCode >= 96 && event.keyCode <= 105 ?
+				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
+
 			clearTimeout( this.filterTimer );
 
 			if ( character === prev ) {
@@ -1602,7 +1584,7 @@
 			if ( match.length ) {
 				this.focus( event, match );
 				this.previousFilter = character;
-				this.filterTimer = this._delay(function() {
+				this.filterTimer = this._delay( function() {
 					delete this.previousFilter;
 				}, 1000 );
 			} else {
@@ -1616,8 +1598,8 @@
 	},
 
 	_activate: function( event ) {
-		if ( !this.active.is( ".ui-state-disabled" ) ) {
-			if ( this.active.is( "[aria-haspopup='true']" ) ) {
+		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
+			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
 				this.expand( event );
 			} else {
 				this.select( event );
@@ -1626,54 +1608,57 @@
 	},
 
 	refresh: function() {
-		var menus, items,
+		var menus, items, newSubmenus, newItems, newWrappers,
 			that = this,
 			icon = this.options.icons.submenu,
 			submenus = this.element.find( this.options.menus );
 
-		this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
+		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
 
 		// Initialize nested menus
-		submenus.filter( ":not(.ui-menu)" )
-			.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
+		newSubmenus = submenus.filter( ":not(.ui-menu)" )
 			.hide()
-			.attr({
+			.attr( {
 				role: this.options.role,
 				"aria-hidden": "true",
 				"aria-expanded": "false"
-			})
-			.each(function() {
+			} )
+			.each( function() {
 				var menu = $( this ),
-					item = menu.parent(),
-					submenuCarat = $( "<span>" )
-						.addClass( "ui-menu-icon ui-icon " + icon )
-						.data( "ui-menu-submenu-carat", true );
-
+					item = menu.prev(),
+					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
+
+				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
 				item
 					.attr( "aria-haspopup", "true" )
-					.prepend( submenuCarat );
+					.prepend( submenuCaret );
 				menu.attr( "aria-labelledby", item.attr( "id" ) );
-			});
+			} );
+
+		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
 
 		menus = submenus.add( this.element );
 		items = menus.find( this.options.items );
 
 		// Initialize menu-items containing spaces and/or dashes only as dividers
-		items.not( ".ui-menu-item" ).each(function() {
+		items.not( ".ui-menu-item" ).each( function() {
 			var item = $( this );
 			if ( that._isDivider( item ) ) {
-				item.addClass( "ui-widget-content ui-menu-divider" );
+				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
 			}
-		});
+		} );
 
 		// Don't refresh list items that are already adapted
-		items.not( ".ui-menu-item, .ui-menu-divider" )
-			.addClass( "ui-menu-item" )
-			.uniqueId()
-			.attr({
-				tabIndex: -1,
-				role: this._itemRole()
-			});
+		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
+		newWrappers = newItems.children()
+			.not( ".ui-menu" )
+				.uniqueId()
+				.attr( {
+					tabIndex: -1,
+					role: this._itemRole()
+				} );
+		this._addClass( newItems, "ui-menu-item" )
+			._addClass( newWrappers, "ui-menu-item-wrapper" );
 
 		// Add aria-disabled attribute to any disabled menu item
 		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
@@ -1693,26 +1678,31 @@
 
 	_setOption: function( key, value ) {
 		if ( key === "icons" ) {
-			this.element.find( ".ui-menu-icon" )
-				.removeClass( this.options.icons.submenu )
-				.addClass( value.submenu );
-		}
-		if ( key === "disabled" ) {
-			this.element
-				.toggleClass( "ui-state-disabled", !!value )
-				.attr( "aria-disabled", value );
+			var icons = this.element.find( ".ui-menu-icon" );
+			this._removeClass( icons, null, this.options.icons.submenu )
+				._addClass( icons, null, value.submenu );
 		}
 		this._super( key, value );
 	},
 
+	_setOptionDisabled: function( value ) {
+		this._super( value );
+
+		this.element.attr( "aria-disabled", String( value ) );
+		this._toggleClass( null, "ui-state-disabled", !!value );
+	},
+
 	focus: function( event, item ) {
-		var nested, focused;
+		var nested, focused, activeParent;
 		this.blur( event, event && event.type === "focus" );
 
 		this._scrollIntoView( item );
 
 		this.active = item.first();
-		focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
+
+		focused = this.active.children( ".ui-menu-item-wrapper" );
+		this._addClass( focused, null, "ui-state-active" );
+
 		// Only update aria-activedescendant if there's a role
 		// otherwise we assume focus is managed elsewhere
 		if ( this.options.role ) {
@@ -1720,22 +1710,23 @@
 		}
 
 		// Highlight active parent menu item, if any
-		this.active
+		activeParent = this.active
 			.parent()
-			.closest( ".ui-menu-item" )
-			.addClass( "ui-state-active" );
+				.closest( ".ui-menu-item" )
+					.children( ".ui-menu-item-wrapper" );
+		this._addClass( activeParent, null, "ui-state-active" );
 
 		if ( event && event.type === "keydown" ) {
 			this._close();
 		} else {
-			this.timer = this._delay(function() {
+			this.timer = this._delay( function() {
 				this._close();
 			}, this.delay );
 		}
 
 		nested = item.children( ".ui-menu" );
 		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
-			this._startOpening(nested);
+			this._startOpening( nested );
 		}
 		this.activeMenu = item.parent();
 
@@ -1745,8 +1736,8 @@
 	_scrollIntoView: function( item ) {
 		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
 		if ( this._hasScroll() ) {
-			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
-			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
+			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
+			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
 			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
 			scroll = this.activeMenu.scrollTop();
 			elementHeight = this.activeMenu.height();
@@ -1769,29 +1760,30 @@
 			return;
 		}
 
-		this.active.removeClass( "ui-state-focus" );
-		this.active = null;
+		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
+			null, "ui-state-active" );
 
 		this._trigger( "blur", event, { item: this.active } );
+		this.active = null;
 	},
 
 	_startOpening: function( submenu ) {
 		clearTimeout( this.timer );
 
 		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
-		// shift in the submenu position when mousing over the carat icon
+		// shift in the submenu position when mousing over the caret icon
 		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
 			return;
 		}
 
-		this.timer = this._delay(function() {
+		this.timer = this._delay( function() {
 			this._close();
 			this._open( submenu );
 		}, this.delay );
 	},
 
 	_open: function( submenu ) {
-		var position = $.extend({
+		var position = $.extend( {
 			of: this.active
 		}, this.options.position );
 
@@ -1809,12 +1801,14 @@
 
 	collapseAll: function( event, all ) {
 		clearTimeout( this.timer );
-		this.timer = this._delay(function() {
+		this.timer = this._delay( function() {
+
 			// If we were passed an event, look for the submenu that contains the event
 			var currentMenu = all ? this.element :
 				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
 
-			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
+			// If we found no valid submenu ancestor, use the main menu to close all
+			// sub menus anyway
 			if ( !currentMenu.length ) {
 				currentMenu = this.element;
 			}
@@ -1822,6 +1816,10 @@
 			this._close( currentMenu );
 
 			this.blur( event );
+
+			// Work around active item staying active after menu is blurred
+			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
+
 			this.activeMenu = currentMenu;
 		}, this.delay );
 	},
@@ -1833,14 +1831,10 @@
 			startMenu = this.active ? this.active.parent() : this.element;
 		}
 
-		startMenu
-			.find( ".ui-menu" )
-				.hide()
-				.attr( "aria-hidden", "true" )
-				.attr( "aria-expanded", "false" )
-			.end()
-			.find( ".ui-state-active" ).not( ".ui-state-focus" )
-				.removeClass( "ui-state-active" );
+		startMenu.find( ".ui-menu" )
+			.hide()
+			.attr( "aria-hidden", "true" )
+			.attr( "aria-expanded", "false" );
 	},
 
 	_closeOnDocumentClick: function( event ) {
@@ -1866,16 +1860,16 @@
 		var newItem = this.active &&
 			this.active
 				.children( ".ui-menu " )
-				.find( this.options.items )
-				.first();
+					.find( this.options.items )
+						.first();
 
 		if ( newItem && newItem.length ) {
 			this._open( newItem.parent() );
 
 			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
-			this._delay(function() {
+			this._delay( function() {
 				this.focus( event, newItem );
-			});
+			} );
 		}
 	},
 
@@ -1928,10 +1922,10 @@
 		if ( this._hasScroll() ) {
 			base = this.active.offset().top;
 			height = this.element.height();
-			this.active.nextAll( ".ui-menu-item" ).each(function() {
+			this.active.nextAll( ".ui-menu-item" ).each( function() {
 				item = $( this );
 				return item.offset().top - base - height < 0;
-			});
+			} );
 
 			this.focus( event, item );
 		} else {
@@ -1952,10 +1946,10 @@
 		if ( this._hasScroll() ) {
 			base = this.active.offset().top;
 			height = this.element.height();
-			this.active.prevAll( ".ui-menu-item" ).each(function() {
+			this.active.prevAll( ".ui-menu-item" ).each( function() {
 				item = $( this );
 				return item.offset().top - base + height > 0;
-			});
+			} );
 
 			this.focus( event, item );
 		} else {
@@ -1968,6 +1962,7 @@
 	},
 
 	select: function( event ) {
+
 		// TODO: It should never be possible to not have an active item at this
 		// point, but the tests don't trigger mouseenter before click.
 		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
@@ -1978,36 +1973,45 @@
 		this._trigger( "select", event, ui );
 	},
 
-	_filterMenuItems: function(character) {
+	_filterMenuItems: function( character ) {
 		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
 			regex = new RegExp( "^" + escapedCharacter, "i" );
 
 		return this.activeMenu
 			.find( this.options.items )
 
-			// Only match on items, not dividers or other content (#10571)
-			.filter( ".ui-menu-item" )
-			.filter(function() {
-				return regex.test( $.trim( $( this ).text() ) );
-			});
+				// Only match on items, not dividers or other content (#10571)
+				.filter( ".ui-menu-item" )
+					.filter( function() {
+						return regex.test(
+							$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
+					} );
 	}
-});
+} );
 
 
 /*!
- * jQuery UI Autocomplete 1.11.4
+ * jQuery UI Autocomplete 1.12.1
  * http://jqueryui.com
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license.
  * http://jquery.org/license
- *
- * http://api.jqueryui.com/autocomplete/
  */
 
+//>>label: Autocomplete
+//>>group: Widgets
+//>>description: Lists suggested words as the user is typing.
+//>>docs: http://api.jqueryui.com/autocomplete/
+//>>demos: http://jqueryui.com/autocomplete/
+//>>css.structure: ../../themes/base/core.css
+//>>css.structure: ../../themes/base/autocomplete.css
+//>>css.theme: ../../themes/base/theme.css
+
+
 
 $.widget( "ui.autocomplete", {
-	version: "1.11.4",
+	version: "1.12.1",
 	defaultElement: "<input>",
 	options: {
 		appendTo: null,
@@ -2021,7 +2025,7 @@
 		},
 		source: null,
 
-		// callbacks
+		// Callbacks
 		change: null,
 		close: null,
 		focus: null,
@@ -2035,6 +2039,7 @@
 	pending: 0,
 
 	_create: function() {
+
 		// Some browsers only repeat keydown events, not keypress events,
 		// so we use the suppressKeyPress flag to determine if we've already
 		// handled the keydown event. #7269
@@ -2047,21 +2052,17 @@
 			isTextarea = nodeName === "textarea",
 			isInput = nodeName === "input";
 
-		this.isMultiLine =
-			// Textareas are always multi-line
-			isTextarea ? true :
-			// Inputs are always single-line, even if inside a contentEditable element
-			// IE also treats inputs as contentEditable
-			isInput ? false :
-			// All other element types are determined by whether or not they're contentEditable
-			this.element.prop( "isContentEditable" );
+		// Textareas are always multi-line
+		// Inputs are always single-line, even if inside a contentEditable element
+		// IE also treats inputs as contentEditable
+		// All other element types are determined by whether or not they're contentEditable
+		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
 
 		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
 		this.isNewMenu = true;
 
-		this.element
-			.addClass( "ui-autocomplete-input" )
-			.attr( "autocomplete", "off" );
+		this._addClass( "ui-autocomplete-input" );
+		this.element.attr( "autocomplete", "off" );
 
 		this._on( this.element, {
 			keydown: function( event ) {
@@ -2094,8 +2095,10 @@
 					this._keyEvent( "next", event );
 					break;
 				case keyCode.ENTER:
+
 					// when menu is open and has focus
 					if ( this.menu.active ) {
+
 						// #6055 - Opera still allows the keypress to occur
 						// which causes forms to submit
 						suppressKeyPress = true;
@@ -2114,6 +2117,7 @@
 							this._value( this.term );
 						}
 						this.close( event );
+
 						// Different browsers have different default behavior for escape
 						// Single press can mean undo or clear
 						// Double press in IE means clear the whole form
@@ -2122,6 +2126,7 @@
 					break;
 				default:
 					suppressKeyPressRepeat = true;
+
 					// search timeout should be triggered before the input value is changed
 					this._searchTimeout( event );
 					break;
@@ -2139,7 +2144,7 @@
 					return;
 				}
 
-				// replicate some key handlers to allow them to repeat in Firefox and Opera
+				// Replicate some key handlers to allow them to repeat in Firefox and Opera
 				var keyCode = $.ui.keyCode;
 				switch ( event.keyCode ) {
 				case keyCode.PAGE_UP:
@@ -2178,51 +2183,46 @@
 				this.close( event );
 				this._change( event );
 			}
-		});
+		} );
 
 		this._initSource();
 		this.menu = $( "<ul>" )
-			.addClass( "ui-autocomplete ui-front" )
 			.appendTo( this._appendTo() )
-			.menu({
+			.menu( {
+
 				// disable ARIA support, the live region takes care of that
 				role: null
-			})
+			} )
 			.hide()
 			.menu( "instance" );
 
+		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
 		this._on( this.menu.element, {
 			mousedown: function( event ) {
+
 				// prevent moving focus out of the text field
 				event.preventDefault();
 
 				// IE doesn't prevent moving focus even with event.preventDefault()
 				// so we set a flag to know when we should ignore the blur event
 				this.cancelBlur = true;
-				this._delay(function() {
+				this._delay( function() {
 					delete this.cancelBlur;
-				});
-
-				// clicking on the scrollbar causes focus to shift to the body
-				// but we can't detect a mouseup or a click immediately afterward
-				// so we have to track the next mousedown and close the menu if
-				// the user clicks somewhere outside of the autocomplete
-				var menuElement = this.menu.element[ 0 ];
-				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
-					this._delay(function() {
-						var that = this;
-						this.document.one( "mousedown", function( event ) {
-							if ( event.target !== that.element[ 0 ] &&
-									event.target !== menuElement &&
-									!$.contains( menuElement, event.target ) ) {
-								that.close();
-							}
-						});
-					});
-				}
+
+					// Support: IE 8 only
+					// Right clicking a menu item or selecting text from the menu items will
+					// result in focus moving out of the input. However, we've already received
+					// and ignored the blur event because of the cancelBlur flag set above. So
+					// we restore focus to ensure that the menu closes properly based on the user's
+					// next actions.
+					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
+						this.element.trigger( "focus" );
+					}
+				} );
 			},
 			menufocus: function( event, ui ) {
 				var label, item;
+
 				// support: Firefox
 				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
 				if ( this.isNewMenu ) {
@@ -2232,7 +2232,7 @@
 
 						this.document.one( "mousemove", function() {
 							$( event.target ).trigger( event.originalEvent );
-						});
+						} );
 
 						return;
 					}
@@ -2240,6 +2240,7 @@
 
 				item = ui.item.data( "ui-autocomplete-item" );
 				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
+
 					// use value to match what will end up in the input, if it was a key event
 					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
 						this._value( item.value );
@@ -2257,22 +2258,24 @@
 				var item = ui.item.data( "ui-autocomplete-item" ),
 					previous = this.previous;
 
-				// only trigger when focus was lost (click on menu)
-				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
-					this.element.focus();
+				// Only trigger when focus was lost (click on menu)
+				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
+					this.element.trigger( "focus" );
 					this.previous = previous;
+
 					// #6109 - IE triggers two focus events and the second
 					// is asynchronous, so we need to reset the previous
 					// term synchronously and asynchronously :-(
-					this._delay(function() {
+					this._delay( function() {
 						this.previous = previous;
 						this.selectedItem = item;
-					});
+					} );
 				}
 
 				if ( false !== this._trigger( "select", event, { item: item } ) ) {
 					this._value( item.value );
 				}
+
 				// reset the term after the select event
 				// this allows custom select handling to work properly
 				this.term = this._value();
@@ -2280,31 +2283,30 @@
 				this.close( event );
 				this.selectedItem = item;
 			}
-		});
-
-		this.liveRegion = $( "<span>", {
-				role: "status",
-				"aria-live": "assertive",
-				"aria-relevant": "additions"
-			})
-			.addClass( "ui-helper-hidden-accessible" )
+		} );
+
+		this.liveRegion = $( "<div>", {
+			role: "status",
+			"aria-live": "assertive",
+			"aria-relevant": "additions"
+		} )
 			.appendTo( this.document[ 0 ].body );
 
-		// turning off autocomplete prevents the browser from remembering the
+		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
+
+		// Turning off autocomplete prevents the browser from remembering the
 		// value when navigating through history, so we re-enable autocomplete
 		// if the page is unloaded before the widget is destroyed. #7790
 		this._on( this.window, {
 			beforeunload: function() {
 				this.element.removeAttr( "autocomplete" );
 			}
-		});
+		} );
 	},
 
 	_destroy: function() {
 		clearTimeout( this.searching );
-		this.element
-			.removeClass( "ui-autocomplete-input" )
-			.removeAttr( "autocomplete" );
+		this.element.removeAttr( "autocomplete" );
 		this.menu.element.remove();
 		this.liveRegion.remove();
 	},
@@ -2322,6 +2324,20 @@
 		}
 	},
 
+	_isEventTargetInWidget: function( event ) {
+		var menuElement = this.menu.element[ 0 ];
+
+		return event.target === this.element[ 0 ] ||
+			event.target === menuElement ||
+			$.contains( menuElement, event.target );
+	},
+
+	_closeOnClickOutside: function( event ) {
+		if ( !this._isEventTargetInWidget( event ) ) {
+			this.close();
+		}
+	},
+
 	_appendTo: function() {
 		var element = this.options.appendTo;
 
@@ -2332,7 +2348,7 @@
 		}
 
 		if ( !element || !element[ 0 ] ) {
-			element = this.element.closest( ".ui-front" );
+			element = this.element.closest( ".ui-front, dialog" );
 		}
 
 		if ( !element.length ) {
@@ -2356,7 +2372,7 @@
 				if ( that.xhr ) {
 					that.xhr.abort();
 				}
-				that.xhr = $.ajax({
+				that.xhr = $.ajax( {
 					url: url,
 					data: request,
 					dataType: "json",
@@ -2364,9 +2380,9 @@
 						response( data );
 					},
 					error: function() {
-						response([]);
+						response( [] );
 					}
-				});
+				} );
 			};
 		} else {
 			this.source = this.options.source;
@@ -2375,7 +2391,7 @@
 
 	_searchTimeout: function( event ) {
 		clearTimeout( this.searching );
-		this.searching = this._delay(function() {
+		this.searching = this._delay( function() {
 
 			// Search if the value has changed, or if the user retypes the same value (see #7434)
 			var equalValues = this.term === this._value(),
@@ -2392,7 +2408,7 @@
 	search: function( value, event ) {
 		value = value != null ? value : this._value();
 
-		// always save the actual value, not the one passed as an argument
+		// Always save the actual value, not the one passed as an argument
 		this.term = this._value();
 
 		if ( value.length < this.options.minLength ) {
@@ -2408,7 +2424,7 @@
 
 	_search: function( value ) {
 		this.pending++;
-		this.element.addClass( "ui-autocomplete-loading" );
+		this._addClass( "ui-autocomplete-loading" );
 		this.cancelSearch = false;
 
 		this.source( { term: value }, this._response() );
@@ -2417,14 +2433,14 @@
 	_response: function() {
 		var index = ++this.requestIndex;
 
-		return $.proxy(function( content ) {
+		return $.proxy( function( content ) {
 			if ( index === this.requestIndex ) {
 				this.__response( content );
 			}
 
 			this.pending--;
 			if ( !this.pending ) {
-				this.element.removeClass( "ui-autocomplete-loading" );
+				this._removeClass( "ui-autocomplete-loading" );
 			}
 		}, this );
 	},
@@ -2438,6 +2454,7 @@
 			this._suggest( content );
 			this._trigger( "open" );
 		} else {
+
 			// use ._close() instead of .close() so we don't cancel future searches
 			this._close();
 		}
@@ -2449,6 +2466,10 @@
 	},
 
 	_close: function( event ) {
+
+		// Remove the handler that closes the menu on outside clicks
+		this._off( this.document, "mousedown" );
+
 		if ( this.menu.element.is( ":visible" ) ) {
 			this.menu.element.hide();
 			this.menu.blur();
@@ -2464,6 +2485,7 @@
 	},
 
 	_normalize: function( items ) {
+
 		// assume all items have the right format when the first item is complete
 		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
 			return items;
@@ -2478,8 +2500,8 @@
 			return $.extend( {}, item, {
 				label: item.label || item.value,
 				value: item.value || item.label
-			});
-		});
+			} );
+		} );
 	},
 
 	_suggest: function( items ) {
@@ -2488,21 +2510,27 @@
 		this.isNewMenu = true;
 		this.menu.refresh();
 
-		// size and position menu
+		// Size and position menu
 		ul.show();
 		this._resizeMenu();
-		ul.position( $.extend({
+		ul.position( $.extend( {
 			of: this.element
 		}, this.options.position ) );
 
 		if ( this.options.autoFocus ) {
 			this.menu.next();
 		}
+
+		// Listen for interactions outside of the widget (#6642)
+		this._on( this.document, {
+			mousedown: "_closeOnClickOutside"
+		} );
 	},
 
 	_resizeMenu: function() {
 		var ul = this.menu.element;
 		ul.outerWidth( Math.max(
+
 			// Firefox wraps long text (possibly a rounding bug)
 			// so we add 1px to avoid the wrapping (#7513)
 			ul.width( "" ).outerWidth() + 1,
@@ -2514,7 +2542,7 @@
 		var that = this;
 		$.each( items, function( index, item ) {
 			that._renderItemData( ul, item );
-		});
+		} );
 	},
 
 	_renderItemData: function( ul, item ) {
@@ -2522,7 +2550,9 @@
 	},
 
 	_renderItem: function( ul, item ) {
-		return $( "<li>" ).text( item.label ).appendTo( ul );
+		return $( "<li>" )
+			.append( $( "<div>" ).text( item.label ) )
+			.appendTo( ul );
 	},
 
 	_move: function( direction, event ) {
@@ -2555,11 +2585,29 @@
 		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
 			this._move( keyEvent, event );
 
-			// prevents moving cursor to beginning/end of the text field in some browsers
+			// Prevents moving cursor to beginning/end of the text field in some browsers
 			event.preventDefault();
 		}
+	},
+
+	// Support: Chrome <=50
+	// We should be able to just use this.element.prop( "isContentEditable" )
+	// but hidden elements always report false in Chrome.
+	// https://code.google.com/p/chromium/issues/detail?id=313082
+	_isContentEditable: function( element ) {
+		if ( !element.length ) {
+			return false;
+		}
+
+		var editable = element.prop( "contentEditable" );
+
+		if ( editable === "inherit" ) {
+		  return this._isContentEditable( element.parent() );
+		}
+
+		return editable === "true";
 	}
-});
+} );
 
 $.extend( $.ui.autocomplete, {
 	escapeRegex: function( value ) {
@@ -2569,11 +2617,11 @@
 		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
 		return $.grep( array, function( value ) {
 			return matcher.test( value.label || value.value || value );
-		});
+		} );
 	}
-});
-
-// live region extension, adding a `messages` option
+} );
+
+// Live region extension, adding a `messages` option
 // NOTE: This is an experimental API. We are still investigating
 // a full solution for string manipulation and internationalization.
 $.widget( "ui.autocomplete", $.ui.autocomplete, {
@@ -2601,10 +2649,11 @@
 		this.liveRegion.children().hide();
 		$( "<div>" ).text( message ).appendTo( this.liveRegion );
 	}
-});
-
-var autocomplete = $.ui.autocomplete;
-
-
-
-}));
+} );
+
+var widgetsAutocomplete = $.ui.autocomplete;
+
+
+
+
+}));
\ No newline at end of file
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css	Wed Dec 12 08:38:45 2018 -0500
@@ -1,7 +1,7 @@
-/*! jQuery UI - v1.11.4 - 2015-05-20
+/*! jQuery UI - v1.12.1 - 2018-12-06
 * http://jqueryui.com
 * Includes: core.css, autocomplete.css, menu.css, theme.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=custom-theme&bgImgOpacityError=95&bgImgOpacityHighlight=55&bgImgOpacityActive=65&bgImgOpacityHover=75&bgImgOpacityDefault=75&bgImgOpacityContent=75&bgImgOpacityHeader=75&cornerRadiusShadow=8px&offsetLeftShadow=-8px&offsetTopShadow=-8px&thicknessShadow=8px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=%23aaaaaa&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=%23aaaaaa&iconColorError=%23cd0a0a&fcError=%23cd0a0a&borderColorError=%23cd0a0a&bgTextureError=glass&bgColorError=%23fef1ec&iconColorHighlight=%232e83ff&fcHighlight=%23363636&borderColorHighlight=%23fcefa1&bgTextureHighlight=glass&bgColorHighlight=%23fbf9ee&iconColorActive=%23454545&fcActive=%23212121&borderColorActive=%23aaaaaa&bgTextureActive=glass&bgColorActive=%23dadada&iconColorHover=%23454545&fcHover=%23212121&borderColorHover=%23999999&bgTextureHover=glass&bgColorHover=%23dadada&iconColorDefault=%23888888&fcDefault=%23555555&borderColorDefault=%23d3d3d3&bgTextureDefault=glass&bgColorDefault=%23e6e6e6&iconColorContent=%23222222&fcContent=%23222222&borderColorContent=%23aaaaaa&bgTextureContent=flat&bgColorContent=%23ffffff&iconColorHeader=%23222222&fcHeader=%23222222&borderColorHeader=%23aaaaaa&bgTextureHeader=highlight_soft&bgColorHeader=%23cccccc&cornerRadius=4px&fwDefault=normal&fsDefault=1.1em&ffDefault=Verdana%2CArial%2Csans-serif
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
 
-.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #d3d3d3}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#212121;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #aaa;background:#dadada url("images/ui-bg_glass_65_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-icon-background,.ui-state-active .ui-icon-background{border:#aaa;background-color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-checked{border:1px solid #fcefa1;background:#fbf9ee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:-8px -8px 8px #aaa;box-shadow:-8px -8px 8px #aaa}
\ No newline at end of file
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js	Wed Dec 12 08:38:45 2018 -0500
@@ -1,7 +1,6 @@
-/*! jQuery UI - v1.11.4 - 2015-05-20
+/*! jQuery UI - v1.12.1 - 2018-12-06
 * http://jqueryui.com
-* Includes: core.js, widget.js, position.js, autocomplete.js, menu.js
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+* Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
 
-(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/^(input|select|textarea|button|object)$/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var s=0,n=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,a=n.call(arguments,1),o=0,r=a.length;r>o;o++)for(i in a[o])s=a[o][i],a[o].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=n.call(arguments,1),h=this;return o?this.each(function(){var i,n=e.data(this,s);return"instance"===a?(h=n,!1):n?e.isFunction(n[a])&&"_"!==a.charAt(0)?(i=n[a].apply(n,r),i!==n&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):(r.length&&(a=e.widget.extend.apply(null,[a].concat(r))),this.each(function(){var t=e.data(this,s);t?(t.option(a||{}),t._init&&t._init()):e.data(this,s,new i(a,this))})),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=s++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget,function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.width<t.element[0].scrollWidth,a="scroll"===s||"auto"===s&&t.height<t.element[0].scrollHeight;return{width:a?e.position.scrollbarWidth():0,height:n?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var i=e(t||window),s=e.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s||n?i.width():i.outerWidth(),height:s||n?i.height():i.outerHeight()}}},e.fn.position=function(n){if(!n||!n.of)return f.apply(this,arguments);n=e.extend({},n);var p,m,g,v,y,b,_=e(n.of),x=e.position.getWithinInfo(n.within),w=e.position.getScrollInfo(x),k=(n.collision||"flip").split(" "),T={};return b=s(_),_[0].preventDefault&&(n.at="left top"),m=b.width,g=b.height,v=b.offset,y=e.extend({},v),e.each(["my","at"],function(){var e,t,i=(n[this]||"").split(" ");1===i.length&&(i=l.test(i[0])?i.concat(["center"]):u.test(i[0])?["center"].concat(i):["center","center"]),i[0]=l.test(i[0])?i[0]:"center",i[1]=u.test(i[1])?i[1]:"center",e=d.exec(i[0]),t=d.exec(i[1]),T[this]=[e?e[0]:0,t?t[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===k.length&&(k[1]=k[0]),"right"===n.at[0]?y.left+=m:"center"===n.at[0]&&(y.left+=m/2),"bottom"===n.at[1]?y.top+=g:"center"===n.at[1]&&(y.top+=g/2),p=t(T.at,m,g),y.left+=p[0],y.top+=p[1],this.each(function(){var s,l,u=e(this),d=u.outerWidth(),c=u.outerHeight(),f=i(this,"marginLeft"),b=i(this,"marginTop"),D=d+f+i(this,"marginRight")+w.width,S=c+b+i(this,"marginBottom")+w.height,N=e.extend({},y),M=t(T.my,u.outerWidth(),u.outerHeight());"right"===n.my[0]?N.left-=d:"center"===n.my[0]&&(N.left-=d/2),"bottom"===n.my[1]?N.top-=c:"center"===n.my[1]&&(N.top-=c/2),N.left+=M[0],N.top+=M[1],a||(N.left=h(N.left),N.top=h(N.top)),s={marginLeft:f,marginTop:b},e.each(["left","top"],function(t,i){e.ui.position[k[t]]&&e.ui.position[k[t]][i](N,{targetWidth:m,targetHeight:g,elemWidth:d,elemHeight:c,collisionPosition:s,collisionWidth:D,collisionHeight:S,offset:[p[0]+M[0],p[1]+M[1]],my:n.my,at:n.at,within:x,elem:u})}),n.using&&(l=function(e){var t=v.left-N.left,i=t+m-d,s=v.top-N.top,a=s+g-c,h={target:{element:_,left:v.left,top:v.top,width:m,height:g},element:{element:u,left:N.left,top:N.top,width:d,height:c},horizontal:0>i?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(N,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.menu",{version:"1.11.4",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget);i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,i)},_filterMenuItems:function(t){var i=t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&"),s=RegExp("^"+i,"i");return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function(){return s.test(e.trim(e(this).text()))})}}),e.widget("ui.autocomplete",{version:"1.11.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e("<div>").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(":visible"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):void 0},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({},t,{label:t.label||t.value,value:t.value||t.label})})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()
-},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("<div>").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete});
+(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,o="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:o?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType,o=!s&&!n;return{element:i,isWindow:s,isDocument:n,offset:o?t(e).offset():{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:i.outerWidth(),height:i.outerHeight()}}},t.fn.position=function(n){if(!n||!n.of)return d.apply(this,arguments);n=t.extend({},n);var u,p,f,g,m,_,v=t(n.of),b=t.position.getWithinInfo(n.within),y=t.position.getScrollInfo(b),w=(n.collision||"flip").split(" "),k={};return _=s(v),v[0].preventDefault&&(n.at="left top"),p=_.width,f=_.height,g=_.offset,m=t.extend({},g),t.each(["my","at"],function(){var t,e,i=(n[this]||"").split(" ");1===i.length&&(i=r.test(i[0])?i.concat(["center"]):l.test(i[0])?["center"].concat(i):["center","center"]),i[0]=r.test(i[0])?i[0]:"center",i[1]=l.test(i[1])?i[1]:"center",t=h.exec(i[0]),e=h.exec(i[1]),k[this]=[t?t[0]:0,e?e[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===n.at[0]?m.left+=p:"center"===n.at[0]&&(m.left+=p/2),"bottom"===n.at[1]?m.top+=f:"center"===n.at[1]&&(m.top+=f/2),u=e(k.at,p,f),m.left+=u[0],m.top+=u[1],this.each(function(){var s,r,l=t(this),h=l.outerWidth(),c=l.outerHeight(),d=i(this,"marginLeft"),_=i(this,"marginTop"),x=h+d+i(this,"marginRight")+y.width,C=c+_+i(this,"marginBottom")+y.height,D=t.extend({},m),T=e(k.my,l.outerWidth(),l.outerHeight());"right"===n.my[0]?D.left-=h:"center"===n.my[0]&&(D.left-=h/2),"bottom"===n.my[1]?D.top-=c:"center"===n.my[1]&&(D.top-=c/2),D.left+=T[0],D.top+=T[1],s={marginLeft:d,marginTop:_},t.each(["left","top"],function(e,i){t.ui.position[w[e]]&&t.ui.position[w[e]][i](D,{targetWidth:p,targetHeight:f,elemWidth:h,elemHeight:c,collisionPosition:s,collisionWidth:x,collisionHeight:C,offset:[u[0]+T[0],u[1]+T[1]],my:n.my,at:n.at,within:b,elem:l})}),n.using&&(r=function(t){var e=g.left-D.left,i=e+p-h,s=g.top-D.top,r=s+f-c,u={target:{element:v,left:g.left,top:g.top,width:p,height:f},element:{element:l,left:D.left,top:D.top,width:h,height:c},horizontal:0>i?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.widget("ui.menu",{version:"1.12.1",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,l=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=l.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("<span>").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=l.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)},_filterMenuItems:function(e){var i=e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&"),s=RegExp("^"+i,"i");return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function(){return s.test(t.trim(t(this).children(".ui-menu-item-wrapper").text()))})}}),t.widget("ui.autocomplete",{version:"1.12.1",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n;this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("<ul>").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,this.element[0]!==t.ui.safeActiveElement(this.document[0])&&this.element.trigger("focus")})},menufocus:function(e,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",e,{item:n})&&e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&t.trim(s).length&&(this.liveRegion.children().hide(),t("<div>").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,i){var s=i.item.data("ui-autocomplete-item"),n=this.previous;this.element[0]!==t.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=n,this._delay(function(){this.previous=n,this.selectedItem=s})),!1!==this._trigger("select",e,{item:s})&&this._value(s.value),this.term=this._value(),this.close(e),this.selectedItem=s}}),this.liveRegion=t("<div>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(e){var i=this.menu.element[0];return e.target===this.element[0]||e.target===i||t.contains(i,e.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e&&e[0]||(e=this.element.closest(".ui-front, dialog")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){var e=this.term===this._value(),i=this.menu.element.is(":visible"),s=t.altKey||t.ctrlKey||t.metaKey||t.shiftKey;(!e||e&&!i&&!s)&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):void 0},_search:function(t){this.pending++,this._addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var e=++this.requestIndex;return t.proxy(function(t){e===this.requestIndex&&this.__response(t),this.pending--,this.pending||this._removeClass("ui-autocomplete-loading")},this)},__response:function(t){t&&(t=this._normalize(t)),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this._off(this.document,"mousedown"),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(e){return e.length&&e[0].label&&e[0].value?e:t.map(e,function(e){return"string"==typeof e?{label:e,value:e}:t.extend({},e,{label:e.label||e.value,value:e.value||e.label})})},_suggest:function(e){var i=this.menu.element.empty();this._renderMenu(i,e),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(t.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(),this._on(this.document,{mousedown:"_closeOnClickOutside"})},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(e,i){var s=this;t.each(i,function(t,i){s._renderItemData(e,i)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(e,i){return t("<li>").append(t("<div>").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[t](e),void 0):(this.search(null,e),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.children().hide(),t("<div>").text(i).appendTo(this.liveRegion))}}),t.ui.autocomplete});
\ No newline at end of file
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.structure.css	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.structure.css	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*!
- * jQuery UI CSS Framework 1.11.4
+ * jQuery UI CSS Framework 1.12.1
  * http://jqueryui.com
  *
  * Copyright jQuery Foundation and other contributors
@@ -8,7 +8,6 @@
  *
  * http://api.jqueryui.com/category/theming/
  */
-
 /* Layout helpers
 ----------------------------------*/
 .ui-helper-hidden {
@@ -43,9 +42,6 @@
 .ui-helper-clearfix:after {
 	clear: both;
 }
-.ui-helper-clearfix {
-	min-height: 0; /* support: IE7 */
-}
 .ui-helper-zfix {
 	width: 100%;
 	height: 100%;
@@ -65,20 +61,27 @@
 ----------------------------------*/
 .ui-state-disabled {
 	cursor: default !important;
+	pointer-events: none;
 }
 
 
 /* Icons
 ----------------------------------*/
-
-/* states and images */
 .ui-icon {
-	display: block;
+	display: inline-block;
+	vertical-align: middle;
+	margin-top: -.25em;
+	position: relative;
 	text-indent: -99999px;
 	overflow: hidden;
 	background-repeat: no-repeat;
 }
 
+.ui-widget-icon-block {
+	left: 50%;
+	margin-left: -8px;
+	display: block;
+}
 
 /* Misc visuals
 ----------------------------------*/
@@ -102,20 +105,21 @@
 	padding: 0;
 	margin: 0;
 	display: block;
-	outline: none;
+	outline: 0;
 }
 .ui-menu .ui-menu {
 	position: absolute;
 }
 .ui-menu .ui-menu-item {
-	position: relative;
 	margin: 0;
-	padding: 3px 1em 3px .4em;
 	cursor: pointer;
-	min-height: 0; /* support: IE7 */
 	/* support: IE10, see #8844 */
 	list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
 }
+.ui-menu .ui-menu-item-wrapper {
+	position: relative;
+	padding: 3px 1em 3px .4em;
+}
 .ui-menu .ui-menu-divider {
 	margin: 5px 0;
 	height: 0;
@@ -132,7 +136,7 @@
 .ui-menu-icons {
 	position: relative;
 }
-.ui-menu-icons .ui-menu-item {
+.ui-menu-icons .ui-menu-item-wrapper {
 	padding-left: 2em;
 }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.structure.min.css	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.structure.min.css	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
-/*! jQuery UI - v1.11.4 - 2015-05-20
+/*! jQuery UI - v1.12.1 - 2018-12-06
 * http://jqueryui.com
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
 
-.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}
\ No newline at end of file
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Wed Dec 12 08:38:45 2018 -0500
@@ -97,6 +97,7 @@
     _renderMenu: function(ul, items) {
         var rMenu = this,
                 currentCategory = "";
+        rMenu.menu.bindings = $();
         $.each(items, function(index, item) {
             var li;
             if (item.l !== noResult.l && item.category !== currentCategory) {
@@ -133,15 +134,16 @@
             label = item.l;
         }
         var li = $("<li/>").appendTo(ul);
+        var div = $("<div/>").appendTo(li);
         if (item.category === catSearchTags) {
             if (item.d) {
-                li.html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span><br><span class=\"searchTagDescResult\">"
+                div.html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span><br><span class=\"searchTagDescResult\">"
                                 + item.d + "</span><br>");
             } else {
-                li.html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span>");
+                div.html(label + "<span class=\"searchTagHolderResult\"> (" + item.h + ")</span>");
             }
         } else {
-            li.html(label);
+            div.html(label);
         }
         return li;
     }
--- a/src/jdk.javadoc/share/legal/jqueryUI.md	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.javadoc/share/legal/jqueryUI.md	Wed Dec 12 08:38:45 2018 -0500
@@ -1,4 +1,4 @@
-## jQuery UI v1.11.4
+## jQuery UI v1.12.1
 
 ### jQuery UI License
 ```
--- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Wed Dec 12 08:38:45 2018 -0500
@@ -82,6 +82,9 @@
 
 static char *names;                         /* strings derived from OnLoad options */
 
+static jboolean allowStartViaJcmd = JNI_FALSE;  /* if true we allow the debugging to be started via a jcmd */
+static jboolean startedViaJcmd = JNI_FALSE;     /* if false, we have not yet started debugging via a jcmd */
+
 /*
  * Elements of the transports bag
  */
@@ -870,6 +873,7 @@
  "launch=<command line>            run debugger on event             none\n"
  "onthrow=<exception name>         debug on throw                    none\n"
  "onuncaught=y|n                   debug on any uncaught?            n\n"
+ "onjcmd=y|n                       start debug via jcmd?             n\n"
  "timeout=<timeout value>          for listen/attach in milliseconds n\n"
  "mutf8=y|n                        output modified utf-8             n\n"
  "quiet=y|n                        control over terminal messages    n\n"));
@@ -1010,6 +1014,7 @@
     int length;
     char *str;
     char *errmsg;
+    jboolean onJcmd = JNI_FALSE;
 
     /* Set defaults */
     gdata->assertOn     = DEFAULT_ASSERT_ON;
@@ -1229,6 +1234,10 @@
             if ( !get_boolean(&str, &useStandardAlloc) ) {
                 goto syntax_error;
             }
+        } else if (strcmp(buf, "onjcmd") == 0) {
+            if (!get_boolean(&str, &onJcmd)) {
+                goto syntax_error;
+            }
         } else {
             goto syntax_error;
         }
@@ -1254,7 +1263,6 @@
         goto bad_option_with_errmsg;
     }
 
-
     if (!isServer) {
         jboolean specified = bagEnumerateOver(transports, checkAddress, NULL);
         if (!specified) {
@@ -1280,6 +1288,20 @@
         }
     }
 
+    if (onJcmd) {
+        if (launchOnInit != NULL) {
+            errmsg = "Cannot combine onjcmd and launch suboptions";
+            goto bad_option_with_errmsg;
+        }
+        if (!isServer) {
+            errmsg = "Can only use onjcmd with server=y";
+            goto bad_option_with_errmsg;
+        }
+        suspendOnInit = JNI_FALSE;
+        initOnStartup = JNI_FALSE;
+        allowStartViaJcmd = JNI_TRUE;
+    }
+
     return JNI_TRUE;
 
 syntax_error:
@@ -1348,3 +1370,45 @@
     // Last chance to die, this kills the entire process.
     forceExit(EXIT_JVMTI_ERROR);
 }
+
+static jboolean getFirstTransport(void *item, void *arg)
+{
+    TransportSpec** store = arg;
+    *store = item;
+
+    return JNI_FALSE; /* Want the first */
+}
+
+/* Call to start up debugging. */
+JNIEXPORT char const* JNICALL debugInit_startDebuggingViaCommand(JNIEnv* env, jthread thread, char const** transport_name,
+                                                                char const** address, jboolean* first_start) {
+    jboolean is_first_start = JNI_FALSE;
+    TransportSpec* spec = NULL;
+
+    if (!vmInitialized) {
+        return "Not yet initialized. Try again later.";
+    }
+
+    if (!allowStartViaJcmd) {
+        return "Starting debugging via jcmd was not enabled via the onjcmd option of the jdwp agent.";
+    }
+
+    if (!startedViaJcmd) {
+        startedViaJcmd = JNI_TRUE;
+        is_first_start = JNI_TRUE;
+        initialize(env, thread, EI_VM_INIT);
+    }
+
+    bagEnumerateOver(transports, getFirstTransport, &spec);
+
+    if ((spec != NULL) && (transport_name != NULL) && (address != NULL)) {
+        *transport_name = spec->name;
+        *address = spec->address;
+    }
+
+    if (first_start != NULL) {
+        *first_start = is_first_start;
+    }
+
+    return NULL;
+}
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, 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
@@ -25,6 +25,7 @@
 
 package jdk.internal.jshell.tool;
 
+
 import jdk.jshell.SourceCodeAnalysis.Documentation;
 import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
 import jdk.jshell.SourceCodeAnalysis.Suggestion;
@@ -32,7 +33,10 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InterruptedIOException;
+import java.io.OutputStream;
 import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -40,29 +44,39 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Locale;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import jdk.internal.shellsupport.doc.JavadocFormatter;
-import jdk.internal.jline.NoInterruptUnixTerminal;
-import jdk.internal.jline.Terminal;
-import jdk.internal.jline.TerminalFactory;
-import jdk.internal.jline.TerminalSupport;
-import jdk.internal.jline.WindowsTerminal;
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.KeyMap;
-import jdk.internal.jline.console.UserInterruptException;
-import jdk.internal.jline.console.history.History;
-import jdk.internal.jline.console.history.MemoryHistory;
-import jdk.internal.jline.extra.EditingHistory;
-import jdk.internal.jline.internal.NonBlockingInputStream;
 import jdk.internal.jshell.tool.StopDetectingInputStream.State;
 import jdk.internal.misc.Signal;
 import jdk.internal.misc.Signal.Handler;
+import jdk.internal.org.jline.keymap.KeyMap;
+import jdk.internal.org.jline.reader.Binding;
+import jdk.internal.org.jline.reader.EOFError;
+import jdk.internal.org.jline.reader.History;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.LineReader.Option;
+import jdk.internal.org.jline.reader.Parser;
+import jdk.internal.org.jline.reader.UserInterruptException;
+import jdk.internal.org.jline.reader.Widget;
+import jdk.internal.org.jline.reader.impl.LineReaderImpl;
+import jdk.internal.org.jline.reader.impl.completer.ArgumentCompleter.ArgumentLine;
+import jdk.internal.org.jline.reader.impl.history.DefaultHistory;
+import jdk.internal.org.jline.terminal.impl.LineDisciplineTerminal;
+import jdk.internal.org.jline.terminal.Attributes;
+import jdk.internal.org.jline.terminal.Attributes.ControlChar;
+import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal;
+import jdk.internal.org.jline.terminal.TerminalBuilder;
+import jdk.internal.org.jline.utils.Display;
+import jdk.internal.org.jline.utils.NonBlockingReader;
 import jdk.jshell.ExpressionSnippet;
 import jdk.jshell.Snippet;
 import jdk.jshell.Snippet.SubKind;
@@ -73,73 +87,117 @@
 
     private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_";
 
+    final boolean allowIncompleteInputs;
     final JShellTool repl;
     final StopDetectingInputStream input;
-    final ConsoleReader in;
-    final EditingHistory history;
-    final MemoryHistory userInputHistory = new MemoryHistory();
+    final Attributes originalAttributes;
+    final LineReaderImpl in;
+    final History userInputHistory = new DefaultHistory();
+    final Instant historyLoad;
 
     String prefix = "";
 
     ConsoleIOContext(JShellTool repl, InputStream cmdin, PrintStream cmdout) throws Exception {
+        this.allowIncompleteInputs = Boolean.getBoolean("jshell.test.allow.incomplete.inputs");
         this.repl = repl;
-        this.input = new StopDetectingInputStream(() -> repl.stop(), ex -> repl.hard("Error on input: %s", ex));
-        Terminal term;
+        Map<String, Object> variables = new HashMap<>();
+        this.input = new StopDetectingInputStream(() -> repl.stop(),
+                                                  ex -> repl.hard("Error on input: %s", ex));
+        Terminal terminal;
         if (System.getProperty("test.jdk") != null) {
-            term = new TestTerminal(input);
-        } else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) {
-            term = new JShellWindowsTerminal(input);
+            terminal = new TestTerminal(input, cmdout);
+            input.setInputStream(cmdin);
         } else {
-            term = new JShellUnixTerminal(input);
+            terminal = TerminalBuilder.builder().inputStreamWrapper(in -> {
+                input.setInputStream(in);
+                return input;
+            }).build();
         }
-        term.init();
-        CompletionState completionState = new CompletionState();
-        in = new ConsoleReader(cmdin, cmdout, term) {
-            @Override public KeyMap getKeys() {
-                return new CheckCompletionKeyMap(super.getKeys(), completionState);
+        originalAttributes = terminal.getAttributes();
+        Attributes noIntr = new Attributes(originalAttributes);
+        noIntr.setControlChar(ControlChar.VINTR, 0);
+        terminal.setAttributes(noIntr);
+        terminal.enterRawMode();
+        LineReaderImpl reader = new LineReaderImpl(terminal, "jshell", variables) {
+            {
+                //jline can handle the CONT signal on its own, but (currently) requires sun.misc for it
+                try {
+                    Signal.handle(new Signal("CONT"), new Handler() {
+                        @Override public void handle(Signal sig) {
+                            try {
+                                handleSignal(jdk.internal.org.jline.terminal.Terminal.Signal.CONT);
+                            } catch (Exception ex) {
+                                ex.printStackTrace();
+                            }
+                        }
+                    });
+                } catch (IllegalArgumentException ignored) {
+                    //the CONT signal does not exist on this platform
+                }
+            }
+            CompletionState completionState = new CompletionState();
+            @Override
+            protected boolean doComplete(CompletionType lst, boolean useMenu, boolean prefix) {
+                return ConsoleIOContext.this.complete(completionState);
             }
             @Override
-            protected boolean complete() throws IOException {
-                return ConsoleIOContext.this.complete(completionState);
+            public Binding readBinding(KeyMap<Binding> keys, KeyMap<Binding> local) {
+                completionState.actionCount++;
+                return super.readBinding(keys, local);
             }
         };
-        in.setExpandEvents(false);
-        in.setHandleUserInterrupt(true);
-        List<String> persistenHistory = Stream.of(repl.prefs.keys())
-                                              .filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
-                                              .sorted()
-                                              .map(key -> repl.prefs.get(key))
-                                              .collect(Collectors.toList());
-        in.setHistory(history = new EditingHistory(in, persistenHistory) {
-            @Override protected boolean isComplete(CharSequence input) {
-                return repl.analysis.analyzeCompletion(input.toString()).completeness().isComplete();
+
+        reader.setOpt(Option.DISABLE_EVENT_EXPANSION);
+
+        reader.setParser((line, cursor, context) -> {
+            if (!allowIncompleteInputs && !repl.isComplete(line)) {
+                throw new EOFError(cursor, cursor, line);
             }
+            return new ArgumentLine(line, cursor);
         });
-        in.setBellEnabled(true);
-        in.setCopyPasteDetection(true);
-        bind(FIXES_SHORTCUT, (Runnable) () -> fixes());
-        try {
-            Signal.handle(new Signal("CONT"), new Handler() {
-                @Override public void handle(Signal sig) {
-                    try {
-                        in.getTerminal().reset();
-                        in.redrawLine();
-                        in.flush();
-                    } catch (Exception ex) {
-                        ex.printStackTrace();
-                    }
-                }
-            });
-        } catch (IllegalArgumentException ignored) {
-            //the CONT signal does not exist on this platform
+
+        reader.getKeyMaps().get(LineReader.MAIN)
+              .bind((Widget) () -> fixes(), FIXES_SHORTCUT);
+        reader.getKeyMaps().get(LineReader.MAIN)
+              .bind((Widget) () -> { throw new UserInterruptException(""); }, "\003");
+
+        List<String> loadHistory = new ArrayList<>();
+        Stream.of(repl.prefs.keys())
+              .filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
+              .sorted()
+              .map(key -> repl.prefs.get(key))
+              .forEach(loadHistory::add);
+
+        for (ListIterator<String> it = loadHistory.listIterator(); it.hasNext(); ) {
+            String current = it.next();
+
+            int trailingBackSlashes = countTrailintBackslashes(current);
+            boolean continuation = trailingBackSlashes % 2 != 0;
+            current = current.substring(0, current.length() - trailingBackSlashes / 2 - (continuation ? 1 : 0));
+            if (continuation && it.hasNext()) {
+                String next = it.next();
+                it.remove();
+                it.previous();
+                current += "\n" + next;
+            }
+
+            it.set(current);
         }
+
+        historyLoad = Instant.now();
+        loadHistory.forEach(line -> reader.getHistory().add(historyLoad, line));
+
+        in = reader;
     }
 
     @Override
-    public String readLine(String prompt, String prefix) throws IOException, InputInterruptedException {
+    public String readLine(String firstLinePrompt, String continuationPrompt,
+                           boolean firstLine, String prefix) throws IOException, InputInterruptedException {
+        assert firstLine || allowIncompleteInputs;
         this.prefix = prefix;
         try {
-            return in.readLine(prompt);
+            in.setVariable(LineReader.SECONDARY_PROMPT_PATTERN, continuationPrompt);
+            return in.readLine(firstLinePrompt);
         } catch (UserInterruptException ex) {
             throw (InputInterruptedException) new InputInterruptedException().initCause(ex);
         }
@@ -152,7 +210,10 @@
 
     @Override
     public Iterable<String> history(boolean currentSession) {
-        return history.entries(currentSession);
+        return StreamSupport.stream(getHistory().spliterator(), false)
+                            .filter(entry -> !currentSession || !historyLoad.equals(entry.time()))
+                            .map(entry -> entry.line())
+                            .collect(Collectors.toList());
     }
 
     @Override
@@ -163,7 +224,11 @@
                 repl.prefs.remove(key);
             }
         }
-        Collection<? extends String> savedHistory = history.save();
+        Collection<String> savedHistory =
+            StreamSupport.stream(in.getHistory().spliterator(), false)
+                         .map(History.Entry::line)
+                         .flatMap(this::toSplitEntries)
+                         .collect(Collectors.toList());
         if (!savedHistory.isEmpty()) {
             int len = (int) Math.ceil(Math.log10(savedHistory.size()+1));
             String format = HISTORY_LINE_PREFIX + "%0" + len + "d";
@@ -173,25 +238,46 @@
             }
         }
         repl.prefs.flush();
-        in.close();
         try {
-            in.getTerminal().restore();
+            in.getTerminal().setAttributes(originalAttributes);
+            in.getTerminal().close();
         } catch (Exception ex) {
             throw new IOException(ex);
         }
         input.shutdown();
     }
 
-    private void bind(String shortcut, Object action) {
-        KeyMap km = in.getKeys();
-        for (int i = 0; i < shortcut.length(); i++) {
-            Object value = km.getBound(Character.toString(shortcut.charAt(i)));
-            if (value instanceof KeyMap) {
-                km = (KeyMap) value;
+    private Stream<String> toSplitEntries(String entry) {
+        String[] lines = entry.split("\n");
+        List<String> result = new ArrayList<>();
+
+        for (int i = 0; i < lines.length; i++) {
+            StringBuilder historyLine = new StringBuilder(lines[i]);
+            int trailingBackSlashes = countTrailintBackslashes(historyLine);
+            for (int j = 0; j < trailingBackSlashes; j++) {
+                historyLine.append("\\");
+            }
+            if (i + 1 < lines.length) {
+                historyLine.append("\\");
+            }
+            result.add(historyLine.toString());
+        }
+
+        return result.stream();
+    }
+
+    private int countTrailintBackslashes(CharSequence text) {
+        int count = 0;
+
+        for (int i = text.length() - 1; i >= 0; i--) {
+            if (text.charAt(i) == '\\') {
+                count++;
             } else {
-                km.bind(shortcut.substring(i), action);
+                break;
             }
         }
+
+        return count;
     }
 
     private static final String FIXES_SHORTCUT = "\033\133\132"; //Shift-TAB
@@ -199,6 +285,7 @@
     private static final String LINE_SEPARATOR = System.getProperty("line.separator");
     private static final String LINE_SEPARATORS2 = LINE_SEPARATOR + LINE_SEPARATOR;
 
+    /*XXX:*/private static final int AUTOPRINT_THRESHOLD = 100;
     @SuppressWarnings("fallthrough")
     private boolean complete(CompletionState completionState) {
         //The completion has multiple states (invoked by subsequent presses of <tab>).
@@ -206,8 +293,8 @@
         //and placed into the todo list (completionState.todo). The todo list is
         //then followed on both the first and subsequent completion invocations:
         try {
-            String text = in.getCursorBuffer().toString();
-            int cursor = in.getCursorBuffer().cursor;
+            String text = in.getBuffer().toString();
+            int cursor = in.getBuffer().cursor();
 
             List<CompletionTask> todo = completionState.todo;
 
@@ -230,13 +317,13 @@
                                        .collect(Collectors.toList());
                 }
                 long smartCount = suggestions.stream().filter(Suggestion::matchesType).count();
-                boolean hasSmart = smartCount > 0 && smartCount <= in.getAutoprintThreshold();
+                boolean hasSmart = smartCount > 0 && smartCount <= /*in.getAutoprintThreshold()*/AUTOPRINT_THRESHOLD;
                 boolean hasBoth = hasSmart &&
                                   suggestions.stream()
                                              .map(s -> s.matchesType())
                                              .distinct()
                                              .count() == 2;
-                boolean tooManyItems = suggestions.size() > in.getAutoprintThreshold();
+                boolean tooManyItems = suggestions.size() > /*in.getAutoprintThreshold()*/AUTOPRINT_THRESHOLD;
                 CompletionTask ordinaryCompletion =
                         new OrdinaryCompletionTask(suggestions,
                                                    anchor[0],
@@ -312,8 +399,8 @@
                         //intentional fall-through
                     case NO_DATA:
                         if (!todo.isEmpty()) {
-                            in.println();
-                            in.println(todo.get(0).description());
+                            in.getTerminal().writer().println();
+                            in.getTerminal().writer().println(todo.get(0).description());
                         }
                         break OUTER;
                 }
@@ -363,9 +450,9 @@
 
                         @Override
                         public Result perform(String text, int cursor) throws IOException {
-                            in.println();
+                            in.getTerminal().writer().println();
                             for (String line : thisPageLines) {
-                                in.println(line);
+                                in.getTerminal().writer().println(line);
                             }
                             return Result.FINISH;
                         }
@@ -431,9 +518,9 @@
 
         @Override
         public Result perform(String text, int cursor) throws IOException {
-            in.println();
-            in.println(repl.getResourceString("jshell.console.no.such.command"));
-            in.println();
+            in.getTerminal().writer().println();
+            in.getTerminal().writer().println(repl.getResourceString("jshell.console.no.such.command"));
+            in.getTerminal().writer().println();
             return Result.SKIP;
         }
 
@@ -494,8 +581,8 @@
             boolean showItems = toShow.size() > 1 || showSmart;
 
             if (showItems) {
-                in.println();
-                in.printColumns(toShow);
+                in.getTerminal().writer().println();
+                printColumns(toShow);
             }
 
             if (!prefixStr.isEmpty())
@@ -518,7 +605,7 @@
 
         @Override
         public String description() {
-            if (suggestions.size() <= in.getAutoprintThreshold()) {
+            if (suggestions.size() <= /*in.getAutoprintThreshold()*/AUTOPRINT_THRESHOLD) {
                 return repl.getResourceString("jshell.console.completion.all.completions");
             } else {
                 return repl.messageFormat("jshell.console.completion.all.completions.number", suggestions.size());
@@ -540,14 +627,34 @@
             String prefixStr = prefix.map(str -> str.substring(cursor - anchor)).orElse("");
             in.putString(prefixStr);
             if (candidates.size() > 1) {
-                in.println();
-                in.printColumns(candidates);
+                in.getTerminal().writer().println();
+                printColumns(candidates);
             }
             return suggestions.isEmpty() ? Result.NO_DATA : Result.FINISH;
         }
 
     }
 
+    private void printColumns(List<? extends CharSequence> candidates) {
+        if (candidates.isEmpty()) return ;
+        int size = candidates.stream().mapToInt(CharSequence::length).max().getAsInt() + 3;
+        int columns = in.getTerminal().getWidth() / size;
+        int c = 0;
+        for (CharSequence cand : candidates) {
+            in.getTerminal().writer().print(cand);
+            for (int s = cand.length(); s < size; s++) {
+                in.getTerminal().writer().print(" ");
+            }
+            if (++c == columns) {
+                in.getTerminal().writer().println();
+                c = 0;
+            }
+        }
+        if (c != 0) {
+            in.getTerminal().writer().println();
+        }
+    }
+
     private final class CommandSynopsisTask implements CompletionTask {
 
         private final List<String> synopsis;
@@ -563,14 +670,14 @@
 
         @Override
         public Result perform(String text, int cursor) throws IOException {
-            try {
-                in.println();
-                in.println(synopsis.stream()
+//            try {
+                in.getTerminal().writer().println();
+                in.getTerminal().writer().println(synopsis.stream()
                                    .map(l -> l.replaceAll("\n", LINE_SEPARATOR))
                                    .collect(Collectors.joining(LINE_SEPARATORS2)));
-            } catch (IOException ex) {
-                throw new IllegalStateException(ex);
-            }
+//            } catch (IOException ex) {
+//                throw new IllegalStateException(ex);
+//            }
             return Result.FINISH;
         }
 
@@ -612,9 +719,9 @@
 
         @Override
         public Result perform(String text, int cursor) throws IOException {
-            in.println();
-            in.println(repl.getResourceString("jshell.console.completion.current.signatures"));
-            in.println(doc.stream().collect(Collectors.joining(LINE_SEPARATOR)));
+            in.getTerminal().writer().println();
+            in.getTerminal().writer().println(repl.getResourceString("jshell.console.completion.current.signatures"));
+            in.getTerminal().writer().println(doc.stream().collect(Collectors.joining(LINE_SEPARATOR)));
             return Result.FINISH;
         }
 
@@ -638,7 +745,7 @@
             //schedule showing javadoc:
             Terminal term = in.getTerminal();
             JavadocFormatter formatter = new JavadocFormatter(term.getWidth(),
-                                                              term.isAnsiSupported());
+                                                              true);
             Function<Documentation, String> convertor = d -> formatter.formatJavadoc(d.signature(), d.javadoc()) +
                              (d.javadoc() == null ? repl.messageFormat("jshell.console.no.javadoc")
                                                   : "");
@@ -654,23 +761,15 @@
     @Override
     public boolean terminalEditorRunning() {
         Terminal terminal = in.getTerminal();
-        if (terminal instanceof SuspendableTerminal)
-            return ((SuspendableTerminal) terminal).isRaw();
-        return false;
+        return !terminal.getAttributes().getLocalFlag(LocalFlag.ICANON);
     }
 
     @Override
     public void suspend() {
-        Terminal terminal = in.getTerminal();
-        if (terminal instanceof SuspendableTerminal)
-            ((SuspendableTerminal) terminal).suspend();
     }
 
     @Override
     public void resume() {
-        Terminal terminal = in.getTerminal();
-        if (terminal instanceof SuspendableTerminal)
-            ((SuspendableTerminal) terminal).resume();
     }
 
     @Override
@@ -688,49 +787,51 @@
 
     @Override
     public void replaceLastHistoryEntry(String source) {
-        history.fullHistoryReplace(source);
+        var it = in.getHistory().iterator();
+        while (it.hasNext()) {
+            it.next();
+        }
+        it.remove();
+        in.getHistory().add(source);
     }
 
     private static final long ESCAPE_TIMEOUT = 100;
 
-    private void fixes() {
+    private boolean fixes() {
         try {
-            int c = in.readCharacter();
+            int c = in.getTerminal().input().read();
 
             if (c == (-1)) {
-                return ;
+                return true; //TODO: true or false???
             }
 
             for (FixComputer computer : FIX_COMPUTERS) {
                 if (computer.shortcut == c) {
                     fixes(computer);
-                    return ;
+                    return true; //TODO: true of false???
                 }
             }
 
             readOutRemainingEscape(c);
 
             in.beep();
-            in.println();
-            in.println(repl.getResourceString("jshell.fix.wrong.shortcut"));
+            in.getTerminal().writer().println();
+            in.getTerminal().writer().println(repl.getResourceString("jshell.fix.wrong.shortcut"));
             in.redrawLine();
             in.flush();
         } catch (IOException ex) {
             ex.printStackTrace();
         }
+        return true;
     }
 
     private void readOutRemainingEscape(int c) throws IOException {
         if (c == '\033') {
             //escape, consume waiting input:
-            InputStream inp = in.getInput();
+            NonBlockingReader inp = in.getTerminal().reader();
 
-            if (inp instanceof NonBlockingInputStream) {
-                NonBlockingInputStream nbis = (NonBlockingInputStream) inp;
-
-                while (nbis.isNonBlockingEnabled() && nbis.peek(ESCAPE_TIMEOUT) > 0) {
-                    in.readCharacter();
-                }
+            while (inp.peek(ESCAPE_TIMEOUT) > 0) {
+                inp.read();
             }
         }
     }
@@ -738,14 +839,14 @@
     //compute possible options/Fixes based on the selected FixComputer, present them to the user,
     //and perform the selected one:
     private void fixes(FixComputer computer) {
-        String input = prefix + in.getCursorBuffer().toString();
-        int cursor = prefix.length() + in.getCursorBuffer().cursor;
+        String input = prefix + in.getBuffer().toString();
+        int cursor = prefix.length() + in.getBuffer().cursor();
         FixResult candidates = computer.compute(repl, input, cursor);
 
         try {
             final boolean printError = candidates.error != null && !candidates.error.isEmpty();
             if (printError) {
-                in.println(candidates.error);
+                in.getTerminal().writer().println(candidates.error);
             }
             if (candidates.fixes.isEmpty()) {
                 in.beep();
@@ -768,19 +869,19 @@
                     }
 
                     @Override
-                    public void perform(ConsoleReader in) throws IOException {
+                    public void perform(LineReaderImpl in) throws IOException {
                         in.redrawLine();
                     }
                 });
 
                 Map<Character, Fix> char2Fix = new HashMap<>();
-                in.println();
+                in.getTerminal().writer().println();
                 for (int i = 0; i < fixes.size(); i++) {
                     Fix fix = fixes.get(i);
                     char2Fix.put((char) ('0' + i), fix);
-                    in.println("" + i + ": " + fixes.get(i).displayName());
+                    in.getTerminal().writer().println("" + i + ": " + fixes.get(i).displayName());
                 }
-                in.print(repl.messageFormat("jshell.console.choice"));
+                in.getTerminal().writer().print(repl.messageFormat("jshell.console.choice"));
                 in.flush();
                 int read;
 
@@ -793,7 +894,7 @@
                     fix = fixes.get(0);
                 }
 
-                in.println();
+                in.getTerminal().writer().println();
 
                 fix.perform(in);
 
@@ -810,21 +911,24 @@
     @Override
     public synchronized int readUserInput() throws IOException {
         while (inputBytes == null || inputBytes.length <= inputBytesPointer) {
-            boolean prevHandleUserInterrupt = in.getHandleUserInterrupt();
             History prevHistory = in.getHistory();
+            boolean prevDisableCr = Display.DISABLE_CR;
+            Parser prevParser = in.getParser();
 
             try {
+                in.setParser((line, cursor, context) -> new ArgumentLine(line, cursor));
                 input.setState(State.WAIT);
-                in.setHandleUserInterrupt(true);
+                Display.DISABLE_CR = true;
                 in.setHistory(userInputHistory);
                 inputBytes = (in.readLine("") + System.getProperty("line.separator")).getBytes();
                 inputBytesPointer = 0;
             } catch (UserInterruptException ex) {
                 throw new InterruptedIOException();
             } finally {
+                in.setParser(prevParser);
                 in.setHistory(prevHistory);
-                in.setHandleUserInterrupt(prevHandleUserInterrupt);
                 input.setState(State.BUFFER);
+                Display.DISABLE_CR = prevDisableCr;
             }
         }
         return inputBytes[inputBytesPointer++];
@@ -841,7 +945,7 @@
         /**
          * Perform the given action.
          */
-        public void perform(ConsoleReader in) throws IOException;
+        public void perform(LineReaderImpl in) throws IOException;
     }
 
     /**
@@ -882,11 +986,11 @@
 
     private static final FixComputer[] FIX_COMPUTERS = new FixComputer[] {
         new FixComputer('v', false) { //compute "Introduce variable" Fix:
-            private void performToVar(ConsoleReader in, String type) throws IOException {
+            private void performToVar(LineReaderImpl in, String type) throws IOException {
                 in.redrawLine();
-                in.setCursorPosition(0);
+                in.getBuffer().cursor(0);
                 in.putString(type + "  = ");
-                in.setCursorPosition(in.getCursorBuffer().cursor - 3);
+                in.getBuffer().cursor(in.getBuffer().cursor() - 3);
                 in.flush();
             }
 
@@ -904,7 +1008,7 @@
                     }
 
                     @Override
-                    public void perform(ConsoleReader in) throws IOException {
+                    public void perform(LineReaderImpl in) throws IOException {
                         performToVar(in, type);
                     }
                 });
@@ -922,9 +1026,9 @@
                             }
 
                             @Override
-                            public void perform(ConsoleReader in) throws IOException {
+                            public void perform(LineReaderImpl in) throws IOException {
                                 repl.processSource("import " + type + ";");
-                                in.println("Imported: " + type);
+                                in.getTerminal().writer().println("Imported: " + type);
                                 performToVar(in, stype);
                             }
                         });
@@ -934,19 +1038,19 @@
             }
         },
         new FixComputer('m', false) { //compute "Introduce method" Fix:
-            private void performToMethod(ConsoleReader in, String type, String code) throws IOException {
+            private void performToMethod(LineReaderImpl in, String type, String code) throws IOException {
                 in.redrawLine();
                 if (!code.trim().endsWith(";")) {
                     in.putString(";");
                 }
                 in.putString(" }");
-                in.setCursorPosition(0);
+                in.getBuffer().cursor(0);
                 String afterCursor = type.equals("void")
                         ? "() { "
                         : "() { return ";
                 in.putString(type + " " + afterCursor);
                 // position the cursor where the method name should be entered (before parens)
-                in.setCursorPosition(in.getCursorBuffer().cursor - afterCursor.length());
+                in.getBuffer().cursor(in.getBuffer().cursor() - afterCursor.length());
                 in.flush();
             }
 
@@ -1009,7 +1113,7 @@
                     }
 
                     @Override
-                    public void perform(ConsoleReader in) throws IOException {
+                    public void perform(LineReaderImpl in) throws IOException {
                         performToMethod(in, type, codeToCursor);
                     }
                 });
@@ -1027,9 +1131,9 @@
                             }
 
                             @Override
-                            public void perform(ConsoleReader in) throws IOException {
+                            public void perform(LineReaderImpl in) throws IOException {
                                 repl.processSource("import " + type + ";");
-                                in.println("Imported: " + type);
+                                in.getTerminal().writer().println("Imported: " + type);
                                 performToMethod(in, stype, codeToCursor);
                             }
                         });
@@ -1051,9 +1155,9 @@
                         }
 
                         @Override
-                        public void perform(ConsoleReader in) throws IOException {
+                        public void perform(LineReaderImpl in) throws IOException {
                             repl.processSource("import " + fqn + ";");
-                            in.println("Imported: " + fqn);
+                            in.getTerminal().writer().println("Imported: " + fqn);
                             in.redrawLine();
                         }
                     });
@@ -1075,113 +1179,22 @@
         }
     };
 
-    private static final class JShellUnixTerminal extends NoInterruptUnixTerminal implements SuspendableTerminal {
-
-        private final StopDetectingInputStream input;
-
-        public JShellUnixTerminal(StopDetectingInputStream input) throws Exception {
-            this.input = input;
-        }
-
-        @Override
-        public boolean isRaw() {
-            try {
-                return getSettings().get("-a").contains("-icanon");
-            } catch (IOException | InterruptedException ex) {
-                return false;
-            }
-        }
-
-        @Override
-        public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-            return input.setInputStream(super.wrapInIfNeeded(in));
-        }
-
-        @Override
-        public void disableInterruptCharacter() {
-        }
-
-        @Override
-        public void enableInterruptCharacter() {
-        }
-
-        @Override
-        public void suspend() {
-            try {
-                getSettings().restore();
-                super.disableInterruptCharacter();
-            } catch (Exception ex) {
-                throw new IllegalStateException(ex);
-            }
-        }
-
-        @Override
-        public void resume() {
-            try {
-                init();
-            } catch (Exception ex) {
-                throw new IllegalStateException(ex);
-            }
-        }
-
+    private History getHistory() {
+        return in.getHistory();
     }
 
-    private static final class JShellWindowsTerminal extends WindowsTerminal implements SuspendableTerminal {
-
-        private final StopDetectingInputStream input;
-
-        public JShellWindowsTerminal(StopDetectingInputStream input) throws Exception {
-            this.input = input;
-        }
+    private static final class TestTerminal extends LineDisciplineTerminal {
 
-        @Override
-        public void init() throws Exception {
-            super.init();
-            setAnsiSupported(false);
-        }
-
-        @Override
-        public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-            return input.setInputStream(super.wrapInIfNeeded(in));
-        }
+        private static final int DEFAULT_HEIGHT = 24;
 
-        @Override
-        public void suspend() {
-            try {
-                restore();
-                setConsoleMode(getConsoleMode() & ~ConsoleMode.ENABLE_PROCESSED_INPUT.code);
-            } catch (Exception ex) {
-                throw new IllegalStateException(ex);
-            }
-        }
-
-        @Override
-        public void resume() {
-            try {
-                restore();
-                init();
-            } catch (Exception ex) {
-                throw new IllegalStateException(ex);
-            }
-        }
-
-        @Override
-        public boolean isRaw() {
-            return (getConsoleMode() & ConsoleMode.ENABLE_LINE_INPUT.code) == 0;
-        }
-
-    }
-
-    private static final class TestTerminal extends TerminalSupport {
-
-        private final StopDetectingInputStream input;
-        private final int height;
-
-        public TestTerminal(StopDetectingInputStream input) throws Exception {
-            super(true);
-            setAnsiSupported(true);
-            setEchoEnabled(false);
-            this.input = input;
+        public TestTerminal(StopDetectingInputStream input, OutputStream output) throws Exception {
+            super("test", "ansi", output, Charset.forName("UTF-8"));
+//            setAnsiSupported(true);
+//            setEchoEnabled(false);
+//            this.input = input;
+            Attributes a = new Attributes(getAttributes());
+            a.setLocalFlag(LocalFlag.ECHO, false);
+            setAttributes(attributes);
             int h = DEFAULT_HEIGHT;
             try {
                 String hp = System.getProperty("test.terminal.height");
@@ -1191,74 +1204,20 @@
             } catch (Throwable ex) {
                 // ignore
             }
-            this.height = h;
-        }
-
-        @Override
-        public InputStream wrapInIfNeeded(InputStream in) throws IOException {
-            return input.setInputStream(super.wrapInIfNeeded(in));
-        }
-
-        @Override
-        public int getHeight() {
-            return height;
-        }
-
-    }
+            setSize(new Size(80, h));
+            new Thread(() -> {
+                int r;
 
-    private interface SuspendableTerminal {
-        public void suspend();
-        public void resume();
-        public boolean isRaw();
-    }
-
-    private static final class CheckCompletionKeyMap extends KeyMap {
-
-        private final KeyMap del;
-        private final CompletionState completionState;
-
-        public CheckCompletionKeyMap(KeyMap del, CompletionState completionState) {
-            super(del.getName());
-            this.del = del;
-            this.completionState = completionState;
+                try {
+                    while ((r = input.read()) != (-1)) {
+                        processInputByte(r);
+                    }
+                } catch (IOException ex) {
+                    throw new IllegalStateException(ex);
+                }
+            }).start();
         }
 
-        @Override
-        public void bind(CharSequence keySeq, Object function) {
-            del.bind(keySeq, function);
-        }
-
-        @Override
-        public void bindIfNotBound(CharSequence keySeq, Object function) {
-            del.bindIfNotBound(keySeq, function);
-        }
-
-        @Override
-        public void from(KeyMap other) {
-            del.from(other);
-        }
-
-        @Override
-        public Object getAnotherKey() {
-            return del.getAnotherKey();
-        }
-
-        @Override
-        public Object getBound(CharSequence keySeq) {
-            this.completionState.actionCount++;
-
-            return del.getBound(keySeq);
-        }
-
-        @Override
-        public void setBlinkMatchingParen(boolean on) {
-            del.setBlinkMatchingParen(on);
-        }
-
-        @Override
-        public String toString() {
-            return "check: " + del.toString();
-        }
     }
 
     private static final class CompletionState {
@@ -1268,4 +1227,5 @@
         /**Precomputed completion actions. Should only be reused if actionCount == 1.*/
         public List<CompletionTask> todo = Collections.emptyList();
     }
+
 }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -36,7 +36,7 @@
     @Override
     public abstract void close() throws IOException;
 
-    public abstract String readLine(String prompt, String prefix) throws IOException, InputInterruptedException;
+    public abstract String readLine(String firstLinePrompt, String continuationPrompt, boolean firstLine, String prefix) throws IOException, InputInterruptedException;
 
     public abstract boolean interactiveOutput();
 
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1220,45 +1220,22 @@
     private String getInput(String initial) throws IOException{
         String src = initial;
         while (live) { // loop while incomplete (and live)
-            if (!src.isEmpty()) {
-                // We have some source, see if it is complete, if so, use it
-                String check;
-
-                if (isCommand(src)) {
-                    // A command can only be incomplete if it is a /exit with
-                    // an argument
-                    int sp = src.indexOf(" ");
-                    if (sp < 0) return src;
-                    check = src.substring(sp).trim();
-                    if (check.isEmpty()) return src;
-                    String cmd = src.substring(0, sp);
-                    Command[] match = findCommand(cmd, c -> c.kind.isRealCommand);
-                    if (match.length != 1 || !match[0].command.equals("/exit")) {
-                        // A command with no snippet arg, so no multi-line input
-                        return src;
-                    }
-                } else {
-                    // For a snippet check the whole source
-                    check = src;
-                }
-                Completeness comp = analysis.analyzeCompletion(check).completeness();
-                if (comp.isComplete() || comp == Completeness.EMPTY) {
-                    return src;
-                }
+            if (!src.isEmpty() && isComplete(src)) {
+                return src;
             }
-            String prompt = interactive()
-                    ? testPrompt
-                            ? src.isEmpty()
-                                    ? "\u0005" //ENQ -- test prompt
-                                    : "\u0006" //ACK -- test continuation prompt
-                            : src.isEmpty()
-                                    ? feedback.getPrompt(currentNameSpace.tidNext())
-                                    : feedback.getContinuationPrompt(currentNameSpace.tidNext())
+            String firstLinePrompt = interactive()
+                    ? testPrompt ? " \005"
+                                 : feedback.getPrompt(currentNameSpace.tidNext())
+                    : "" // Non-interactive -- no prompt
+                    ;
+            String continuationPrompt = interactive()
+                    ? testPrompt ? " \006"
+                                 : feedback.getContinuationPrompt(currentNameSpace.tidNext())
                     : "" // Non-interactive -- no prompt
                     ;
             String line;
             try {
-                line = input.readLine(prompt, src);
+                line = input.readLine(firstLinePrompt, continuationPrompt, src.isEmpty(), src);
             } catch (InputInterruptedException ex) {
                 //input interrupted - clearing current state
                 src = "";
@@ -1279,6 +1256,33 @@
         throw new EOFException(); // not longer live
     }
 
+    public boolean isComplete(String src) {
+        String check;
+
+        if (isCommand(src)) {
+            // A command can only be incomplete if it is a /exit with
+            // an argument
+            int sp = src.indexOf(" ");
+            if (sp < 0) return true;
+            check = src.substring(sp).trim();
+            if (check.isEmpty()) return true;
+            String cmd = src.substring(0, sp);
+            Command[] match = findCommand(cmd, c -> c.kind.isRealCommand);
+            if (match.length != 1 || !match[0].command.equals("/exit")) {
+                // A command with no snippet arg, so no multi-line input
+                return true;
+            }
+        } else {
+            // For a snippet check the whole source
+            check = src;
+        }
+        Completeness comp = analysis.analyzeCompletion(check).completeness();
+        if (comp.isComplete() || comp == Completeness.EMPTY) {
+            return true;
+        }
+        return false;
+    }
+
     private boolean isCommand(String line) {
         return line.startsWith("/") && !line.startsWith("//") && !line.startsWith("/*");
     }
@@ -1853,6 +1857,9 @@
         registerCommand(new Command("intro",
                 "help.intro",
                 CommandKind.HELP_SUBJECT));
+        registerCommand(new Command("keys",
+                "help.keys",
+                CommandKind.HELP_SUBJECT));
         registerCommand(new Command("id",
                 "help.id",
                 CommandKind.HELP_SUBJECT));
@@ -4001,7 +4008,7 @@
     }
 
     @Override
-    public String readLine(String prompt, String prefix) {
+    public String readLine(String firstLinePrompt, String continuationPrompt, boolean firstLine, String prefix) {
         if (scannerIn.hasNextLine()) {
             return scannerIn.nextLine();
         } else {
@@ -4030,7 +4037,7 @@
     }
 
     @Override
-    public String readLine(String prompt, String prefix) {
+    public String readLine(String firstLinePrompt, String continuationPrompt, boolean firstLine, String prefix) {
         String s = it.hasNext()
                 ? it.next()
                 : null;
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Dec 12 08:38:45 2018 -0500
@@ -571,6 +571,103 @@
 \n\
 For a list of commands: /help
 
+help.keys.summary = a description of readline-like input editing
+help.keys =\
+The jshell tool provides line editing support to allow you to navigate within\n\
+and edit snippets and commands. The current command/snippet can be edited,\n\
+or prior commands/snippets can be retrieved from history, edited, and executed.\n\
+This support is similar to readline/editline with simple emacs-like bindings.\n\
+There are also jshell tool specific key sequences.\n\
+\n\
+--- Line and history navigation ---\n\
+\n\
+Return\n\t\
+  Enters the current snippet\n\
+Left-arrow or Ctrl+B\n\t\
+  Moves backward one character\n\
+Right-arrow or Ctrl+F\n\t\
+  Moves forward one character\n\
+Up-arrow or Ctrl+P\n\t\
+  Moves up one line, backward through history\n\
+Down arrow or Ctrl+N\n\t\
+  Moves down one line, forward through history\n\
+Ctrl+A\n\t\
+  Moves to the beginning of the line\n\
+Ctrl+E\n\t\
+  Moves to the end of the line\n\
+Meta+B\n\t\
+  Moves backward one word\n\
+Meta+F\n\t\
+  Moves forward one word\n\
+Ctrl+R\n\t\
+  Search backward through history\n\
+\n\
+\n\
+--- Line and history basic editing ---\n\
+\n\
+Meta+Return or Ctrl+Return (depending on platform)\n\t\
+  Insert a new line in snippet\n\
+Ctrl+_ (underscore may require shift key) or Ctrl+X then Ctrl+U\n\t\
+  Undo edit - repeat to undo more edits\n\
+Delete\n\t\
+  Deletes the character at or after the cursor, depending on the operating system\n\
+Backspace\n\t\
+  Deletes the character before the cursor\n\
+Ctrl+K\n\t\
+  Deletes the text from the cursor to the end of the line\n\
+Meta+D\n\t\
+  Deletes the text from the cursor to the end of the word\n\
+Ctrl+W\n\t\
+  Deletes the text from the cursor to the previous white space\n\
+Ctrl+Y\n\t\
+  Pastes the most recently deleted text into the line\n\
+Meta+Y\n\t\
+  After Ctrl+Y, Meta+Y cycles through previously deleted text\n\
+Ctrl+X then Ctrl+K\n\t\
+  Delete whole snippet\n\
+\n\
+\n\
+--- Shortcuts for jshell tool ---\n\
+\n\
+For details, see: /help shortcuts\n\
+\n\
+Tab\n\t\
+  Complete Java identifier or jshell command\n\
+Shift+Tab then v\n\t\
+  Convert expression to variable declaration\n\
+Shift+Tab then m\n\t\
+  Convert statement to method declaration\n\
+Shift+Tab then i\n\t\
+  Add imports for this identifier\n\
+\n\
+\n\
+--- More line and history editing ---\n\
+\n\
+Ctrl+L\n\t\
+  Clear screen and reprint snippet\n\
+Ctrl+U\n\t\
+  Kill whole line\n\
+Ctrl+T\n\t\
+  Transpose characters\n\
+Ctrl+X then Ctrl+B\n\t\
+  Navigate to matching bracket, parenthesis, ...\n\
+Ctrl+X then =\n\t\
+  Enter show current character position mode\n\
+Ctrl+X then Ctrl+O\n\t\
+  Toggle overwrite characters vs insert characters\n\
+Meta+C\n\t\
+  Capitalize word\n\
+Meta+U\n\t\
+  Convert word to uppercase\n\
+Meta+L\n\t\
+  Convert word to lowercase\n\
+Meta+0 through Meta+9 then key\n\t\
+  Repeat the specified number of times\n\
+\n\
+Where, for example, "Ctrl+A" means hold down the control key and press A.\n\
+Where "Meta" is "Alt" on many keyboards.\n\
+Line editing support is derived from JLine 3.
+
 help.shortcuts.summary = a description of keystrokes for snippet and command completion,\n\
 information access, and automatic code generation
 help.shortcuts =\
--- a/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java	Wed Dec 12 08:38:45 2018 -0500
@@ -150,12 +150,12 @@
      * @throws JSException when an error is reported from the browser or
      * JavaScript engine or if applet is {@code null}
      *
-     * @deprecated  The Applet API is deprecated. See the
+     * @deprecated The Applet API is deprecated, no replacement. See the
      * <a href="{@docRoot}/java.desktop/java/applet/package-summary.html">
      * java.applet package documentation</a> for further information.
      */
 
-    @Deprecated(since = "9")
+    @Deprecated(since="9", forRemoval=true)
     @SuppressWarnings("exports")
     public static JSObject getWindow(Applet applet) throws JSException {
         return ProviderLoader.callGetWindow(applet);
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -31,67 +31,91 @@
 import java.io.PrintStream;
 import java.io.Writer;
 import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import jdk.internal.jline.NoInterruptUnixTerminal;
-import jdk.internal.jline.Terminal;
-import jdk.internal.jline.TerminalFactory;
-import jdk.internal.jline.TerminalFactory.Flavor;
-import jdk.internal.jline.WindowsTerminal;
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.KeyMap;
-import jdk.internal.jline.console.completer.CandidateListCompletionHandler;
-import jdk.internal.jline.extra.EditingHistory;
-import jdk.internal.misc.Signal;
-import jdk.internal.misc.Signal.Handler;
+import java.util.stream.StreamSupport;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.CompletingParsedLine;
+import jdk.internal.org.jline.reader.EOFError;
+import jdk.internal.org.jline.reader.History;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.LineReader.Option;
+import jdk.internal.org.jline.reader.LineReaderBuilder;
+import jdk.internal.org.jline.reader.Parser;
+import jdk.internal.org.jline.reader.Parser.ParseContext;
+import jdk.internal.org.jline.reader.Widget;
+import jdk.internal.org.jline.reader.impl.LineReaderImpl;
+import jdk.internal.org.jline.reader.impl.completer.ArgumentCompleter.ArgumentLine;
+import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
+import jdk.internal.org.jline.terminal.Terminal;
 
 class Console implements AutoCloseable {
     private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
-    private final ConsoleReader in;
+    private final LineReader in;
     private final File historyFile;
 
     Console(final InputStream cmdin, final PrintStream cmdout, final File historyFile,
             final NashornCompleter completer, final Function<String, String> docHelper) throws IOException {
         this.historyFile = historyFile;
 
-        TerminalFactory.registerFlavor(Flavor.WINDOWS, ttyDevice -> isCygwin() ? new JJSUnixTerminal() : new JJSWindowsTerminal());
-        TerminalFactory.registerFlavor(Flavor.UNIX, ttyDevice -> new JJSUnixTerminal());
-        in = new ConsoleReader(cmdin, cmdout);
-        in.setExpandEvents(false);
-        in.setHandleUserInterrupt(true);
-        in.setBellEnabled(true);
-        in.setCopyPasteDetection(true);
-        ((CandidateListCompletionHandler) in.getCompletionHandler()).setPrintSpaceAfterFullCompletion(false);
-        final Iterable<String> existingHistory = historyFile.exists() ? Files.readAllLines(historyFile.toPath()) : null;
-        in.setHistory(new EditingHistory(in, existingHistory) {
-            @Override protected boolean isComplete(CharSequence input) {
-                return completer.isComplete(input.toString());
+        Parser parser = (line, cursor, context) -> {
+            if (context == ParseContext.COMPLETE) {
+                List<Candidate> candidates = new ArrayList<>();
+                int anchor = completer.complete(line, cursor, candidates);
+                anchor = Math.min(anchor, line.length());
+                return new CompletionLine(line.substring(anchor), cursor, candidates);
+            } else if (!completer.isComplete(line)) {
+                throw new EOFError(cursor, cursor, line);
             }
-        });
-        in.addCompleter(completer);
+            return new ArgumentLine(line, cursor);
+        };
+        in = LineReaderBuilder.builder()
+                              .option(Option.DISABLE_EVENT_EXPANSION, true)
+                              .completer((in, line, candidates) -> candidates.addAll(((CompletionLine) line).candidates))
+                              .parser(parser)
+                              .build();
+        if (historyFile.exists()) {
+            StringBuilder line = new StringBuilder();
+            for (String h : Files.readAllLines(historyFile.toPath())) {
+                if (line.length() > 0) {
+                    line.append("\n");
+                }
+                line.append(h);
+                try {
+                    parser.parse(line.toString(), line.length());
+                    in.getHistory().add(line.toString());
+                    line.delete(0, line.length());
+                } catch (EOFError e) {
+                    //continue;
+                }
+            }
+            if (line.length() > 0) {
+                in.getHistory().add(line.toString());
+            }
+        }
         Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
-        bind(DOCUMENTATION_SHORTCUT, (Runnable) ()->showDocumentation(docHelper));
-        try {
-            Signal.handle(new Signal("CONT"), new Handler() {
-                @Override public void handle(Signal sig) {
-                    try {
-                        in.getTerminal().reset();
-                        in.redrawLine();
-                        in.flush();
-                    } catch (Exception ex) {
-                        ex.printStackTrace();
-                    }
-                }
-            });
-        } catch (IllegalArgumentException ignored) {
-            //the CONT signal does not exist on this platform
-        }
+        bind(DOCUMENTATION_SHORTCUT, ()->showDocumentation(docHelper));
     }
 
-    String readLine(final String prompt) throws IOException {
+    String readLine(final String prompt, final String continuationPrompt) throws IOException {
+        in.setVariable(LineReader.SECONDARY_PROMPT_PATTERN, continuationPrompt);
         return in.readLine(prompt);
     }
 
+    String readUserLine(final String prompt) throws IOException {
+        Parser prevParser = in.getParser();
+
+        try {
+            ((LineReaderImpl) in).setParser((line, cursor, context) -> new ArgumentLine(line, cursor));
+            return in.readLine(prompt);
+        } finally {
+            ((LineReaderImpl) in).setParser(prevParser);
+        }
+    }
+
     @Override
     public void close() {
         saveHistory();
@@ -101,103 +125,62 @@
         try (Writer out = Files.newBufferedWriter(historyFile.toPath())) {
             String lineSeparator = System.getProperty("line.separator");
 
-            out.write(getHistory().save()
-                                  .stream()
-                                  .collect(Collectors.joining(lineSeparator)));
+            out.write(StreamSupport.stream(getHistory().spliterator(), false)
+                                   .map(e -> e.line())
+                                   .collect(Collectors.joining(lineSeparator)));
         } catch (final IOException exp) {}
     }
 
-    EditingHistory getHistory() {
-        return (EditingHistory) in.getHistory();
+    History getHistory() {
+        return in.getHistory();
     }
 
     boolean terminalEditorRunning() {
         Terminal terminal = in.getTerminal();
-        if (terminal instanceof JJSUnixTerminal) {
-            return ((JJSUnixTerminal) terminal).isRaw();
-        }
-        return false;
+        return !terminal.getAttributes().getLocalFlag(LocalFlag.ICANON);
     }
 
     void suspend() {
-        try {
-            in.getTerminal().restore();
-        } catch (Exception ex) {
-            throw new IllegalStateException(ex);
-        }
     }
 
     void resume() {
-        try {
-            in.getTerminal().init();
-        } catch (Exception ex) {
-            throw new IllegalStateException(ex);
-        }
+    }
+
+    private void bind(String shortcut, Widget action) {
+        in.getKeyMaps().get(LineReader.MAIN).bind(action, shortcut);
     }
 
-    static final class JJSUnixTerminal extends NoInterruptUnixTerminal {
-        JJSUnixTerminal() throws Exception {
-        }
-
-        boolean isRaw() {
-            try {
-                return getSettings().get("-a").contains("-icanon");
-            } catch (IOException | InterruptedException ex) {
-                return false;
-            }
-        }
-
-        @Override
-        public void disableInterruptCharacter() {
-        }
-
-        @Override
-        public void enableInterruptCharacter() {
+    private boolean showDocumentation(final Function<String, String> docHelper) {
+        final String buffer = in.getBuffer().toString();
+        final int cursor = in.getBuffer().cursor();
+        final String doc = docHelper.apply(buffer.substring(0, cursor));
+        if (doc != null) {
+            in.getTerminal().writer().println();
+            in.printAbove(doc);
+            return true;
+        } else {
+            return false;
         }
     }
 
-    static final class JJSWindowsTerminal extends WindowsTerminal {
-        public JJSWindowsTerminal() throws Exception {
+    private static final class CompletionLine extends ArgumentLine implements CompletingParsedLine {
+        public final List<Candidate> candidates;
+
+        public CompletionLine(String word, int cursor, List<Candidate> candidates) {
+            super(word, cursor);
+            this.candidates = candidates;
         }
 
-        @Override
-        public void init() throws Exception {
-            super.init();
-            setAnsiSupported(false);
+        public CharSequence escape(CharSequence candidate, boolean complete) {
+            return candidate;
         }
-    }
-
-    private static boolean isCygwin() {
-        return System.getenv("SHELL") != null;
-    }
 
-    private void bind(String shortcut, Object action) {
-        KeyMap km = in.getKeys();
-        for (int i = 0; i < shortcut.length(); i++) {
-            final Object value = km.getBound(Character.toString(shortcut.charAt(i)));
-            if (value instanceof KeyMap) {
-                km = (KeyMap) value;
-            } else {
-                km.bind(shortcut.substring(i), action);
-            }
+        public int rawWordCursor() {
+            return word().length();
         }
-    }
 
-    private void showDocumentation(final Function<String, String> docHelper) {
-        final String buffer = in.getCursorBuffer().buffer.toString();
-        final int cursor = in.getCursorBuffer().cursor;
-        final String doc = docHelper.apply(buffer.substring(0, cursor));
-        try {
-            if (doc != null) {
-                in.println();
-                in.println(doc);
-                in.redrawLine();
-                in.flush();
-            } else {
-                in.beep();
-            }
-        } catch (IOException ex) {
-            throw new IllegalStateException(ex);
+        public int rawWordLength() {
+            return word().length();
         }
     }
 }
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/HistoryObject.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/HistoryObject.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -30,13 +30,15 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.UncheckedIOException;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Supplier;
-import jdk.internal.jline.console.history.History;
+
+import jdk.internal.org.jline.reader.History;
 import jdk.nashorn.api.scripting.AbstractJSObject;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.runtime.JSType;
@@ -88,11 +90,20 @@
 
             if (index >= 0 && index < (hist.size() - 1)) {
                 final CharSequence src = hist.get(index);
-                hist.replace(src);
+                var it = hist.iterator();
+                while (it.hasNext()) {
+                    it.next();
+                }
+                it.remove();
+                hist.add(src.toString());
                 err.println(src);
                 evaluator.accept(src.toString());
             } else {
-                hist.removeLast();
+                var it = hist.iterator();
+                while (it.hasNext()) {
+                    it.next();
+                }
+                it.remove();
                 err.println("no history entry @ " + (index + 1));
             }
         }
@@ -103,7 +114,13 @@
     public Object getMember(final String name) {
         switch (name) {
             case "clear":
-                return (Runnable)hist::clear;
+                return (Runnable) () -> {
+                    try {
+                    hist.purge();
+                    } catch (IOException ex) {
+                        throw new UncheckedIOException(ex);
+                    }
+                };
             case "forEach":
                 return (Function<JSObject, Object>)this::iterate;
             case "load":
@@ -132,7 +149,7 @@
     public String toString() {
         final StringBuilder buf = new StringBuilder();
         for (History.Entry e : hist) {
-            buf.append(e.value()).append('\n');
+            buf.append(e.line()).append('\n');
         }
         return buf.toString();
     }
@@ -146,7 +163,7 @@
         final File file = getFile(obj);
         try (final PrintWriter pw = new PrintWriter(file)) {
             for (History.Entry e : hist) {
-                pw.println(e.value());
+                pw.println(e.line());
             }
         } catch (final IOException exp) {
             throw new RuntimeException(exp);
@@ -167,13 +184,13 @@
 
     private void print() {
         for (History.Entry e : hist) {
-            System.out.printf("%3d %s\n", e.index() + 1, e.value());
+            System.out.printf("%3d %s\n", e.index() + 1, e.line());
         }
     }
 
     private Object iterate(final JSObject func) {
         for (History.Entry e : hist) {
-            if (JSType.toBoolean(func.call(this, e.value().toString()))) {
+            if (JSType.toBoolean(func.call(this, e.line().toString()))) {
                 break; // return true from callback to skip iteration
             }
         }
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, 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
@@ -27,10 +27,8 @@
 
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.io.OutputStream;
@@ -38,12 +36,9 @@
 import java.net.URI;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.concurrent.Callable;
 import java.util.function.Consumer;
-import java.util.function.Function;
-import jdk.internal.jline.console.completer.Completer;
-import jdk.internal.jline.console.UserInterruptException;
-import jdk.nashorn.api.scripting.NashornException;
+
+import jdk.internal.org.jline.reader.UserInterruptException;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.objects.NativeJava;
 import jdk.nashorn.internal.runtime.Context;
@@ -178,7 +173,7 @@
             // redefine readLine to use jline Console's readLine!
             ScriptingFunctions.setReadLineHelper(str-> {
                 try {
-                    return in.readLine(str);
+                    return in.readUserLine(str);
                 } catch (final IOException ioExp) {
                     throw new UncheckedIOException(ioExp);
                 }
@@ -209,9 +204,9 @@
             }
 
             while (true) {
-                String source = "";
+                String source;
                 try {
-                    source = in.readLine(prompt);
+                    source = in.readLine(prompt, prompt2);
                 } catch (final IOException ioe) {
                     err.println(ioe.toString());
                     if (env._dump_on_error) {
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/NashornCompleter.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/NashornCompleter.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -31,8 +31,12 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.regex.Pattern;
-import jdk.internal.jline.console.completer.Completer;
-import jdk.internal.jline.console.UserInterruptException;
+
+import jdk.internal.org.jline.reader.Candidate;
+import jdk.internal.org.jline.reader.Completer;
+import jdk.internal.org.jline.reader.LineReader;
+import jdk.internal.org.jline.reader.ParsedLine;
+import jdk.internal.org.jline.reader.UserInterruptException;
 import jdk.nashorn.api.tree.AssignmentTree;
 import jdk.nashorn.api.tree.BinaryTree;
 import jdk.nashorn.api.tree.CompilationUnitTree;
@@ -63,7 +67,7 @@
  * A simple source completer for nashorn. Handles code completion for
  * expressions as well as handles incomplete single line code.
  */
-final class NashornCompleter implements Completer {
+final class NashornCompleter {
     private final Context context;
     private final Global global;
     private final ScriptEnvironment env;
@@ -145,7 +149,7 @@
             buf.append('\n');
             String curLine = null;
             try {
-                curLine = in.readLine(prompt);
+                curLine = in.readLine(prompt, prompt);
                 buf.append(curLine);
                 line++;
             } catch (final Throwable th) {
@@ -208,8 +212,7 @@
     // Pattern to match load call
     private static final Pattern LOAD_CALL = Pattern.compile("\\s*load\\s*\\(\\s*");
 
-    @Override
-    public int complete(final String test, final int cursor, final List<CharSequence> result) {
+    public int complete(String test, int cursor, List<Candidate> candidates) {
         // check that cursor is at the end of test string. Do not complete in the middle!
         if (cursor != test.length()) {
             return cursor;
@@ -245,7 +248,7 @@
                     if (BACKSLASH_FILE_SEPARATOR) {
                         name = name.replace("\\", "\\\\");
                     }
-                    result.add("\"" + name + "\")");
+                    candidates.add(createCandidate("\"" + name + "\")"));
                     return cursor + name.length() + 3;
                 }
             }
@@ -258,9 +261,9 @@
         // Find 'right most' expression of the top level expression
         final Tree rightMostExpr = getRightMostExpression(topExpr);
         if (rightMostExpr instanceof MemberSelectTree) {
-            return completeMemberSelect(exprStr, cursor, result, (MemberSelectTree)rightMostExpr, endsWithDot);
+            return completeMemberSelect(exprStr, cursor, candidates, (MemberSelectTree)rightMostExpr, endsWithDot);
         } else if (rightMostExpr instanceof IdentifierTree) {
-            return completeIdentifier(exprStr, cursor, result, (IdentifierTree)rightMostExpr);
+            return completeIdentifier(exprStr, cursor, candidates, (IdentifierTree)rightMostExpr);
         } else {
             // expression that we cannot handle for completion
             return cursor;
@@ -284,7 +287,7 @@
     }
 
     // fill properties of the incomplete member expression
-    private int completeMemberSelect(final String exprStr, final int cursor, final List<CharSequence> result,
+    private int completeMemberSelect(final String exprStr, final int cursor, final List<Candidate> candidates,
                 final MemberSelectTree select, final boolean endsWithDot) {
         final ExpressionTree objExpr = select.getExpression();
         final String objExprCode = exprStr.substring((int)objExpr.getStartPosition(), (int)objExpr.getEndPosition());
@@ -303,12 +306,12 @@
         if (obj != null && obj != ScriptRuntime.UNDEFINED) {
             if (endsWithDot) {
                 // no user specified "prefix". List all properties of the object
-                result.addAll(propsHelper.getProperties(obj));
+                propsHelper.getProperties(obj).stream().map(this::createCandidate).forEach(candidates::add);
                 return cursor;
             } else {
                 // list of properties matching the user specified prefix
                 final String prefix = select.getIdentifier();
-                result.addAll(propsHelper.getProperties(obj, prefix));
+                propsHelper.getProperties(obj, prefix).stream().map(this::createCandidate).forEach(candidates::add);
                 return cursor - prefix.length();
             }
         }
@@ -317,10 +320,10 @@
     }
 
     // fill properties for the given (partial) identifer
-    private int completeIdentifier(final String test, final int cursor, final List<CharSequence> result,
+    private int completeIdentifier(final String test, final int cursor, final List<Candidate> candidates,
                 final IdentifierTree ident) {
         final String name = ident.getName();
-        result.addAll(propsHelper.getProperties(global, name));
+        propsHelper.getProperties(global, name).stream().map(this::createCandidate).forEach(candidates::add);
         return cursor - name.length();
     }
 
@@ -431,4 +434,8 @@
 
         return Parser.create(args.toArray(new String[0]));
     }
+
+    private Candidate createCandidate(String value) {
+        return new Candidate(value, value, null, null, null, null, false);
+    }
 }
--- a/test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh	Wed Dec 12 08:38:45 2018 -0500
@@ -36,7 +36,7 @@
 
 $JAVA_HOME/bin/javac -d . $DIR/$TEST.java
 
-JAOTC_OPTS="-J-Xmx4g --compile-for-tiered --info"
+JAOTC_OPTS="-J-ea -J-Xmx4g --compile-for-tiered --info"
 JAVA_OPTS="-Xmx4g -XX:+UseAOT -XX:+UnlockDiagnosticVMOptions -XX:+UseAOTStrictLoading"
 
 # Compile with: +UseCompressedOops +UseG1GC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/g1/TestEdenSurvivorLessThanMax.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test TestEdenSurvivorLessThanMax
+ * @bug 8152724
+ * @summary Check that G1 eden plus survivor max capacity after GC does not exceed maximum number of regions.
+ * @requires vm.gc.G1
+ * @key gc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xlog:gc+heap=debug -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC -Xmx64M -Xms64M -Xmn50M -XX:SurvivorRatio=1 TestEdenSurvivorLessThanMax
+ */
+
+import sun.hotspot.WhiteBox;
+
+// The test fills the heap in a way that previous to 8152724 the maximum number of survivor regions
+// for that young gc was higher than there was free space left which is impossible.
+public class TestEdenSurvivorLessThanMax {
+    private static final long BYTES_TO_FILL = 50 * 1024 * 1024;
+
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+    public static void main(String[] args) throws Exception {
+        Object o = new int[100];
+
+        long objSize = WB.getObjectSize(o);
+
+        // Fill eden to approximately ~90%.
+        int numObjs = (int)((BYTES_TO_FILL / objSize) * 9 / 10);
+        for (int i = 0; i < numObjs; i++) {
+          o = new int[100];
+        }
+
+        WB.youngGC();
+
+        System.out.println(o.toString());
+    }
+}
+
--- a/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java	Wed Dec 12 08:38:45 2018 -0500
@@ -69,7 +69,7 @@
         pb = ProcessTools.createJavaProcessBuilder("--enable-preview", "-Xlog:class+preview",
             "-cp", "." + File.pathSeparator + System.getProperty("test.classes"), "PVTest");
         oa = new OutputAnalyzer(pb.start());
-        oa.shouldContain("[info][class,preview] Loading preview feature type PVTest");
+        oa.shouldContain("[info][class,preview] Loading class PVTest that depends on preview features");
 
         // Subtract 1 from class's major version.  The class should fail to load
         // because its major_version does not match the JVM current version.
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Wed Dec 12 08:38:45 2018 -0500
@@ -23,8 +23,8 @@
 
 /**
  * @test
- * @bug 8174994
- * @summary Test the clhsdb commands 'printmdo', 'printall' on a CDS enabled corefile.
+ * @bug 8174994 8200613
+ * @summary Test the clhsdb commands 'printmdo', 'printall', 'jstack' on a CDS enabled corefile.
  * @requires vm.cds
  * @requires vm.hasSA
  * @requires os.family != "windows"
@@ -156,7 +156,7 @@
                 throw new SkippedException("The CDS archive is not mapped");
             }
 
-            cmds = List.of("printmdo -a", "printall");
+            cmds = List.of("printmdo -a", "printall", "jstack -v");
 
             Map<String, List<String>> expStrMap = new HashMap<>();
             Map<String, List<String>> unExpStrMap = new HashMap<>();
@@ -182,6 +182,11 @@
                 "illegal code",
                 "Failure occurred at bci",
                 "No suitable match for type of address"));
+            expStrMap.put("jstack -v", List.of(
+                "Common-Cleaner",
+                "Method*"));
+            unExpStrMap.put("jstack -v", List.of(
+                "sun.jvm.hotspot.debugger.UnmappedAddressException"));
             test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds, expStrMap, unExpStrMap);
         } catch (SkippedException e) {
             throw e;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Breakpoint/breakpoint001/breakpoint001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Breakpoint/breakpoint001/breakpoint001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -118,17 +118,17 @@
     }
     if (thr_info.name == NULL ||
             strcmp(thr_info.name,THREAD_NAME) != 0 ||
-            thr_info.is_daemon==JNI_TRUE) {
+            thr_info.is_daemon == JNI_TRUE) {
         result = checkStatus = STATUS_FAILED;
         NSK_COMPLAIN2(
             "TEST FAILED: Breakpoint event with unexpected thread info:\n"
             "\tname: \"%s\"\ttype: %s thread\n\n",
-            (thr_info.name == NULL)?"NULL":thr_info.name,
-            (thr_info.is_daemon==JNI_TRUE)?"deamon":"user");
+            (thr_info.name == NULL) ? "NULL" : thr_info.name,
+            (thr_info.is_daemon == JNI_TRUE) ? "deamon" : "user");
     }
     else
         NSK_DISPLAY2("CHECK PASSED: thread name: \"%s\"\ttype: %s thread\n",
-            thr_info.name, (thr_info.is_daemon==JNI_TRUE)?"deamon":"user");
+            thr_info.name, (thr_info.is_daemon == JNI_TRUE) ? "deamon" : "user");
 
     /* checking location */
     if (location != 0) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassLoad/classload001/classload001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ClassLoad/classload001/classload001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -89,9 +89,9 @@
 static int findSig(char *sig, int expected) {
     unsigned int i;
 
-    for (i=0; i<((expected==1)?EXP_SIG_NUM:UNEXP_SIG_NUM); i++)
+    for (i=0; i<((expected == 1) ? EXP_SIG_NUM : UNEXP_SIG_NUM); i++)
         if (sig != NULL &&
-                strcmp(((expected==1)?expSigs[i]:unexpSigs[i]), sig) == 0)
+                strcmp(((expected == 1) ? expSigs[i] : unexpSigs[i]), sig) == 0)
             return i; /* the signature found, return index */
 
     return -1; /* the signature not found */
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc001/fieldacc001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc001/fieldacc001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -214,9 +214,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             return;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc002/fieldacc002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc002/fieldacc002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -213,9 +213,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             return;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc003/fieldacc003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc003/fieldacc003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -193,9 +193,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             return;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc004/fieldacc004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldAccess/fieldacc004/fieldacc004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -179,9 +179,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             return;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod001/fieldmod001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod001/fieldmod001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -282,9 +282,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             if (!isEqual((JNIEnv *)env, watch.f_sig, watch.val, watches[i].val)) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod002/fieldmod002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FieldModification/fieldmod002/fieldmod002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -281,9 +281,9 @@
             }
             if (watch.is_static != watches[i].is_static) {
                 printf("(watch#%" PRIuPTR ") wrong field type: %s", i,
-                    (watch.is_static==JNI_TRUE)?"static":"instance");
+                    (watch.is_static == JNI_TRUE) ? "static" : "instance");
                 printf(", expected: %s\n",
-                    (watches[i].is_static==JNI_TRUE)?"static":"instance");
+                    (watches[i].is_static == JNI_TRUE) ? "static" : "instance");
                 result = STATUS_FAILED;
             }
             if (!isEqual((JNIEnv *)env, watch.f_sig, watch.val, watches[i].val)) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -200,7 +200,7 @@
     new_item->depth = depth;
     threads[i].tos = new_item;
     push_count++;
-    max_depth = (max_depth < depth) ? depth: max_depth;
+    max_depth = (max_depth < depth) ? depth : max_depth;
 }
 
 void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env,
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassSignature/getclsig006/getclsig006.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassSignature/getclsig006/getclsig006.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -67,7 +67,7 @@
             class_sig[idx][0]);
 
         if (strcmp(class_sig[idx][1], sign) != 0 ||
-                strcmp(class_sig[idx][2], (gen_sign==NULL)?"NULL":gen_sign) != 0) {
+                strcmp(class_sig[idx][2], (gen_sign == NULL) ? "NULL" : gen_sign) != 0) {
             NSK_COMPLAIN5(
                 "TEST FAILED: class: \"%s\" has\n"
                 "\tsignature: \"%s\"\n"
@@ -75,19 +75,19 @@
                 "\tExpected: \"%s\"\n"
                 "\t\"%s\"\n\n",
                 class_sig[idx][0],
-                sign, (gen_sign==NULL)?"NULL":gen_sign,
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign,
                 class_sig[idx][1], class_sig[idx][2]);
             totRes = STATUS_FAILED;
         }
         else
             NSK_DISPLAY2("CHECK PASSED: signature: \"%s\",\n\tgeneric signature: \"%s\"\n",
-                sign, (gen_sign==NULL)?"NULL":gen_sign);
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign);
 
         NSK_DISPLAY0("Deallocating the signature array\n");
         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) sign))) {
             totRes = STATUS_FAILED;
         }
-        if (gen_sign!=NULL)
+        if (gen_sign != NULL)
             if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) gen_sign))) {
                 totRes = STATUS_FAILED;
             }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetFieldName/getfldnm005/getfldnm005.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetFieldName/getfldnm005/getfldnm005.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -101,29 +101,29 @@
             name);
 
         if (strcmp(fld_sig[idx][2], sign) != 0 ||
-                strcmp(fld_sig[idx][3], (gen_sign==NULL)?"NULL":gen_sign) != 0) {
+                strcmp(fld_sig[idx][3], (gen_sign == NULL) ? "NULL" : gen_sign) != 0) {
             NSK_COMPLAIN6(
                 "TEST FAILED: %s field \"%s\" has\n"
                 "\tsignature: \"%s\"\n"
                 "\tgeneric signature: \"%s\"\n\n"
                 "\tExpected: \"%s\"\n"
                 "\t\t\"%s\"\n\n",
-               (instance==0)?"instance":"static",
+               (instance == 0) ? "instance" : "static",
                 fld_sig[idx][0],
-                sign, (gen_sign==NULL)?"NULL":gen_sign,
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign,
                 fld_sig[idx][2], fld_sig[idx][3]);
             totRes = STATUS_FAILED;
         }
         else
             NSK_DISPLAY2("CHECK PASSED: signature: \"%s\",\n\tgeneric signature: \"%s\"\n",
-                sign, (gen_sign==NULL)?"NULL":gen_sign);
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign);
 
         NSK_DISPLAY0("Deallocating name & signature arrays\n");
         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) name)))
             totRes = STATUS_FAILED;
         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) sign)))
             totRes = STATUS_FAILED;
-        if (gen_sign!=NULL)
+        if (gen_sign != NULL)
             if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) gen_sign)))
                 totRes = STATUS_FAILED;
     }
@@ -142,9 +142,9 @@
         instance = strcmp(fld_sig[i][1], "instance");
 
         NSK_DISPLAY2(">>> Finding %s field: %s ...\n",
-            (instance==0)?"instance":"static",
+            (instance == 0) ? "instance" : "static",
              fld_sig[i][0]);
-        if (instance==0) {
+        if (instance == 0) {
             if (!NSK_JNI_VERIFY(jni, (testedFld = jni->GetFieldID(objCls, fld_sig[i][0], fld_sig[i][2])) != NULL)) {
                 NSK_COMPLAIN1("TEST FAILERE: unable to get field ID for \"%s\"\n\n",
                     fld_sig[i][0]);
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetJNIFunctionTable/getjniftab001/getjniftab001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetJNIFunctionTable/getjniftab001/getjniftab001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -140,14 +140,14 @@
     if (redir_calls == exCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function table is returned by GetJNIFunctionTable():\n\t%d interception of GetVersion() calls as expected\n",
-                (exCalls==0)?"original":"modified",
+                (exCalls == 0) ? "original" : "modified",
                 redir_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function table is returned by GetJNIFunctionTable() instead of the %s one:\n\t%d interception of GetVersion() calls instead of %d as expected\n",
-            (exCalls==0)?"modified":"original",
-            (exCalls==0)?"original":"modified",
+            (exCalls == 0) ? "modified" : "original",
+            (exCalls == 0) ? "original" : "modified",
             redir_calls, exCalls);
     }
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLineNumberTable/linetab003/linetab003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLineNumberTable/linetab003/linetab003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -123,7 +123,7 @@
         printf("Error expected: JVMTI_ERROR_ABSENT_INFORMATION,\n");
         printf("\tactual: %s (%d)\n", TranslateError(err), err);
         printf("  meth() line number table (%d entries):%s\n",
-               entryCount, (entryCount==0 ? " empty" : ""));
+               entryCount, (entryCount == 0 ? " empty" : ""));
         for (i = 0; i < entryCount; i++) {
             printf("    start_location = 0x%x%08x,",
                    (jint)(table[i].start_location >> 32),
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab003/localtab003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab003/localtab003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -121,7 +121,7 @@
         printf("Error expected: JVMTI_ERROR_ABSENT_INFORMATION,\n");
         printf("\tactual: %s (%d)\n", TranslateError(err), err);
         printf("  meth() local variable table (%d entries):%s\n",
-               entryCount, (entryCount==0 ? " empty" : ""));
+               entryCount, (entryCount == 0 ? " empty" : ""));
         for (i = 0; i < entryCount; i++) {
             printf("    name=\"%s\", sig=\"%s\"",
                 table[i].name, table[i].signature);
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab004/localtab004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab004/localtab004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -104,7 +104,7 @@
             methInfo[i].mid = jni_env->GetStaticMethodID(testedCls, methInfo[i].m_name, methInfo[i].m_sign);
         if (methInfo[i].mid == NULL) {
             NSK_COMPLAIN3("TEST FAILURE: unable to get the method ID for the %s method \"%s\", signature \"%s\"\n\n",
-                methInfo[i].inst?"instance":"static",
+                methInfo[i].inst ? "instance" : "static",
                 methInfo[i].m_name, methInfo[i].m_sign);
             return STATUS_FAILED;
         }
@@ -112,7 +112,7 @@
 /* get the LocalVariableTable attribute */
         if (!NSK_JVMTI_VERIFY(jvmti->GetLocalVariableTable(methInfo[i].mid, &count, &lv_table))) {
             NSK_COMPLAIN3("TEST FAILED: unable to get local variable table\n\tfor the %s method \"%s\", signature \"%s\"\n\n",
-                methInfo[i].inst?"instance":"static",
+                methInfo[i].inst ? "instance" : "static",
                 methInfo[i].m_name, methInfo[i].m_sign);
             return STATUS_FAILED;
         } else {
@@ -121,7 +121,7 @@
                 NSK_COMPLAIN5(
                     "TEST FAILED: %s method \"%s\", signature \"%s\": found %d vars in the LocalVariableTable, expected %d\n"
                     "\tHere are the found vars:\n",
-                    methInfo[i].inst?"instance":"static",
+                    methInfo[i].inst ? "instance" : "static",
                     methInfo[i].m_name, methInfo[i].m_sign,
                     count, methInfo[i].vcount);
                 for (j=0; j<count; j++)
@@ -135,7 +135,7 @@
                 NSK_DISPLAY4(
                     "Checking vars in the LocalVariableTable of the %s method \"%s\", signature \"%s\" ...\n"
                     "\tfound %d local vars as expected\n",
-                    methInfo[i].inst?"instance":"static",
+                    methInfo[i].inst ? "instance" : "static",
                     methInfo[i].m_name, methInfo[i].m_sign, count);
             }
 
@@ -146,7 +146,7 @@
                             NSK_COMPLAIN6(
                                 "TEST FAILED: %s method: \"%s\", signature: \"%s\": var \"%s\" "
                                 "has signature \"%s\" in the LocalVariableTable, expected \"%s\"\n\n",
-                                methInfo[i].inst?"instance":"static",
+                                methInfo[i].inst ? "instance" : "static",
                                 methInfo[i].m_name, methInfo[i].m_sign,
                                 lv_table[j].name, lv_table[j].signature,
                                 methInfo[i].vars[k].v_sign);
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab005/localtab005.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetLocalVariableTable/localtab005/localtab005.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -112,7 +112,7 @@
             methInfo[i].mid = jni_env->GetStaticMethodID(testedCls, methInfo[i].m_name, methInfo[i].m_sign);
         if (methInfo[i].mid == NULL) {
             NSK_COMPLAIN3("TEST FAILURE: unable to get the method ID for the %s method \"%s\", signature \"%s\"\n\n",
-                methInfo[i].inst?"instance":"static",
+                methInfo[i].inst ? "instance" : "static",
                 methInfo[i].m_name, methInfo[i].m_sign);
             return STATUS_FAILED;
         }
@@ -120,24 +120,24 @@
 /* get the LocalVariableTable attribute */
         if (!NSK_JVMTI_VERIFY(jvmti->GetLocalVariableTable(methInfo[i].mid, &count, &lv_table))) {
             NSK_COMPLAIN3("TEST FAILED: unable to get local variable table\n\tfor the %s method \"%s\", signature \"%s\"\n\n",
-                methInfo[i].inst?"instance":"static",
+                methInfo[i].inst ? "instance" : "static",
                 methInfo[i].m_name, methInfo[i].m_sign);
             return STATUS_FAILED;
         } else {
             if (count != methInfo[i].vcount) {
                 totRes = STATUS_FAILED;
                 NSK_COMPLAIN5(
-                    "TEST FAILED: %s method \"%s\", signature \"%s\":"
+                    "TEST FAILED: %s method \"%s\", signature \"%s\" : "
                     "found %d vars in the LocalVariableTable, expected %d\n"
                     "\tHere are the found vars:\n",
-                    methInfo[i].inst?"instance":"static",
+                    methInfo[i].inst ? "instance" : "static",
                     methInfo[i].m_name, methInfo[i].m_sign,
                     count, methInfo[i].vcount);
                 for (j=0; j<count; j++)
                     NSK_COMPLAIN4("\t%d) name: \"%s\"\n\tsignature: \"%s\"\n\tgeneric signature: \"%s\"\n",
                         j+1, lv_table[j].name,
                         lv_table[j].signature,
-                       (lv_table[j].generic_signature==NULL)?"NULL":lv_table[j].generic_signature);
+                       (lv_table[j].generic_signature == NULL) ? "NULL" : lv_table[j].generic_signature);
                 NSK_COMPLAIN0("\n");
 
                 continue;
@@ -147,7 +147,7 @@
                     ">>> Checking vars in the LocalVariableTable of the %s method \"%s\","
                     "signature \"%s\" ...\n"
                     "\t%d local vars as expected\n",
-                    methInfo[i].inst?"instance":"static",
+                    methInfo[i].inst ? "instance" : "static",
                     methInfo[i].m_name, methInfo[i].m_sign, count);
             }
 
@@ -155,19 +155,19 @@
                 for (k=0; k<count; k++) {
                     if (strcmp(lv_table[j].name, methInfo[i].vars[k].v_name) == 0) {
                         if ((strcmp(lv_table[j].signature, methInfo[i].vars[k].v_sign) != 0) ||
-                            (strcmp((lv_table[j].generic_signature==NULL)?"NULL":lv_table[j].generic_signature,
+                            (strcmp((lv_table[j].generic_signature == NULL) ? "NULL" : lv_table[j].generic_signature,
                                 methInfo[i].vars[k].v_gen_sign) != 0)) {
                             NSK_COMPLAIN8(
                                 "TEST FAILED: %s method: \"%s\" \"%s\":\n"
                                 "\tvar \"%s\" has signature \"%s\",\n"
                                 "\tgeneric signature \"%s\"\n\n"
                                 "\tExpected: \"%s\"\n\t\t\"%s\"\n\n",
-                                methInfo[i].inst?"instance":"static",
+                                methInfo[i].inst ? "instance" : "static",
                                 methInfo[i].m_name, methInfo[i].m_sign,
                                 lv_table[j].name, lv_table[j].signature,
-                               (lv_table[j].generic_signature==NULL)?"NULL":lv_table[j].generic_signature,
+                               (lv_table[j].generic_signature == NULL) ? "NULL" : lv_table[j].generic_signature,
                                 methInfo[i].vars[k].v_sign,
-                               (methInfo[i].vars[k].v_gen_sign==NULL)?"NULL":methInfo[i].vars[k].v_gen_sign);
+                               (methInfo[i].vars[k].v_gen_sign == NULL) ? "NULL" : methInfo[i].vars[k].v_gen_sign);
                             totRes = STATUS_FAILED;
                             break;
                         }
@@ -175,7 +175,7 @@
                             NSK_DISPLAY3("CHECK PASSED: var: \"%s\",\n\tsignature: \"%s\",\n\tgeneric signature: \"%s\"\n",
                                 lv_table[j].name,
                                 lv_table[j].signature,
-                               (lv_table[j].generic_signature==NULL)?"NULL":lv_table[j].generic_signature);
+                               (lv_table[j].generic_signature == NULL) ? "NULL" : lv_table[j].generic_signature);
                     }
                 }
             }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetMethodName/methname003/methname003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetMethodName/methname003/methname003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -98,17 +98,17 @@
             meth_sig[clsIdx][methIdx][0]);
 
         if (strcmp(meth_sig[clsIdx][methIdx][2], sign) != 0 ||
-                strcmp(meth_sig[clsIdx][methIdx][3], (gen_sign==NULL)?"NULL":gen_sign) != 0) {
+                strcmp(meth_sig[clsIdx][methIdx][3], (gen_sign == NULL) ? "NULL" : gen_sign) != 0) {
             NSK_COMPLAIN5("TEST FAILED: class: \"%s\" \
 has\n\tsignature: \"%s\"\n\tgeneric signature: \"%s\"\n\n\tExpected: \"%s\"\n\t\t\"%s\"\n\n",
                 meth_sig[clsIdx][methIdx][0],
-                sign, (gen_sign==NULL)?"NULL":gen_sign,
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign,
                 meth_sig[clsIdx][methIdx][2], meth_sig[clsIdx][methIdx][3]);
             totRes = STATUS_FAILED;
         }
         else
             NSK_DISPLAY2("CHECK PASSED: signature: \"%s\",\n\tgeneric signature: \"%s\"\n",
-                sign, (gen_sign==NULL)?"NULL":gen_sign);
+                sign, (gen_sign == NULL) ? "NULL" : gen_sign);
 
         NSK_DISPLAY0("Deallocating name & signature arrays\n");
         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) name))) {
@@ -117,7 +117,7 @@
         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) sign))) {
             totRes = STATUS_FAILED;
         }
-        if (gen_sign!=NULL)
+        if (gen_sign != NULL)
             if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*) gen_sign))) {
                 totRes = STATUS_FAILED;
             }
@@ -137,9 +137,9 @@
         instance = strcmp(meth_sig[clsIdx][i][1], "instance");
 
         NSK_DISPLAY2(">>> Finding %s method: %s ...\n",
-            (instance==0)?"instance":"static",
+            (instance == 0) ? "instance" : "static",
              meth_sig[clsIdx][i][0]);
-        if (instance==0) {
+        if (instance == 0) {
             if (!NSK_JNI_VERIFY(jni, (testedMeth = jni->GetMethodID(objCls, meth_sig[clsIdx][i][0], meth_sig[clsIdx][i][2])) != NULL)) {
                 NSK_COMPLAIN2("TEST FAILERE: unable to get method ID for \"%s\" \"%s\"\n\n",
                     meth_sig[clsIdx][i][0], meth_sig[clsIdx][i][2]);
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetTopThreadGroups/topthrgrp001/topthrgrp001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetTopThreadGroups/topthrgrp001/topthrgrp001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -102,7 +102,7 @@
                 printf(">>>         parent: 0x%p\n", inf.parent);
                 printf(">>>   max priority: %d\n", inf.max_priority);
                 printf(">>>      is daemon: %s\n",
-                       (inf.is_daemon==JNI_TRUE) ? "true" : "false");
+                       (inf.is_daemon == JNI_TRUE) ? "true" : "false");
             }
             if (inf.parent != NULL) {
                 printf("ERROR: thread group is not parentless!\n");
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/callbacks/Callbacks.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/callbacks/Callbacks.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -127,7 +127,7 @@
 int get_tag_type(const char *signature) {
   if (is_primitive_type(signature)) {
     return TAG_TYPE_PRIMITIVE;
-  } else if (signature[0]=='[' && is_primitive_type(signature+1)) {
+  } else if (signature[0] == '[' && is_primitive_type(signature+1)) {
     return TAG_TYPE_ARRAY;
   } else if (!strcmp(signature, "Ljava/lang/String;")) {
     return TAG_TYPE_STRING;
@@ -143,21 +143,21 @@
 jboolean verify_value(jvalue value, jvmtiPrimitiveType type) {
   switch (type) {
   case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
-    return value.z==BOOLEAN;
+    return value.z == BOOLEAN;
   case JVMTI_PRIMITIVE_TYPE_BYTE:
-    return value.b==BYTE;
+    return value.b == BYTE;
   case JVMTI_PRIMITIVE_TYPE_CHAR:
-    return value.c==CHAR;
+    return value.c == CHAR;
   case JVMTI_PRIMITIVE_TYPE_SHORT:
-    return value.s==SHORT;
+    return value.s == SHORT;
   case JVMTI_PRIMITIVE_TYPE_INT:
-    return value.i==INT;
+    return value.i == INT;
   case JVMTI_PRIMITIVE_TYPE_LONG:
-    return value.j==LONG;
+    return value.j == LONG;
   case JVMTI_PRIMITIVE_TYPE_FLOAT:
-    return value.f==FLOAT;
+    return value.f == FLOAT;
   case JVMTI_PRIMITIVE_TYPE_DOUBLE:
-    return value.d==DOUBLE;
+    return value.d == DOUBLE;
   default:
     NSK_COMPLAIN1("Unknown type: %X.",type);
     return JNI_FALSE;
@@ -245,7 +245,7 @@
   int i;
 
   //skip all untegged strings
-  if (*tag_ptr==0) {
+  if (*tag_ptr == 0) {
     return 0;
   } else if (DECODE_TYPE(*tag_ptr) != TAG_TYPE_STRING) {
     NSK_COMPLAIN2("jvmtiStringPrimitiveValueCallback was invoked for an object "
@@ -341,7 +341,7 @@
 
 JNIEXPORT void JNICALL
 object_free_callback(jvmtiEnv* jvmti, jlong tag) {
-  if (DECODE_TYPE(tag)==TAG_TYPE_PRIMITIVE) {
+  if (DECODE_TYPE(tag) == TAG_TYPE_PRIMITIVE) {
     int object = DECODE_OBJECT(tag);
     objects_info[object].collected = 1;
     NSK_DISPLAY1("Object %s collected.\n",
@@ -523,7 +523,7 @@
   }
 
   NSK_DISPLAY0("Tagging fields.\n");
-  if (!NSK_VERIFY(JNI_OK==tag_objects(jvmti, jni))) {
+  if (!NSK_VERIFY(JNI_OK == tag_objects(jvmti, jni))) {
     return;
   }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/concrete-klass-filter/ConcreteKlassFilter.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/concrete-klass-filter/ConcreteKlassFilter.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -212,7 +212,7 @@
   }
 
   NSK_DISPLAY0("Tagging fields.\n");
-  if (!NSK_VERIFY(JNI_OK==tag_objects(jvmti, jni))) {
+  if (!NSK_VERIFY(JNI_OK == tag_objects(jvmti, jni))) {
     return;
   }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/filter-tagged/HeapFilter.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/IterateThroughHeap/filter-tagged/HeapFilter.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -228,7 +228,7 @@
         int matched = 1;
         int i;
         for (i = 0; i < element_count && matched; i++) {
-          matched = ((jint*)objects_info[object].fields[field].value)[i]==
+          matched = ((jint*)objects_info[object].fields[field].value)[i] ==
             ((jint*)elements)[i];
         }
         if (matched)
@@ -268,22 +268,18 @@
   if (field->primitive) {
     field->size = (int) sizeof(jint);
     if (is_static) {
-      field->value = (void*)(tagged ? &TAGGED_STATIC_INT_VALUE:
-                             &UNTAGGED_STATIC_INT_VALUE);
+      field->value = (void*)(tagged ? &TAGGED_STATIC_INT_VALUE : &UNTAGGED_STATIC_INT_VALUE);
     } else {
-      field->value = (void*)(tagged ? &TAGGED_INT_VALUE:
-                             &UNTAGGED_INT_VALUE);
+      field->value = (void*)(tagged ? &TAGGED_INT_VALUE : &UNTAGGED_INT_VALUE);
     }
     field->type = TYPE_FIELD;
-  } else if (0==strcmp(field->signature,STRING_SIGNATURE)) {
-    field->value = (void*)(tagged ? TAGGED_STRING_VALUE:
-                           UNTAGGED_STRING_VALUE);
+  } else if (0 == strcmp(field->signature,STRING_SIGNATURE)) {
+    field->value = (void*)(tagged ? TAGGED_STRING_VALUE : UNTAGGED_STRING_VALUE);
     field->size = (int) wcslen((wchar_t*)field->value);
     field->type = TYPE_STRING;
-  } else if (0==strcmp(field->signature,INT_ARRAY_SIGNATURE)) {
+  } else if (0 == strcmp(field->signature,INT_ARRAY_SIGNATURE)) {
     field->size = INT_ARRAY_LENGTH;
-    field->value = (void*)(tagged ? TAGGED_INT_ARRAY_VALUE:
-                           UNTAGGED_INT_ARRAY_VALUE);
+    field->value = (void*)(tagged ? TAGGED_INT_ARRAY_VALUE : UNTAGGED_INT_ARRAY_VALUE);
     field->type = TYPE_ARRAY;
   }
 }
@@ -427,7 +423,7 @@
 void verify_objects(int reachable) {
   int object;
   int field;
-  for (object = 0; object < (reachable?TEST_OBJECTS_COUNT:TAGGED_OBJECTS); object++) {
+  for (object = 0; object < (reachable ? TEST_OBJECTS_COUNT : TAGGED_OBJECTS); object++) {
     for (field = 0; field < objects_info[object].fields_count; field++) {
       // If primitive field of object that was not collected or
       // non primitive field that was not collected was not found
@@ -468,7 +464,7 @@
   }
 
   NSK_DISPLAY0("Tagging fields.\n");
-  if (!NSK_VERIFY(JNI_OK==tag_objects(jvmti, jni))) {
+  if (!NSK_VERIFY(JNI_OK == tag_objects(jvmti, jni))) {
     return;
   }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/NativeMethodBind/nativemethbind002/nativemethbind002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/NativeMethodBind/nativemethbind002/nativemethbind002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -82,10 +82,10 @@
         NSK_DISPLAY2("NativeMethodBind received for \"%s %s\"\n",
             methNam, methSig);
 
-    if (!(methNam==NULL))
+    if (methNam != NULL)
         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*) methNam)))
             NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n");
-    if (!(methSig==NULL))
+    if (methSig != NULL)
         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*) methSig)))
             NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method signature\n\n");
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe004/popframe004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe004/popframe004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -287,7 +287,7 @@
         tot_result = STATUS_FAILED;
         return;
     }
-    if (vrb ==1) {
+    if (vrb == 1) {
         printf("nativeMeth2(): calling the Java activeMethod()\n");
         fflush(stdout);
     }
@@ -297,7 +297,7 @@
 JNIEXPORT void JNICALL
 Java_nsk_jvmti_PopFrame_popframe004_nativeMeth(JNIEnv *env, jobject obj, jint vrb,
         jobject frameThr) {
-    if (vrb ==1) {
+    if (vrb == 1) {
         printf("nativeMeth(): calling the native nativeMeth2()\n");
         fflush(stdout);
     }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass008/redefclass008.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass008/redefclass008.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -163,7 +163,7 @@
                 ">>>>>>>> #%d Invoke SetBreakpoint():\n"
                 "\tbreakpoint in the %s method: name=\"%s\"; "
                 "signature=\"%s\"; location=%d\n",
-                i, breakpoints[i].inst?"instance":"static",
+                i, breakpoints[i].inst ? "instance" : "static",
                 breakpoints[i].m_name, breakpoints[i].m_sign, breakpoints[i].loc);
         }
 
@@ -268,7 +268,7 @@
                 "TEST FAILED: Breakpoint #%d in the %s method:\n"
                 "\tname=\"%s\"; signature=\"%s\"; location=%d was not cleared:\n"
                 "\tClearBreakpoint() returned the error %d: %s\n\n",
-                i, breakpoints[i].inst?"instance":"static",
+                i, breakpoints[i].inst ? "instance" : "static",
                 breakpoints[i].m_name, breakpoints[i].m_sign,
                 breakpoints[i].loc, err, TranslateError(err));
             totRes = STATUS_FAILED;
@@ -278,7 +278,7 @@
                     "Check #%d PASSED: Breakpoint in the %s method:\n"
                     "\tname=\"%s\"; signature=\"%s\"; location=%d was cleared:\n"
                     "\tClearBreakpoint() returned the error %d: %s\n\n",
-                    i, breakpoints[i].inst?"instance":"static",
+                    i, breakpoints[i].inst ? "instance" : "static",
                     breakpoints[i].m_name, breakpoints[i].m_sign,
                     breakpoints[i].loc, err, TranslateError(err));
             }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass009/redefclass009.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass009/redefclass009.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -176,7 +176,7 @@
         }
         if (methodsInfo[i].mid == NULL) {
             printf("%s: Failed to get the method ID for the%s%s method \"%s\", signature \"%s\"\n",
-                __FILE__, full?" ":" original ", methodsInfo[i].inst?"instance":"static",
+                __FILE__, full ? " " : " original ", methodsInfo[i].inst ? "instance":"static",
                 methodsInfo[i].m_name, methodsInfo[i].m_sign);
             return STATUS_FAILED;
         }
@@ -187,7 +187,7 @@
             printf("%s: Failed to call GetLocalVariableTable(): error=%d: %s\n",
                 __FILE__, err, TranslateError(err));
             printf("\tfor the%s%s method \"%s\", signature \"%s\"\n\n",
-                full?" ":" original ", methodsInfo[i].inst?"instance":"static",
+                full ? " " : " original ", methodsInfo[i].inst ? "instance":"static",
                 methodsInfo[i].m_name, methodsInfo[i].m_sign);
             return STATUS_FAILED;
         } else {
@@ -195,7 +195,7 @@
                 printf(
                     "TEST FAILED: %s%s method \"%s\", signature \"%s\": "
                     "found %d vars in the LocalVariableTable, expected %d\n",
-                    full?" ":" original ", methodsInfo[i].inst?"instance":"static",
+                    full ? " " : " original ", methodsInfo[i].inst ? "instance":"static",
                     methodsInfo[i].m_name, methodsInfo[i].m_sign,
                     count, methodsInfo[i].vcount);
                 totRes = STATUS_FAILED;
@@ -206,7 +206,7 @@
                     "\nChecking vars in the LocalVariableTable of the %s method \"%s\", "
                     "signature \"%s\" ...\n"
                     "\tfound %d local vars as expected\n",
-                    methodsInfo[i].inst?"instance":"static",
+                    methodsInfo[i].inst ? "instance" : "static",
                     methodsInfo[i].m_name, methodsInfo[i].m_sign, count);
 
             if (full) {
@@ -217,7 +217,7 @@
                                 printf(
                                     "TEST FAILED: %s method \"%s\", signature \"%s\": var \"%s\" "
                                     "has signature \"%s\" in the LocalVariableTable, expected \"%s\"\n",
-                                    methodsInfo[i].inst?"instance":"static",
+                                    methodsInfo[i].inst ? "instance" : "static",
                                     methodsInfo[i].m_name, methodsInfo[i].m_sign,
                                     lv_table[j].name, lv_table[j].signature,
                                     methodsInfo[i].vars[k].v_sign);
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass010/redefclass010.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass010/redefclass010.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -154,7 +154,8 @@
         }
         if (methodsInfo[i].mid == NULL) {
             printf("%s: Failed to get the method ID for the%s%s method \"%s\", signature \"%s\"\n",
-                __FILE__, (vrb==2)?" original ":" ", methodsInfo[i].inst?"instance":"static",
+                __FILE__, (vrb == 2) ? " original " : " ",
+                methodsInfo[i].inst ? "instance" : "static",
                 methodsInfo[i].m_name, methodsInfo[i].m_sign);
             return STATUS_FAILED;
         }
@@ -165,15 +166,16 @@
             printf("%s: Failed to call GetLineNumberTable(): error=%d: %s\n",
                 __FILE__, err, TranslateError(err));
             printf("\tfor the%s%s method \"%s\", signature \"%s\"\n\n",
-                (vrb==2)?" original ":" ", methodsInfo[i].inst?"instance":"static",
+                (vrb == 2) ? " original " : " ",
+                methodsInfo[i].inst ? "instance" : "static",
                 methodsInfo[i].m_name, methodsInfo[i].m_sign);
             return STATUS_FAILED;
         } else {
             if (count != methodsInfo[i].lcount) {
                 printf(
                     "TEST %s %s method \"%s\", signature \"%s\": found %d lines in the LineNumberTable, expected %d\n",
-                    (vrb==2)?"BUG: original ":"FAILED:",
-                    methodsInfo[i].inst?"instance":"static",
+                    (vrb == 2) ? "BUG: original " : "FAILED:",
+                    methodsInfo[i].inst ? "instance" : "static",
                     methodsInfo[i].m_name, methodsInfo[i].m_sign,
                     count, methodsInfo[i].lcount);
                 totRes = STATUS_FAILED;
@@ -183,7 +185,7 @@
                 printf(
                     "\nChecking line numbers in the LineNumberTable of the %s method \"%s\", signature \"%s\" ...\n"
                     "\toverall number of lines: %d as expected\n",
-                    methodsInfo[i].inst?"instance":"static",
+                    methodsInfo[i].inst ? "instance" : "static",
                     methodsInfo[i].m_name, methodsInfo[i].m_sign, count);
 
             for (j=0; j<count; j++) {
@@ -196,8 +198,8 @@
                     printf(
                         "TEST %s %s method \"%s\", signature \"%s\": "
                         "entry #%d has value %d in the LineNumberTable, expected %d\n",
-                        (vrb==2)?"BUG: original":"FAILED:",
-                        methodsInfo[i].inst?"instance":"static",
+                        (vrb == 2) ? "BUG: original" : "FAILED:",
+                        methodsInfo[i].inst ? "instance" : "static",
                         methodsInfo[i].m_name, methodsInfo[i].m_sign,
                         j, ln_table[j].line_number, chkval);
                     totRes = STATUS_FAILED;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/setjniftab001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/setjniftab001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -199,15 +199,15 @@
     if (monent_calls == exMonEntCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function MonitorEnter() has been %s inside %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored", msg,
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored", msg,
                 monent_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function MonitorEnter() has not been %s inside %s:\n\t%d intercepted call(s) instead of %d as expected\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored", msg,
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored", msg,
             monent_calls, exMonEntCalls);
     }
 }
@@ -382,10 +382,10 @@
        and check the assertion with current thread and new threads */
     if (verbose)
         printf("\nc) Checking the restored JNI function table ...\n");
-    doRestore((nextEnv==NULL)? env:nextEnv);
+    doRestore((nextEnv == NULL) ? env : nextEnv);
 
     zeroCounter();
-    doExec((nextEnv==NULL)? env:nextEnv, 0);
+    doExec((nextEnv == NULL) ? env : nextEnv, 0);
     checkCall(2, 0, "main thread");
 
     zeroCounter();
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003/suspendthrd003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003/suspendthrd003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -121,7 +121,7 @@
 
         printf("INFO: made %d late calls to JVM/TI SuspendThread()\n",
                late_count);
-        printf("INFO: N_LATE_CALLS==%d value is %slarge enough to cause a "
+        printf("INFO: N_LATE_CALLS == %d value is %slarge enough to cause a "
                "SuspendThread() call after thread exit.\n", N_LATE_CALLS,
                (late_count == N_LATE_CALLS) ? "NOT " : "");
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/capability/CM01/cm01t011/cm01t011.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/capability/CM01/cm01t011/cm01t011.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -335,7 +335,7 @@
 */
 
     for (i = 0; i < count; i++) {
-        if (strcmp(local_variable_table[i].name, "o") ==0) {
+        if (strcmp(local_variable_table[i].name, "o") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalObject\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalObject(thread, 1, local_variable_table[i].slot, &object_value)))
@@ -345,7 +345,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalObject(thread, 1, local_variable_table[i].slot, object_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "i") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "i") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalInt\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalInt(thread, 1, local_variable_table[i].slot, &int_value)))
@@ -355,7 +355,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalInt(thread, 1, local_variable_table[i].slot, int_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "l") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "l") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalLong\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalLong(thread, 1, local_variable_table[i].slot, &long_value)))
@@ -365,7 +365,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalLong(thread, 1, local_variable_table[i].slot, long_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "f") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "f") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalFloat\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalFloat(thread, 1, local_variable_table[i].slot, &float_value)))
@@ -375,7 +375,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalFloat(thread, 1, local_variable_table[i].slot, float_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "d") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "d") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalDouble\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalDouble(thread, 1, local_variable_table[i].slot, &double_value)))
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/cm03t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/cm03t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -556,7 +556,7 @@
         return NSK_FALSE;
 
     for (i = 0; i < count; i++) {
-        if (strcmp(local_variable_table[i].name, "o") ==0) {
+        if (strcmp(local_variable_table[i].name, "o") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalObject\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalObject(thread, 1, local_variable_table[i].slot, &object_value)))
@@ -566,7 +566,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalObject(thread, 1, local_variable_table[i].slot, object_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "i") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "i") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalInt\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalInt(thread, 1, local_variable_table[i].slot, &int_value)))
@@ -576,7 +576,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalInt(thread, 1, local_variable_table[i].slot, int_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "l") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "l") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalLong\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalLong(thread, 1, local_variable_table[i].slot, &long_value)))
@@ -586,7 +586,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalLong(thread, 1, local_variable_table[i].slot, long_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "f") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "f") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalFloat\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalFloat(thread, 1, local_variable_table[i].slot, &float_value)))
@@ -596,7 +596,7 @@
             if (!NSK_JVMTI_VERIFY(
                     jvmti->SetLocalFloat(thread, 1, local_variable_table[i].slot, float_value)))
                 return NSK_FALSE;
-        } else if (strcmp(local_variable_table[i].name, "d") ==0) {
+        } else if (strcmp(local_variable_table[i].name, "d") == 0) {
             NSK_DISPLAY0("Checking positive: GetLocalDouble\n");
             if (!NSK_JVMTI_VERIFY(
                     jvmti->GetLocalDouble(thread, 1, local_variable_table[i].slot, &double_value)))
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC05/tc05t001/tc05t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC05/tc05t001/tc05t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -122,7 +122,7 @@
         waitedEventsCount++;
         NSK_DISPLAY0("MonitorWaited event:\n");
         NSK_DISPLAY3("\tthread: %p, object: %p, timed_out: %s\n",
-            thr, obj, (timed_out==JNI_TRUE) ? "true" : "false");
+            thr, obj, (timed_out == JNI_TRUE) ? "true" : "false");
         NSK_DISPLAY1("\tGetTime: %s\n",
             jlong_to_string(waitedTime, buffer));
         NSK_DISPLAY1("\tthread CPU time: %s\n",
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM04/em04t001/em04t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM04/em04t001/em04t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -96,7 +96,7 @@
             rec->sign = 1;
             NSK_DISPLAY3("checked: 0x%p %7d %s\n", rec->address, rec->length,
                                 rec->name);
-            if (strncmp(rec->name, name, compLength)!=0) {
+            if (strncmp(rec->name, name, compLength) != 0) {
                 NSK_DISPLAY2("\t<%s> was renamed to <%s>\n", rec->name, name);
             }
             return;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM06/em06t001/em06t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM06/em06t001/em06t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -75,7 +75,7 @@
 
     className = jni_env->GetStringUTFChars(jclassName, 0);
 
-    if (className != NULL && (strcmp(className, EXPECTED_CLASS_NAME)==0)) {
+    if (className != NULL && (strcmp(className, EXPECTED_CLASS_NAME) == 0)) {
 
         if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
             nsk_jvmti_setFailStatus();
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS104/hs104t001/hs104t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS104/hs104t001/hs104t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -75,7 +75,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t003/hs201t003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t003/hs201t003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -169,14 +169,14 @@
             (methBytesCount != redefMethBytesCount && isObsolete == JNI_FALSE)) {
         NSK_DISPLAY3("[%s] CHECK PASSED: IsMethodObsolete = %d(%s) as expected\n",
             event, (int)isObsolete,
-            (isObsolete==JNI_TRUE)?"TRUE":"FALSE");
+            (isObsolete == JNI_TRUE) ? "TRUE" : "FALSE");
     }
     else {
         nsk_jvmti_setFailStatus();
         NSK_COMPLAIN4("[%s] TEST FAILED: IsMethodObsolete = %d(%s), expected: %s\n",
             event, (int)isObsolete,
-            (isObsolete == JNI_TRUE)?"TRUE":"FALSE",
-            (methBytesCount == redefMethBytesCount)?"TRUE":"FALSE");
+            (isObsolete == JNI_TRUE) ? "TRUE" : "FALSE",
+            (methBytesCount == redefMethBytesCount) ? "TRUE" : "FALSE");
     }
 }
 
@@ -185,7 +185,7 @@
         jthread thr, jmethodID method) {
 
     if (expectedMeth(jvmti_env, "MethodEntry",
-            method, expHSMethod, expHSSignature)==1) {
+            method, expHSMethod, expHSSignature) == 1) {
         if (!NSK_JVMTI_VERIFY(jvmti_env->GetBytecodes(method, &redefMethBytesCount, &redefMethBytes)))
             nsk_jvmti_setFailStatus();
         else {
@@ -207,7 +207,7 @@
         jmethodID catch_method, jlocation catch_location) {
 
     if (expectedMeth(jvmti_env, "Exception",
-            method, expHSMethod, expHSSignature)==1) {
+            method, expHSMethod, expHSSignature) == 1) {
         NSK_DISPLAY1("[Exception] thread=0x%p\n", thr);
 
         doHotSwap(jvmti_env, method, "Exception");
@@ -221,7 +221,7 @@
         jboolean was_poped_by_exc, jvalue return_value) {
 
     if (expectedMeth(jvmti_env, "MethodExit",
-            method, expHSMethod, expHSSignature)==1) {
+            method, expHSMethod, expHSSignature) == 1) {
         NSK_DISPLAY1("[MethodExit] thread=0x%p\n", thr);
 
         doHotSwap(jvmti_env, method, "MethodExit");
@@ -233,7 +233,7 @@
 FramePop(jvmtiEnv *jvmti_env, JNIEnv *env,
         jthread thr, jmethodID method, jboolean wasPopedByException) {
     if (expectedMeth(jvmti_env, "FramePop",
-            method, expHSMethod, expHSSignature)==1) {
+            method, expHSMethod, expHSSignature) == 1) {
         NSK_DISPLAY1("[FramePop] thread=0x%p\n", thr);
 
         doHotSwap(jvmti_env, method, "FramePop");
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS202/hs202t002/hs202t002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS202/hs202t002/hs202t002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -74,7 +74,7 @@
                 nsk_printf(" Agent:: redefine class success ..\n");
                 nsk_printf("Agent::SUSPENDING>> \n");
                 err=jvmti_env->SuspendThread(thread);
-                if (err ==  JVMTI_ERROR_NONE) {
+                if (err == JVMTI_ERROR_NONE) {
                     thread_suspend_status = suspended;
                     nsk_printf("Agent:: Thread successfully suspended..\n");
                 } else if (err == JVMTI_ERROR_THREAD_SUSPENDED) {
@@ -102,7 +102,7 @@
     nsk_printf("Agent:: VM.. Started..\n");
     redefineNumber=0;
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t001/hs203t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t001/hs203t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -104,7 +104,7 @@
     }
     nsk_printf(" End of REDEFINE CLASS LOADER \n");
     err=jvmti->SuspendThread(thread);
-    if (err ==  JVMTI_ERROR_NONE) {
+    if (err == JVMTI_ERROR_NONE) {
         nsk_printf("Agent:: Succeded in suspending..\n");
     } else {
         nsk_printf(" ## Error occured %s \n",TranslateError(err));
@@ -139,7 +139,7 @@
     jint rc ;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -105,7 +105,7 @@
         return;
     }
     err=jvmti->SuspendThread(thread);
-    if (err ==  JVMTI_ERROR_NONE) {
+    if (err == JVMTI_ERROR_NONE) {
         nsk_printf("Agent:: Succeded in suspending..\n");
     } else {
         nsk_printf(" ## Error occured %s \n",TranslateError(err));
@@ -140,7 +140,7 @@
         jint rc ;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t001/hs204t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t001/hs204t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -64,7 +64,7 @@
         jclass klass) {
     char * name;
     name = getClassName(jvmti_env,klass);
-    if ((strcmp(name,CLASS_NAME) == 0) && (redefineNumber== 1)) {
+    if ((strcmp(name,CLASS_NAME) == 0) && (redefineNumber == 1)) {
        char fileName[512];
         nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName,
                         sizeof(fileName)/sizeof(char));
@@ -89,7 +89,7 @@
         jclass klass) {
     char *  name;
     name = getClassName(jvmti_env, klass);
-    if ((strcmp(name, CLASS_NAME) ==0) && (redefineNumber == 0)) {
+    if ((strcmp(name, CLASS_NAME) == 0) && (redefineNumber == 0)) {
         char fileName[512];
         nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName,
                         sizeof(fileName)/sizeof(char));
@@ -118,7 +118,7 @@
         const unsigned char* class_data,
         jint* new_class_data_len,
         unsigned char** new_class_data) {
-    if (name != NULL && strcmp(name, NAME)==0 && (redefineNumber == 1)) {
+    if (name != NULL && strcmp(name, NAME) == 0 && (redefineNumber == 1)) {
         NSK_DISPLAY1(">>>>>>callbackClassFileLoadHock ... Name=%s...  >>\n",name);
         /*redefineClass(jvmti_env, myTestClass);*/
     }
@@ -175,7 +175,7 @@
     jint rc ;
     NSK_DISPLAY0(" VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         NSK_COMPLAIN0(" Could not load JVMTI interface \n");
     } else {
         /* Open simple block for better memor usage. */
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t002/hs204t002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t002/hs204t002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -77,7 +77,7 @@
                     err= jvmti->SetBreakpoint(method, start+1);
                     if (err == JVMTI_ERROR_DUPLICATE) {
                         printf("Agent::JVMTI_ERROR_DUPLICATE");
-                    } else if (err ==JVMTI_ERROR_INVALID_METHODID) {
+                    } else if (err == JVMTI_ERROR_INVALID_METHODID) {
                         printf("Agent::JVMTI_ERROR_INVALID_METHODID ");
                     } else if (err == JVMTI_ERROR_INVALID_LOCATION) {
                         printf("Agent::JVMTI_ERROR_INVALID_LOCATION ");
@@ -128,7 +128,7 @@
     jint rc ;
     printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t004/hs204t004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t004/hs204t004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -104,7 +104,7 @@
     }
     nsk_printf(" End of REDEFINE CLASS LOADER \n");
     err=jvmti->SuspendThread(thread);
-    if (err ==  JVMTI_ERROR_NONE) {
+    if (err == JVMTI_ERROR_NONE) {
         nsk_printf("Agent:: Succeded in suspending..\n");
     } else if (err == JVMTI_ERROR_THREAD_SUSPENDED) {
         nsk_printf("Agent:: JVMTI_ERROR_THREAD_SUSPENDED \n");
@@ -133,7 +133,7 @@
       jint rc ;
       nsk_printf("Agent:: VM.. Started..\n");
       rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-      if (rc!= JNI_OK) {
+      if (rc != JNI_OK) {
           nsk_printf("Agent:: Could not load JVMTI interface \n");
           return JNI_ERR;
       } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS301/hs301t004/hs301t004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS301/hs301t004/hs301t004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -47,7 +47,7 @@
             nsk_jvmti_disableNotification(jvmti_env, JVMTI_EVENT_CLASS_PREPARE, NULL);
             nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName,
                     sizeof(fileName)/sizeof(char));
-            if (nsk_jvmti_redefineClass(jvmti_env, klass, fileName)  == NSK_TRUE) {
+            if (nsk_jvmti_redefineClass(jvmti_env, klass, fileName) == NSK_TRUE) {
                 nsk_printf("Agent:: Redefine successful.\n");
             } else {
                 nsk_printf("Agent:: Redefine failed.\n");
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS301/hs301t005/hs301t005.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS301/hs301t005/hs301t005.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -67,7 +67,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t001/hs302t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t001/hs302t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -67,7 +67,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t002/hs302t002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t002/hs302t002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -69,7 +69,7 @@
 
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t003/hs302t003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t003/hs302t003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -70,7 +70,7 @@
 
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t004/hs302t004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t004/hs302t004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -67,7 +67,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t005/hs302t005.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t005/hs302t005.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -69,7 +69,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t006/hs302t006.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t006/hs302t006.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -68,7 +68,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t007/hs302t007.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t007/hs302t007.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -65,7 +65,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t009/hs302t009.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t009/hs302t009.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -68,7 +68,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t010/hs302t010.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t010/hs302t010.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -67,7 +67,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t011/hs302t011.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t011/hs302t011.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -68,7 +68,7 @@
     jvmtiEnv * jvmti;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t012/hs302t012.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS302/hs302t012/hs302t012.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -46,7 +46,7 @@
         nsk_jvmti_disableNotification(jvmti_env, JVMTI_EVENT_CLASS_PREPARE, NULL);
         nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName,
                         sizeof(fileName)/sizeof(char));
-        if (nsk_jvmti_redefineClass(jvmti_env, klass, fileName)  == NSK_TRUE) {
+        if (nsk_jvmti_redefineClass(jvmti_env, klass, fileName) == NSK_TRUE) {
             nsk_printf("Redefine successful ..\n");
         } else {
             nsk_printf("# error :: Redefine failed..\n");
@@ -70,7 +70,7 @@
     jint rc ;
     nsk_printf("Agent:: VM.. Started..\n");
     rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
-    if (rc!= JNI_OK) {
+    if (rc != JNI_OK) {
         nsk_printf("Agent:: Could not load JVMTI interface \n");
         return JNI_ERR;
     } else {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI01/ji01t001/ji01t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI01/ji01t001/ji01t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -205,8 +205,8 @@
     if ((exFndCalls > 0 && fnd_calls >= exFndCalls) || (fnd_calls == exFndCalls)) {
             NSK_DISPLAY5("CHECK PASSED: %s: the %s JNI function FindClass() has been %s during %s phase\n\t%d intercepted call(s) as expected\n"
                         , callBackFunc
-                        , (step==1) ? "tested" : "original"
-                        , (step==1) ? "redirected" : "restored"
+                        , (step == 1) ? "tested" : "original"
+                        , (step == 1) ? "redirected" : "restored"
                         , msg
                         , fnd_calls
                         );
@@ -222,8 +222,8 @@
 
         NSK_COMPLAIN6("TEST FAILED: %s: the %s JNI function FindClass() has not been %s during %s phase\n\t%d intercepted call(s) instead of %d as expected\n"
                      , callBackFunc
-                     , (step==1) ? "tested" : "original"
-                     , (step==1) ? "redirected" : "restored"
+                     , (step == 1) ? "tested" : "original"
+                     , (step == 1) ? "redirected" : "restored"
                      , msg
                      , fnd_calls
                      , exFndCalls
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t002/ji03t002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t002/ji03t002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -236,17 +236,17 @@
         if (meth_info[i].jni_calls == exJniCalls) {
             if (verbose)
                 printf("\nCHECK PASSED: the %s JNI function for calling method \"%s %s\" has been %s\n\t%d intercepted call(s) as expected\n",
-                    (step==1)?"tested":"original",
+                    (step == 1) ? "tested" : "original",
                     meth_info[i].m_name, meth_info[i].m_sign,
-                    (step==1)?"redirected":"restored",
+                    (step == 1) ? "redirected" : "restored",
                     meth_info[i].jni_calls);
         }
         else {
             result = STATUS_FAILED;
             printf("\nTEST FAILED: the %s JNI function for calling method \"%s %s\" has not been %s\n\t%d intercepted call(s) instead of %d as expected\n",
-                (step==1)?"tested":"original",
+                (step == 1) ? "tested" : "original",
                 meth_info[i].m_name, meth_info[i].m_sign,
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "redirected" : "restored",
                 meth_info[i].jni_calls, exJniCalls);
         }
         meth_info[i].jni_calls = 0; /* zeroing interception counter */
@@ -255,13 +255,13 @@
             if (verbose)
                 printf("CHECK PASSED: the java method \"%s %s\" has been really invoked by the %s JNI function\n",
                     meth_info[i].m_name, meth_info[i].m_sign,
-                    (step==1)?"redirected":"restored");
+                    (step == 1) ? "redirected" : "restored");
         }
         else {
             result = STATUS_FAILED;
             printf("TEST FAILED: the tested java method \"%s %s\" has not been really invoked by the %s JNI function\n",
                 meth_info[i].m_name, meth_info[i].m_sign,
-                (step==1)?"redirected":"restored");
+                (step == 1) ? "redirected" : "restored");
         }
     }
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t003/ji03t003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t003/ji03t003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -202,15 +202,15 @@
     if (throw_calls == exThrCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function Throw() has been %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored",
                 throw_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function Throw() has not been %s:\n\t%d intercepted call(s) instead of %d as expected\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored",
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored",
             throw_calls, exThrCalls);
     }
     throw_calls = 0; /* zeroing an interception counter */
@@ -218,15 +218,15 @@
     if (thrownew_calls == exThrNewCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function ThrowNew() has been %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored",
                 thrownew_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function ThrowNew() has not been %s:\n\t%d intercepted call(s) instead of %d as expected\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored",
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored",
             thrownew_calls, exThrNewCalls);
     }
     thrownew_calls = 0; /* zeroing an interception counter */
@@ -234,15 +234,15 @@
     if (excoccur_calls == exExcOccCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function ExceptionOccurred() has been %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored",
                 excoccur_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function ExceptionOccurred() has not been %s:\n\t%d intercepted call(s) instead of %d as expected\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored",
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored",
             excoccur_calls, exExcOccCalls);
     }
     excoccur_calls = 0; /* zeroing an interception counter */
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t004/ji03t004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI03/ji03t004/ji03t004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -173,15 +173,15 @@
     if (allobj_calls == exAllObjCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function AllocObject() has been %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored",
                 allobj_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function AllocObject() has not been %s:\t%d intercepted call(s) instead of %d as expected\n\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored",
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored",
             allobj_calls, exAllObjCalls);
     }
     allobj_calls = 0; /* zeroing an interception counter */
@@ -189,15 +189,15 @@
     if (newobj_calls == exNewObjCalls) {
         if (verbose)
             printf("\nCHECK PASSED: the %s JNI function NewObjectV() has been %s:\n\t%d intercepted call(s) as expected\n",
-                (step==1)?"tested":"original",
-                (step==1)?"redirected":"restored",
+                (step == 1) ? "tested" : "original",
+                (step == 1) ? "redirected" : "restored",
                 newobj_calls);
     }
     else {
         result = STATUS_FAILED;
         printf("\nTEST FAILED: the %s JNI function NewObjectV() has not been %s:\n\t%d intercepted call(s) instead of %d as expected\n",
-            (step==1)?"tested":"original",
-            (step==1)?"redirected":"restored",
+            (step == 1) ? "tested" : "original",
+            (step == 1) ? "redirected" : "restored",
             newobj_calls, exNewObjCalls);
     }
     newobj_calls = 0; /* zeroing an interception counter */
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/ji05t001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/ji05t001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -98,19 +98,19 @@
     jvmtiError err;
 
     NSK_DISPLAY1("\n%s JVMTI env: doRedirect: obtaining the JNI function table ...\n",
-        (indx==0)?"first":"second");
+        (indx == 0) ? "first" : "second");
     err = jvmti->GetJNIFunctionTable(&orig_jni_functions[indx]);
     if (err != JVMTI_ERROR_NONE) {
         result = STATUS_FAILED;
         NSK_COMPLAIN2("TEST FAILED: %s JVMTI env: failed to get original JNI function table: %s\n",
-            (indx==0)?"first":"second", TranslateError(err));
+            (indx == 0) ? "first" : "second", TranslateError(err));
         env->FatalError("failed to get original JNI function table");
     }
     err = jvmti->GetJNIFunctionTable(&redir_jni_functions[indx]);
     if (err != JVMTI_ERROR_NONE) {
         result = STATUS_FAILED;
         NSK_COMPLAIN2("TEST FAILED: %s JVMTI env: failed to get redirected JNI function table: %s\n",
-            (indx==0)?"first":"second", TranslateError(err));
+            (indx == 0) ? "first" : "second", TranslateError(err));
         env->FatalError("failed to get redirected JNI function table");
     }
 
@@ -119,18 +119,18 @@
         "\toverwriting the function GetVersion() ...\n",
         (indx == 0) ? "first" : "second");
     redir_jni_functions[indx]->GetVersion =
-        (indx==0)?MyGetVersionA:MyGetVersionB;
+        (indx == 0) ? MyGetVersionA : MyGetVersionB;
 
     err = jvmti->SetJNIFunctionTable(redir_jni_functions[indx]);
     if (err != JVMTI_ERROR_NONE) {
         result = STATUS_FAILED;
         NSK_COMPLAIN2("TEST FAILED: %s JVMTI env: failed to set new JNI function table: %s\n",
-            (indx==0)?"first":"second", TranslateError(err));
+            (indx == 0) ? "first" : "second", TranslateError(err));
         env->FatalError("failed to set new JNI function table");
     }
 
     NSK_DISPLAY1("%s JVMTI env: doRedirect: the functions are overwritten successfully\n",
-        (indx==0)?"first":"second");
+        (indx == 0) ? "first" : "second");
 }
 
 static void provokeIntercept(JNIEnv *env, const char *name) {
@@ -146,22 +146,22 @@
         NSK_DISPLAY5(
             "\nCHECK PASSED: GetVersion() interception set in the %s JVMTI env %s properly:\n"
             "\t%d interception(s) with the%s%s JVMTI env as expected\n",
-            (indx==0)?"first":"second",
-            (exCalls==0)?"overwritten by another environment":"works",
+            (indx == 0) ? "first" : "second",
+            (exCalls == 0) ? "overwritten by another environment" : "works",
             redir_calls[indx],
-            (indx==env_num)?" same ":" ",
-            (env_num==0)?"first":"second");
+            (indx == env_num) ? " same " : " ",
+            (env_num == 0) ? "first" : "second");
     }
     else {
         result = STATUS_FAILED;
         NSK_COMPLAIN6(
             "\nTEST FAILED: GetVersion() interception set in the %s JVMTI env doesn't %s properly:\n"
             "\t%d interception(s) with the%s%s JVMTI env instead of %d as expected\n",
-            (indx==0)?"first":"second",
-            (exCalls==0)?"overwritten by another environment":"work",
+            (indx == 0) ? "first" : "second",
+            (exCalls == 0) ? "overwritten by another environment" : "work",
             redir_calls[indx],
-            (indx==env_num)?" same ":" ",
-            (env_num==0)?"first":"second",
+            (indx == env_num) ? " same " : " ",
+            (env_num == 0) ? "first" : "second",
             exCalls);
         return STATUS_FAILED;
     }
@@ -177,17 +177,17 @@
 
     thrstarted[indx] = redir[indx] = redir_calls[indx] = 0;
 
-    NSK_DISPLAY1("\nagent %s initializer: obtaining the JVMTI env ...\n", (indx==0)?"A":"B");
+    NSK_DISPLAY1("\nagent %s initializer: obtaining the JVMTI env ...\n", (indx == 0) ? "A" : "B");
     res = vm->GetEnv((void **) &jvmti[indx], JVMTI_VERSION_1_1);
     if (res != JNI_OK || jvmti[indx] == NULL) {
         NSK_COMPLAIN1("TEST FAILURE: failed to call GetEnv for the agent %s\n",
-            (indx==0)?"A":"B");
+            (indx == 0) ? "A" : "B");
         result = STATUS_FAILED;
         return STATUS_FAILED;
     }
 
     NSK_DISPLAY1("\nagent %s initializer: the JVMTI env obtained\n\tsetting event callbacks ...\n",
-        (indx==0)?"A":"B");
+        (indx == 0) ? "A" : "B");
     (void) memset(&callbacks, 0, sizeof(callbacks));
     switch (indx) {
     case 0:
@@ -206,16 +206,16 @@
     }
 
     NSK_DISPLAY1("\nagent %s initializer: setting event callbacks done\n\tenabling events ...\n",
-        (indx==0)?"A":"B");
+        (indx == 0) ? "A" : "B");
     err = jvmti[indx]->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
     if (err != JVMTI_ERROR_NONE) { /* enable event globally */
         NSK_COMPLAIN2("TEST FAILURE: failed to enable JVMTI_EVENT_VM_INIT event for the agent %s: %s\n",
-            (indx==0)?"A":"B", TranslateError(err));
+            (indx == 0) ? "A" : "B", TranslateError(err));
         result = STATUS_FAILED;
         return STATUS_FAILED;
     }
     NSK_DISPLAY2("\nagent %s initializer: enabling events done, returning exit code %d\n",
-        (indx==0)?"A":"B", exitCode);
+        (indx == 0) ? "A" : "B", exitCode);
 
     return exitCode;
 }
@@ -224,29 +224,29 @@
     int tries = 0;
 
     NSK_DISPLAY1("\nstartAgent: starting agent %s thread ...\n",
-        (indx==0)?"A":"B");
-    void* context = (void*) ((indx==0)?"agent A":"agent B");
-    agentThr[indx] = THREAD_new((indx==0)?agentA:agentB, context);
+        (indx == 0) ? "A" : "B");
+    void* context = (void*) ((indx == 0) ? "agent A" : "agent B");
+    agentThr[indx] = THREAD_new((indx == 0) ? agentA : agentB, context);
     if (THREAD_start(agentThr[indx]) == NULL) {
         NSK_COMPLAIN1("TEST FAILURE: cannot start the agent %s thread\n",
-            (indx==0)?"A":"B");
+            (indx == 0) ? "A" : "B");
         exit(STATUS_FAILED);
     }
 
     NSK_DISPLAY1("\nstartAgent: waiting for the agent %s to be started ...\n",
-        (indx==0)?"A":"B");
+        (indx == 0) ? "A" : "B");
     do {
         THREAD_sleep(1);
         tries++;
         if (tries > TRIES) {
             NSK_COMPLAIN2("TEST FAILURE: the agent %s thread is still not started after %d attempts\n",
-                (indx==0)?"A":"B", TRIES);
+                (indx == 0) ? "A" : "B", TRIES);
             exit(STATUS_FAILED);
         }
     } while (thrstarted[indx] != 1);
 
     NSK_DISPLAY1("\nstartAgent: the agent %s thread started\n",
-        (indx==0)?"A":"B");
+        (indx == 0) ? "A" : "B");
 }
 
 /* agent thread procedures */
@@ -402,15 +402,15 @@
 
     for (i=0; i<AGENTS; i++) {
         NSK_DISPLAY1("\ngetResult: waiting for the agent %s thread...\n",
-            (i==0)?"A":"B");
+            (i == 0) ? "A" : "B");
         THREAD_waitFor(agentThr[i]);
         if (THREAD_status(agentThr[i]) != PASSED) {
             result = STATUS_FAILED;
             NSK_COMPLAIN2("TEST FAILED: the agent %s thread done with the error code %d\n",
-                (i==0)?"A":"B", THREAD_status(agentThr[i]));
+                (i == 0) ? "A" : "B", THREAD_status(agentThr[i]));
         }
         else NSK_DISPLAY2("getResult: the agent %s thread done with the code %d\n",
-                (i==0)?"A":"B", THREAD_status(agentThr[i]));
+                (i == 0) ? "A" : "B", THREAD_status(agentThr[i]));
         free(agentThr[i]);
     }
 
@@ -439,7 +439,7 @@
 
     for (i=0; i<AGENTS; i++) {
         NSK_DISPLAY1("initializing agent %s ...\n",
-                (i==0)?"A":"B");
+                (i == 0) ? "A" : "B");
         if (initAgent(i) != PASSED)
             return JNI_ERR;
     }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLineNumberTable/linetab004/linetab004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLineNumberTable/linetab004/linetab004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -104,7 +104,7 @@
     err = jvmti->GetLineNumberTable(mid, &entryCount, &table);
     if (printdump == JNI_TRUE) {
         printf("\n Method: %s%s\n", methName,
-            (abstract==0) ? "" : " (abstract)");
+            (abstract == 0) ? "" : " (abstract)");
     }
     if (err != exp) {
         result = STATUS_FAILED;
@@ -112,8 +112,8 @@
         printf(" actual: %s (%d)\n", TranslateError(err), err);
         if (err == JVMTI_ERROR_NONE) {
             printf("  %s%s line number table (%d entries):%s\n",
-                   methName, (abstract==0) ? "" : " (abstract)",
-                   entryCount, (entryCount==0 ? " empty" : ""));
+                   methName, (abstract == 0) ? "" : " (abstract)",
+                   entryCount, (entryCount == 0 ? " empty" : ""));
             for (i = 0; i < entryCount; i++) {
                 printf("    start_location = 0x%x%08x,",
                        (jint)(table[i].start_location >> 32),
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/functions/nosuspendMonitorInfo/JvmtiTest/JvmtiTest.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/functions/nosuspendMonitorInfo/JvmtiTest/JvmtiTest.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -170,7 +170,7 @@
         iGlobalStatus = 2;
     }
 
-    if (expected_count !=0) {
+    if (expected_count != 0) {
 
         ret = jvmti->GetCurrentContendedMonitor(thr, owned_monitor);
         if (ret != JVMTI_ERROR_NONE) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -441,7 +441,7 @@
         // while (!threadsGroupLocks.runnableCanExit.get()) {
         //        Thread.yield();
         //    }
-        while (flag==JNI_FALSE)
+        while (flag == JNI_FALSE)
         {
             GET_BOOL_FIELD(flag, threadsGroupLocks, ThreadsGroupLocks, "runnableCanExit");
             CALL_STATIC_VOID_NOPARAM(Thread, "yield");
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -150,7 +150,7 @@
     char *cls_sig;
     jint clsByteCount;
 
-    display((hotswap != HOTSWAP_OFF)?0:1,
+    display((hotswap != HOTSWAP_OFF) ? 0 : 1,
         "#### JVMTIagent: ClassLoad occurred ####\n");
 
     getVerdict(jni_env, "ClassLoad");
@@ -236,7 +236,7 @@
     jclass decl_clazz;
 
     display((hotswap == HOTSWAP_EVERY_EXCEPTION ||
-            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS)?0:1,
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS) ? 0 : 1,
         "#### JVMTIagent: Exception occurred ####\n");
 
     getVerdict(jni_env, "Exception");
@@ -408,7 +408,7 @@
         jmethodID method, jlocation location) {
     jclass decl_clazz;
 
-    display((hotswap == HOTSWAP_EVERY_SINGLE_STEP)?0:1,
+    display((hotswap == HOTSWAP_EVERY_SINGLE_STEP) ? 0 : 1,
         "#### JVMTIagent: SingleStep occurred ####\n");
 
     getVerdict(jni_env, "SingleStep");
@@ -428,7 +428,7 @@
     jclass decl_clazz;
 
     display((hotswap == HOTSWAP_EVERY_METHOD_ENTRY ||
-            hotswap == HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS)?0:1,
+            hotswap == HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS) ? 0 : 1,
         "#### JVMTIagent: MethodEntry occurred ####\n");
 
     getVerdict(jni_env, "MethodEntry");
@@ -459,7 +459,7 @@
     jclass decl_clazz;
 
     display((hotswap == HOTSWAP_EVERY_EXCEPTION ||
-            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS)?0:1,
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS) ? 0 : 1,
         "#### JVMTIagent: ExceptionCatch occurred ####\n");
 
     getVerdict(jni_env, "ExceptionCatch");
@@ -1153,7 +1153,7 @@
         sprintf(error_msg, "JVMTIagent: getVerdict: %s event occured after VMDeath",
             evnt);
 
-        if (jni_env==NULL) { /* some event callbacks have no pointer to jni */
+        if (jni_env == NULL) { /* some event callbacks have no pointer to jni */
             printf("ERROR: %s\n", error_msg);
             exit(97);
         }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/Injector.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/Injector.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -432,7 +432,7 @@
                 put_u1(SAME_FRAME_EXTENDED);
                 put_u2(calculateOffsetDelta(i, (u2) frame_type));
 
-            } else if ((frame_type >= SAME_LOCALS_1_STACK_ITEM_BEGIN) && (frame_type<=SAME_LOCALS_1_STACK_ITEM_END)) {
+            } else if ((frame_type >= SAME_LOCALS_1_STACK_ITEM_BEGIN) && (frame_type <= SAME_LOCALS_1_STACK_ITEM_END)) {
                 // same_locals_1_stack_item_frame {
                 //         u1 frame_type = SAME_LOCALS_1_STACK_ITEM;/* 64-127 */
                 //         verification_type_info stack[1];
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/hotswap/HotSwap.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/hotswap/HotSwap.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -318,7 +318,7 @@
             NSK_DISPLAY1("SingleStepEventsCount: %d\n", SingleStepEventsCount);
             if (vm_mode == VM_MODE_MIXED) {
                 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(
-                        (((i % 2)==0) ? JVMTI_DISABLE : JVMTI_ENABLE),
+                        (((i % 2) == 0) ? JVMTI_DISABLE : JVMTI_ENABLE),
                         JVMTI_EVENT_SINGLE_STEP, NULL)))
                     nsk_jvmti_setFailStatus();
             }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -142,7 +142,7 @@
 
 /**
  * Return 1 if the thread has been started, or 0 if not,
- * or -1 if thread==NULL.
+ * or -1 if thread == NULL.
  */
 int THREAD_isStarted(void* t) {
     THREAD* thread = (THREAD*)t;
@@ -154,7 +154,7 @@
 /**
  * Return 1 if the thread has been started and already has finished,
  * or 0 if the thread hasn't finish (or even hasn't been started),
- * or -1 if thread==NULL.
+ * or -1 if thread == NULL.
  */
 int THREAD_hasFinished(void* t) {
     THREAD* thread = (THREAD*)t;
@@ -166,7 +166,7 @@
 /**
  * Return thread->status if thread has finished,
  * or return 0 if thread hasn't finished,
- * or retuen -1 if thread==NULL.
+ * or retuen -1 if thread == NULL.
  */
 int THREAD_status(void* t) {
     THREAD* thread = (THREAD*)t;
@@ -179,7 +179,7 @@
 
 /**
  * Cycle with 1 second sleeps until the thread has finished;
- * or return immediately, if thread==NULL.
+ * or return immediately, if thread == NULL.
  */
 void THREAD_waitFor(void* t) {
     THREAD* thread = (THREAD*)t;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -86,13 +86,13 @@
     }
     memcpy(element->checkstr[allocs],digest,DIGESTLENGTH);
     allocs++;
-    if (allocs%printperiod==0) {
+    if (allocs % printperiod == 0) {
         printf("Check string for thread %s is ", element->str[allocs-1]);
         for (j=0;j<DIGESTLENGTH;j++)
             printf("%02x", digest[j]);
         printf("\n");
     }
-    if (allocs==nstr) {
+    if (allocs == nstr) {
         printf("JNI UTF8 strings memory=%zd\n", strsize);
         tmpstr=env->NewStringUTF(element->str[allocs-1]); CE
         for (j=0; j<nstr; j++) {
@@ -103,7 +103,7 @@
             for (k=0; k < strlen(element->str[j]); k++) {
                 digest[k % DIGESTLENGTH] += element->str[j][k];
             }
-            if (memcmp(digest,element->checkstr[j],DIGESTLENGTH)==0) {
+            if (memcmp(digest,element->checkstr[j],DIGESTLENGTH) == 0) {
                 env->ReleaseStringUTFChars(jstr,element->str[j]); CE
                 element->str[j] = NULL;
                 element->checkstr[j] = NULL;
@@ -185,14 +185,14 @@
         digest[j % DIGESTLENGTH]+=elem[j];
     }
     memcpy(javachars->checkstr[index++],digest,DIGESTLENGTH);
-    if (index%printperiod==0) {
+    if (index % printperiod == 0) {
         printf("Check string sum for thread %.*s is ", elem_len, elem);
         for (j=0;j<DIGESTLENGTH;j++)
             printf("%02x", digest[j]);
         printf("\n");
     }
     free(elem);
-    if (index==nstr) {
+    if (index == nstr) {
         printf("JNI Unicode strings memory=%ld\n",len);
         tmpstr=env->NewString(javachars->str[index-1],elem_len); CE
         for (j=0; j<nstr; j++) {
@@ -208,7 +208,7 @@
                 digest[i % DIGESTLENGTH]+=elem[i];
             }
             free(elem);
-            if (memcmp(digest,javachars->checkstr[j],javachars->size[j])==0) {
+            if (memcmp(digest,javachars->checkstr[j],javachars->size[j]) == 0) {
                 env->ReleaseStringChars(jstr,javachars->str[j]); CE
                 javachars->str[j] = NULL;
                 javachars->checkstr[j] = NULL;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress002.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress002.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -69,13 +69,13 @@
   clazz=env->FindClass(classname); CE
   obj=env->NewObjectArray((jsize)3,clazz,
                  env->AllocObject(clazz)); CE
-  if (obj==NULL) {
+  if (obj == NULL) {
     fprintf(stderr,"Can not construct the object Array for  %s\n", classname);
     return(NULL);
   }
 
   methodID=env->GetMethodID(clazz,name,sig); CE
-  if (methodID==NULL) {
+  if (methodID == NULL) {
     fprintf(stderr,"Can not get the ID of <init> for %s\n", classname);
     return(NULL);
   }
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -80,7 +80,7 @@
     doubleBuf=(jdouble *)malloc(SIZE*sizeof(jdouble));
 
     for (i=0;i<SIZE;i++) {
-    if (i%2==0) boolBuf[i]=JNI_TRUE;
+    if (i%2 == 0) boolBuf[i]=JNI_TRUE;
     else boolBuf[i]=JNI_FALSE;
     /*
       byteBuf[i]=(jbyte)random();
@@ -140,7 +140,7 @@
     jdouble *doubleOrig, *doubleClone;
     int i;
 
-    if ((orig==NULL) || (clone==NULL)) {
+    if ((orig == NULL) || (clone == NULL)) {
     fprintf(stderr,"JNI received a NULL array from Java\n");
     return JNI_FALSE;
     }
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -50,7 +50,7 @@
 /*     const char *threadName=env->GetStringUTFChars(jstr, 0); */
 
     env->MonitorEnter(jobj); CE
-    if (upper==0) tmp=(jchar *)malloc(DIGESTLENGTH*sizeof(char));
+    if (upper == 0) tmp = (jchar *) malloc(DIGESTLENGTH*sizeof(char));
     if (env->ExceptionOccurred()) {
         env->ExceptionDescribe();
         env->ExceptionClear();
@@ -140,7 +140,7 @@
 
     printf("Comparing: ");
     for (i=0;i<len;i++)
-    if (ch[i]!=tmp[i]) {
+    if (ch[i] != tmp[i]) {
         printf("Error in %d\n",i);
         printf("ch[%d]=%02x tmp[%d]=%02x\n",i,ch[i],i,tmp[i]);
         ret=JNI_FALSE;
@@ -153,7 +153,7 @@
     ++upper;
     if (!(upper % 500))
     fprintf(stderr,"There are %d elements now.\n", upper);
-    if (upper==limit) {
+    if (upper == limit) {
     jclass clazz;
     jmethodID methodID;
     char *name = (char*) "halt";
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress005.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress005.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -56,7 +56,7 @@
     CHECK_EXCEPTION
     if (!env->Throw(tobj)) {
     if (env->ExceptionOccurred())
-        if (Exceptcalls%1000==0)
+        if (Exceptcalls % 1000 == 0)
         fprintf(stderr, "NATIVE: Throw has been catched in native\n");
     env->ExceptionClear();
     ++Exceptcalls;
@@ -65,7 +65,7 @@
     env->MonitorExit(jobj);
     CHECK_EXCEPTION
 
-    switch (Exceptcalls%23) {
+    switch (Exceptcalls % 23) {
       case 0: name="java/lang/ArithmeticException"; break;
       case 1: name="java/lang/ArrayIndexOutOfBoundsException"; break;
       case 2: name="java/lang/ArrayStoreException"; break;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp	Wed Dec 12 08:38:45 2018 -0500
@@ -48,8 +48,9 @@
 
     if (upper >= LIMIT) return JNI_TRUE;
 
-    if (upper==0)
-    globRefsArray=(jobject*)(malloc(LIMIT*sizeof(jobject)));
+    if (upper == 0) {
+        globRefsArray=(jobject*)(malloc(LIMIT*sizeof(jobject)));
+    }
 
     globRefsArray[upper]=env->NewGlobalRef(tobj); CE
     if (env->IsSameObject(tobj, globRefsArray[upper])) {
--- a/test/jdk/ProblemList.txt	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/ProblemList.txt	Wed Dec 12 08:38:45 2018 -0500
@@ -515,7 +515,6 @@
 # jdk_lang
 
 java/lang/StringCoding/CheckEncodings.sh                        7008363 generic-all
-java/lang/ProcessBuilder/PipelineTest.java                      8211844 aix-ppc64
 java/lang/ProcessHandle/InfoTest.java                           8211847 aix-ppc64
 
 ############################################################################
@@ -777,8 +776,6 @@
 javax/swing/plaf/basic/BasicComboBoxEditor/Test8015336.java 8198394 generic-all
 javax/swing/plaf/metal/MetalLookAndFeel/Test8039750.java 8198395 generic-all
 javax/swing/text/DevanagariEditor.java 8198397 generic-all
-javax/swing/JColorChooser/Test6199676.java 8198398 generic-all
-javax/swing/JTable/6735286/bug6735286.java 8198398 generic-all
 javax/swing/SpringLayout/4726194/bug4726194.java 8198399 generic-all
 javax/swing/SwingUtilities/6797139/bug6797139.java 8198400 generic-all
 javax/swing/text/html/parser/Parser/6836089/bug6836089.java 8198401 generic-all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/OnJcmdTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8214892
+ * @summary Test that the onjcmd option of the jdwp agent works.
+ *
+ * @author Ralf Schmelter
+ *
+ * @library /test/lib
+ * @run compile --add-exports java.base/jdk.internal.vm=ALL-UNNAMED -g OnJcmdTest.java
+ * @run main/othervm --add-exports java.base/jdk.internal.vm=ALL-UNNAMED -agentlib:jdwp=transport=dt_socket,address=localhost:0,onjcmd=y,server=y OnJcmdTest
+ */
+
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import jdk.internal.vm.VMSupport;
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class OnJcmdTest {
+
+    private static String getListenerAddress() throws Exception {
+        Properties props = VMSupport.getAgentProperties();
+        return props.getProperty("sun.jdwp.listenerAddress", null);
+    }
+
+    public static void main(String[] args) throws Throwable {
+        // First check if we get the expected errors.
+        OutputAnalyzer output = ProcessTools.executeTestJvm(
+                "-agentlib:jdwp=transport=dt_socket,address=any,onjcmd=y");
+        output.shouldContain("Can only use onjcmd with server=y");
+        output.shouldHaveExitValue(1);
+
+        output = ProcessTools.executeTestJvm(
+                "-agentlib:jdwp=transport=dt_socket,address=any,onjcmd=y,onthrow=a,launch=a");
+        output.shouldContain("Cannot combine onjcmd and launch suboptions");
+        output.shouldHaveExitValue(1);
+
+        // Make sure debugging is not yet started.
+        String prop = getListenerAddress();
+
+        if (prop != null) {
+            throw new RuntimeException("Listener address was set to " + prop);
+        }
+
+        // Now start it (test that it is OK to do this more than once).
+        for (int i = 0; i < 3; ++i) {
+            String jcmd = JDKToolFinder.getJDKTool("jcmd");
+            output = ProcessTools.executeProcess(jcmd,
+                    Long.toString(ProcessTools.getProcessId()),
+                    "VM.start_java_debugging");
+
+            String exp_str = i == 0 ? "Debugging has been started." :
+                                      "Debugging is already active.";
+            output.shouldContain(exp_str);
+            output.shouldContain("Transport : dt_socket");
+            output.shouldHaveExitValue(0);
+        }
+
+        // Now the property should be set, as the jdwp agent waits for a
+        // connection.
+        long t1 = System.currentTimeMillis();
+        long t2 = t1;
+
+        while(t2 - t1 < 4000) {
+            prop = getListenerAddress();
+
+            if (prop != null) {
+                if (prop.equals("localhost:0")) {
+                    throw new RuntimeException("Port was not expanded");
+                } else if (!prop.startsWith("dt_socket:")) {
+                    throw new RuntimeException("Invalid transport prop " + prop);
+                }
+
+                return;
+            }
+
+            Thread.sleep(50);
+            t2 = System.currentTimeMillis();
+        }
+
+        throw new RuntimeException("Debugging backend didn't start");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/font/FontPathEnvTest/FontPathEnvTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug      8212703
+ * @summary  Test JAVA2D_FONTPATH env. var does not set a system property
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class FontPathEnvTest {
+
+    public static void main(String args[]) {
+        String env = System.getenv("JAVA2D_FONTPATH");
+        if (env == null) {
+           createChild();
+        } else {
+            String prop = System.getProperty("sun.java2d.fontpath");
+            if (prop != null && env.equals(prop)) {
+                throw new RuntimeException("sun.java2d.fontpath property set");
+            }
+        }
+    }
+
+    static void createChild() {
+        String cpDir = System.getProperty("java.class.path");
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("JAVA2D_FONTPATH", "anyValue");
+        String jHome = System.getProperty("java.home");
+        String jCmd = jHome + File.separator + "bin" + File.separator + "java";
+        int exitValue = doExec(env, jCmd, "-cp", cpDir, "FontPathEnvTest");
+        if (exitValue != 0) {
+            throw new RuntimeException("Test Failed");
+        }
+    }
+
+    static int doExec(Map<String, String> envToSet, String... cmds) {
+        Process p = null;
+        ProcessBuilder pb = new ProcessBuilder(cmds);
+        Map<String, String> env = pb.environment();
+        for (String cmd : cmds) {
+            System.out.print(cmd + " ");
+        }
+        System.out.println();
+        if (envToSet != null) {
+            env.putAll(envToSet);
+        }
+        BufferedReader rdr = null;
+        try {
+            pb.redirectErrorStream(true);
+            p = pb.start();
+            rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            String in = rdr.readLine();
+            while (in != null) {
+                in = rdr.readLine();
+                System.out.println(in);
+            }
+            p.waitFor();
+            p.destroy();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return p.exitValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/font/TextLayout/FontGlyphCompare.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ */
+
+/* @test
+ * @bug 8214002
+ * @requires (os.family == "windows")
+ * @summary verify MS Mincho's Plain & Italic style
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class FontGlyphCompare {
+
+    static BufferedImage getFontImage(Font font, String text) {
+        int x = 1;
+        int y = 15;
+        int w = 10;
+        int h = 18;
+        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = (Graphics2D)bi.getGraphics();
+        g.setColor(Color.black);
+        g.fillRect(0, 0, w, h);
+        g.setColor(Color.white);
+        g.setFont(font);
+        g.drawString(text, x, y);
+        return bi;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String osName = System.getProperty("os.name");
+        System.out.println("OS is " + osName);
+        osName = osName.toLowerCase();
+        if (!osName.startsWith("windows")) {
+            return;
+        }
+        Font msMincho = new Font("MS Mincho", Font.PLAIN, 16);
+        String family = msMincho.getFamily(java.util.Locale.ENGLISH);
+        if (!family.equalsIgnoreCase("MS Mincho")) {
+            System.out.println("Japanese fonts not installed");
+            return;
+        }
+        String s = "|";
+        BufferedImage bi1 = getFontImage(new Font("MS Mincho", Font.PLAIN, 16), s);
+        int h1 = bi1.getHeight();
+        int w1 = bi1.getWidth();
+        BufferedImage bi2 = getFontImage(new Font("MS Mincho", Font.ITALIC, 16), s);
+        int h2 = bi2.getHeight();
+        int w2 = bi2.getWidth();
+        if ((h1 == h2) && (w1 == w2)) {
+            int cnt = 0;
+            for(int yy = 0; yy < h1; yy++) {
+                for(int xx = 0; xx < w1; xx++) {
+                    if (bi1.getRGB(xx, yy) != bi2.getRGB(xx, yy)) {
+                        cnt++;
+                    }
+                }
+            }
+            if (cnt == 0) {
+                throw new Exception("Test failed");
+            }
+        }
+    }
+}
--- a/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java	Wed Dec 12 08:38:45 2018 -0500
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8080535 8191410
+ * @bug 8080535 8191410 8215194
  * @summary Expected size of Character.UnicodeBlock.map is not optimal
  * @library /test/lib
  * @modules java.base/java.lang:open
@@ -32,6 +32,7 @@
  * @run main OptimalMapSize
  */
 
+import java.lang.reflect.Field;
 import jdk.test.lib.util.OptimalCapacity;
 
 // What will be the number of the Unicode blocks in the future.
@@ -44,14 +45,24 @@
 // After implementing support of Unicode 9 and 10 in Java, there will
 // be 638 entries in Character.UnicodeBlock.map.
 //
+// As of Unicode 11, 667 entries are expected.
+//
 // Initialization of the map and this test will have to be adjusted
 // accordingly then.
+//
+// Note that HashMap's implementation aligns the initial capacity to
+// a power of two size, so it will end up 1024 (and thus succeed) in
+// cases, such as 638 and 667.
 
 public class OptimalMapSize {
     public static void main(String[] args) throws Throwable {
         // The initial size of Character.UnicodeBlock.map.
         // See src/java.base/share/classes/java/lang/Character.java
-        int initialCapacity = (int)(638 / 0.75f + 1.0f);
+        Field f = Character.UnicodeBlock.class.getDeclaredField("NUM_ENTITIES");
+        f.setAccessible(true);
+        int num_entities = f.getInt(null);
+        assert num_entities == 667;
+        int initialCapacity = (int)(num_entities / 0.75f + 1.0f);
 
         OptimalCapacity.ofHashMap(Character.UnicodeBlock.class,
                 "map", initialCapacity);
--- a/test/jdk/javax/imageio/stream/StreamCloserLeak/run_test.sh	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/javax/imageio/stream/StreamCloserLeak/run_test.sh	Wed Dec 12 08:38:45 2018 -0500
@@ -1,6 +1,6 @@
 #!/bin/ksh -p
 #
-# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -25,6 +25,7 @@
 #
 #   @test
 #   @bug        6788096
+#   @key        intermittent
 #   @summary    Test simulates the case of multiple applets executed in
 #               the same VM and verifies that ImageIO shutdown hook
 #               StreamCloser does not cause a leak of classloaders.
--- a/test/jdk/javax/swing/JColorChooser/Test6199676.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/javax/swing/JColorChooser/Test6199676.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,33 +23,24 @@
 
 /*
  * @test
+ * @key headful
  * @bug 6199676
  * @summary Tests preview panel after L&F changing
- * @author Sergey Malenkov
  */
 
 import java.awt.Component;
 import java.awt.Container;
+
 import javax.swing.JColorChooser;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
-import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.UnsupportedLookAndFeelException;
 
 public class Test6199676 implements Runnable {
-    public static void main(String[] args) {
-        SwingUtilities.invokeLater(new Test6199676());
-    }
-
-    private static void exit(String error) {
-        if (error != null) {
-            System.err.println(error);
-            System.exit(1);
-        }
-        else {
-            System.exit(0);
-        }
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Test6199676());
     }
 
     private static Component getPreview(Container container) {
@@ -74,44 +65,42 @@
         return (component != null) && component.isShowing();
     }
 
-    private int index;
-    private boolean updated;
-    private JColorChooser chooser;
-
     public synchronized void run() {
-        if (this.chooser == null) {
-            this.chooser = new JColorChooser();
-
-            JFrame frame = new JFrame(getClass().getName());
-            frame.add(this.chooser);
+        JColorChooser chooser = new JColorChooser();
+        JFrame frame = new JFrame(getClass().getName());
+        try {
+            frame.add(chooser);
             frame.setVisible(true);
-        }
-        else if (this.updated) {
-            if (isShowing(this.chooser.getPreviewPanel())) {
-                exit("custom preview panel is showing");
-            }
-            exit(null);
-        }
-        else {
-            Component component = this.chooser.getPreviewPanel();
+            // Check default preview panel
+            setLookAndFeel(UIManager.getInstalledLookAndFeels()[0]);
+            SwingUtilities.updateComponentTreeUI(chooser);
+            Component component = chooser.getPreviewPanel();
             if (component == null) {
-                component = getPreview(this.chooser);
+                component = getPreview(chooser);
             }
             if (!isShowing(component)) {
-                exit("default preview panel is not showing");
+                throw new RuntimeException(
+                        "default preview panel is not showing");
             }
-            this.updated = true;
-            this.chooser.setPreviewPanel(new JPanel());
+            // Check custom preview panel
+            chooser.setPreviewPanel(new JPanel());
+            setLookAndFeel(UIManager.getInstalledLookAndFeels()[1]);
+            SwingUtilities.updateComponentTreeUI(chooser);
+            if (isShowing(chooser.getPreviewPanel())) {
+                throw new RuntimeException("custom preview panel is showing");
+            }
+        } finally {
+            frame.dispose();
         }
-        LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();
-        LookAndFeelInfo info = infos[++this.index % infos.length];
+    }
+
+    private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {
         try {
-            UIManager.setLookAndFeel(info.getClassName());
+            UIManager.setLookAndFeel(laf.getClassName());
+        } catch (final UnsupportedLookAndFeelException ignored){
+        } catch (ClassNotFoundException | InstantiationException |
+                IllegalAccessException e) {
+            throw new RuntimeException(e);
         }
-        catch (Exception exception) {
-            exit("could not change L&F");
-        }
-        SwingUtilities.updateComponentTreeUI(this.chooser);
-        SwingUtilities.invokeLater(this);
     }
 }
--- a/test/jdk/javax/swing/JFrame/NSTexturedJFrame/NSTexturedJFrame.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/javax/swing/JFrame/NSTexturedJFrame/NSTexturedJFrame.java	Wed Dec 12 08:38:45 2018 -0500
@@ -37,7 +37,7 @@
  * @requires (os.family == "mac")
  * @summary We should support NSTexturedBackgroundWindowMask style on OSX.
  * @library /test/lib
- *          /test/jdk/lib/testlibrary/
+ *          /lib/client
  * @build ExtendedRobot jdk.test.lib.Platform
  * @run main NSTexturedJFrame
  */
--- a/test/jdk/javax/swing/JTable/6735286/bug6735286.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/javax/swing/JTable/6735286/bug6735286.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,14 +24,14 @@
 /* @test
    @bug 6735286
    @summary javax.swing.DefaultTableCellRender.getTableCellRendererComponent() doesn't allow passing null Tables
-   @author Pavel Porvatov
 */
 
-import javax.swing.*;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
 
 public class bug6735286 {
-    public static void main(String[] args) {
-        SwingUtilities.invokeLater(new Runnable() {
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
             public void run() {
                 new JTable().getDefaultRenderer(Object.class).getTableCellRendererComponent(null, "a value",
                         true, true, 0, 0);
--- a/test/jdk/jdk/internal/jline/KeyConversionTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/jdk/internal/jline/KeyConversionTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -25,12 +25,16 @@
  * @test
  * @bug 8080679
  * @summary Verify the conversion from key events to escape sequences works properly.
- * @modules jdk.internal.le/jdk.internal.jline
- * @requires os.family == "windows"
+ * @modules jdk.internal.le/jdk.internal.org.jline.terminal
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
  */
 
-import jdk.internal.jline.WindowsTerminal;
-import jdk.internal.jline.WindowsTerminal.KEY_EVENT_RECORD;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
 
 public class KeyConversionTest {
     public static void main(String... args) throws Exception {
@@ -38,23 +42,72 @@
     }
 
     void run() throws Exception {
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 37, 1), "\033[D"); //LEFT
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 37, 1), "\033[1;5D"); //Ctrl-LEFT
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 37, 1), "\033[1;3D"); //Alt-LEFT
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 46, 1), "\033[3~"); //delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 46, 1), "\033[3;5~"); //Ctrl-delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 46, 1), "\033[3;3~"); //Alt-delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 272, 46, 1), "\033[3;2~"); //Shift-delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 280, 46, 1), "\033[3;6~"); //Ctrl-Shift-delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 274, 46, 1), "\033[3;4~"); //Alt-Shift-delete
-        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 282, 46, 1), "\033[3;8~"); //Ctrl-Alt-Shift-delete
+        checkKeyConversion(new KeyEvent(true, (short) 37, '\0', 256), "\033OD"); //LEFT
+        checkKeyConversion(new KeyEvent(true, (short) 37, '\0', 264), "\033[1;5D"); //Ctrl-LEFT
+        checkKeyConversion(new KeyEvent(true, (short) 37, '\0', 258), "\033[1;3D"); //Alt-LEFT
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 256), "\033OP"); //F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 264), "\033[1;5P"); //Ctrl-F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 258), "\033[1;3P"); //Alt-F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 272), "\033[1;2P"); //Shift-F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 280), "\033[1;6P"); //Ctrl-Shift-F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 274), "\033[1;4P"); //Alt-Shift-F1
+        checkKeyConversion(new KeyEvent(true, (short) 112, '\0', 282), "\033[1;8P"); //Ctrl-Alt-Shift-F1
+        checkKeyConversion(new KeyEvent(true, (short) 67, '\003', 8), "\003"); //Ctrl-C
     }
 
-    void checkKeyConversion(KEY_EVENT_RECORD event, String expected) {
-        String actual = WindowsTerminal.convertKeys(event);
+    void checkKeyConversion(KeyEvent event, String expected) throws IOException {
+        StringBuilder result = new StringBuilder();
+        new AbstractWindowsTerminal(new StringWriter(), "", "windows", Charset.forName("UTF-8"),
+                                    0, true, null, in -> in) {
+            @Override
+            protected int getConsoleOutputCP() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+            @Override
+            protected int getConsoleMode() {
+                return 0;
+            }
+            @Override
+            protected void setConsoleMode(int mode) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+            @Override
+            protected boolean processConsoleInput() throws IOException {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+            @Override
+            public Size getSize() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+            @Override
+            public void processInputChar(char c) throws IOException {
+                result.append(c);
+            }
+            @Override
+            public void processKeyEvent(boolean isKeyDown, short virtualKeyCode,
+                                        char ch, int controlKeyState) throws IOException {
+                super.processKeyEvent(isKeyDown, virtualKeyCode, ch, controlKeyState);
+            }
+        }.processKeyEvent(event.isKeyDown, event.virtualKeyCode, event.ch, event.controlKeyState);
+        String actual = result.toString();
 
         if (!expected.equals(actual)) {
             throw new AssertionError("Expected: " + expected + "; actual: " + actual);
         }
     }
+
+    public static class KeyEvent {
+        public final boolean isKeyDown;
+        public final short virtualKeyCode;
+        public final char ch;
+        public final int controlKeyState;
+
+        public KeyEvent(boolean isKeyDown, short virtualKeyCode, char ch, int controlKeyState) {
+            this.isKeyDown = isKeyDown;
+            this.virtualKeyCode = virtualKeyCode;
+            this.ch = ch;
+            this.controlKeyState = controlKeyState;
+        }
+
+    }
 }
--- a/test/jdk/jdk/internal/jline/console/StripAnsiTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8080679 8131913
- * @modules jdk.internal.le/jdk.internal.jline.internal
- * @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly.
- */
-
-import jdk.internal.jline.internal.Ansi;
-
-public class StripAnsiTest {
-    public static void main(String... args) throws Exception {
-        new StripAnsiTest().run();
-    }
-
-    void run() throws Exception {
-        String withAnsi = "0\033[s1\033[2J2\033[37;4m3";
-        String expected = "0123";
-
-        String actual = Ansi.stripAnsi(withAnsi);
-
-        if (!expected.equals(actual)) {
-            throw new IllegalStateException("Did not correctly strip escape sequences: " + actual);
-        }
-    }
-}
--- a/test/jdk/jdk/internal/jline/extra/AnsiInterpretingOutputStreamTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +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.
- */
-
-/*
- * @test
- * @bug 8203827
- * @summary Verify that escape sequences intepretation (used by Windows Terminal) works properly.
- * @modules jdk.internal.le/jdk.internal.jline.extra
- * @build AnsiInterpretingOutputStreamTest
- * @run testng AnsiInterpretingOutputStreamTest
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.BufferState;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.Performer;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
-
-@Test
-public class AnsiInterpretingOutputStreamTest {
-
-    public void testAnsiInterpretation() throws IOException {
-        BufferState[] state = new BufferState[] {new BufferState(5, 5, 10, 10)};
-        ByteArrayOutputStream result = new ByteArrayOutputStream();
-        OutputStream test = new AnsiInterpretingOutputStream("UTF-8", result, new Performer() {
-            @Override
-            public BufferState getBufferState() {
-                return state[0];
-            }
-            @Override
-            public void setCursorPosition(int cursorX, int cursorY) {
-                state[0] = new BufferState(cursorX, cursorY, state[0].sizeX, state[0].sizeY);
-                try {
-                    result.write(("<setCursorPosition(" + cursorX + ", " + cursorY + ")>").getBytes("UTF-8"));
-                } catch (IOException ex) {
-                    throw new AssertionError(ex);
-                }
-            }
-        });
-
-        Writer testWriter = new OutputStreamWriter(test, "UTF-8");
-
-        //cursor move:
-        testWriter.write("\033[A\033[3A\033[15A\n");
-        testWriter.write("\033[B\033[3B\033[15B\n");
-        testWriter.write("\033[D\033[3D\033[15D\n");
-        testWriter.write("\033[C\033[3C\033[15C\n");
-
-        //clearing line:
-        testWriter.write("\033[5D\n");
-        testWriter.write("\033[K\n");
-        testWriter.write("\033[1K\n");
-        testWriter.write("\033[2K\n");
-
-        testWriter.flush();
-
-        String expected = "<setCursorPosition(5, 4)><setCursorPosition(5, 1)><setCursorPosition(5, 0)>\n" +
-                          "<setCursorPosition(5, 1)><setCursorPosition(5, 4)><setCursorPosition(5, 9)>\n" +
-                          "<setCursorPosition(4, 9)><setCursorPosition(1, 9)><setCursorPosition(0, 9)>\n" +
-                          "<setCursorPosition(1, 9)><setCursorPosition(4, 9)><setCursorPosition(9, 9)>\n" +
-                          "<setCursorPosition(4, 9)>\n" +
-                          "     <setCursorPosition(4, 9)>\n" +
-                          "<setCursorPosition(0, 9)>    \n" +
-                          "         <setCursorPosition(0, 9)>\n";
-        String actual = new String(result.toByteArray(), "UTF-8");
-
-        assertEquals(actual, expected);
-    }
-}
--- a/test/jdk/jdk/internal/jline/extra/HistoryTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8178821 8198670
- * @summary Test Completion
- * @modules jdk.internal.le/jdk.internal.jline
- *          jdk.internal.le/jdk.internal.jline.console
- *          jdk.internal.le/jdk.internal.jline.console.history
- *          jdk.internal.le/jdk.internal.jline.extra
- * @build HistoryTest
- * @run testng HistoryTest
- */
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import jdk.internal.jline.UnsupportedTerminal;
-import jdk.internal.jline.console.ConsoleReader;
-import jdk.internal.jline.console.history.MemoryHistory;
-import jdk.internal.jline.extra.EditingHistory;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
-
-@Test
-public class HistoryTest {
-
-    public void testHistory() throws IOException {
-        ConsoleReader in = new ConsoleReader(new ByteArrayInputStream(new byte[0]), new ByteArrayOutputStream(), new UnsupportedTerminal());
-        AtomicBoolean complete = new AtomicBoolean();
-        EditingHistory history = new EditingHistory(in, Collections.emptyList()) {
-            @Override
-            protected boolean isComplete(CharSequence input) {
-                return complete.get();
-            }
-        };
-        complete.set(false); history.add("void test() {");
-        complete.set(false); history.add("    System.err.println(1);");
-        complete.set(true);  history.add("}");
-        complete.set(true);  history.add("/exit");
-
-        previousAndAssert(history, "/exit");
-
-        history.previous(); history.previous(); history.previous();
-
-        complete.set(false); history.add("void test() { /*changed*/");
-
-        complete.set(true);
-        previousAndAssert(history, "}");
-        previousAndAssert(history, "    System.err.println(1);");
-        previousAndAssert(history, "void test() {");
-
-        assertFalse(history.previous());
-
-        nextAndAssert(history, "    System.err.println(1);");
-        nextAndAssert(history, "}");
-        nextAndAssert(history, "");
-
-        complete.set(false); history.add("    System.err.println(2);");
-        complete.set(true);  history.add("} /*changed*/");
-
-        assertEquals(history.size(), 7);
-
-        Collection<? extends String> persistentHistory = history.save();
-
-        history = new EditingHistory(in, persistentHistory) {
-            @Override
-            protected boolean isComplete(CharSequence input) {
-                return complete.get();
-            }
-        };
-
-        previousSnippetAndAssert(history, "void test() { /*changed*/");
-        previousSnippetAndAssert(history, "/exit");
-        previousSnippetAndAssert(history, "void test() {");
-
-        assertFalse(history.previousSnippet());
-
-        nextSnippetAndAssert(history, "/exit");
-        nextSnippetAndAssert(history, "void test() { /*changed*/");
-        nextSnippetAndAssert(history, "");
-
-        assertFalse(history.nextSnippet());
-
-        complete.set(false); history.add("{");
-        complete.set(true);  history.add("}");
-
-        persistentHistory = history.save();
-
-        history = new EditingHistory(in, persistentHistory) {
-            @Override
-            protected boolean isComplete(CharSequence input) {
-                return complete.get();
-            }
-        };
-
-        previousSnippetAndAssert(history, "{");
-        previousSnippetAndAssert(history, "void test() { /*changed*/");
-        previousSnippetAndAssert(history, "/exit");
-        previousSnippetAndAssert(history, "void test() {");
-
-        while (history.next());
-
-        complete.set(true);  history.add("/*current1*/");
-        complete.set(true);  history.add("/*current2*/");
-        complete.set(true);  history.add("/*current3*/");
-
-        assertEquals(history.entries(true), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/"));
-        assertEquals(history.entries(false), Arrays.asList(
-                "void test() {",
-                "    System.err.println(1);",
-                "}",
-                "/exit",
-                "void test() { /*changed*/",
-                "    System.err.println(2);",
-                "} /*changed*/",
-                "{",
-                "}",
-                "/*current1*/", "/*current2*/", "/*current3*/"), history.entries(false).toString());
-
-        history.remove(0);
-
-        assertEquals(history.entries(true), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/"));
-
-        while (history.size() > 2)
-            history.remove(0);
-
-        assertEquals(history.entries(true), Arrays.asList("/*current2*/", "/*current3*/"));
-
-        for (int i = 0; i < MemoryHistory.DEFAULT_MAX_SIZE * 2; i++) {
-            complete.set(true);  history.add("/exit");
-        }
-
-        complete.set(false); history.add("void test() { /*after full*/");
-        complete.set(false); history.add("    System.err.println(1);");
-        complete.set(true);  history.add("}");
-
-        previousSnippetAndAssert(history, "void test() { /*after full*/");
-        nextSnippetAndAssert(history, "");
-
-        assertFalse(history.nextSnippet());
-
-        while (history.previousSnippet())
-            ;
-
-        while (history.nextSnippet())
-            ;
-    }
-
-    private void previousAndAssert(EditingHistory history, String expected) {
-        assertTrue(history.previous());
-        assertEquals(history.current().toString(), expected);
-    }
-
-    private void nextAndAssert(EditingHistory history, String expected) {
-        assertTrue(history.next());
-        assertEquals(history.current().toString(), expected);
-    }
-
-    private void previousSnippetAndAssert(EditingHistory history, String expected) {
-        assertTrue(history.previousSnippet());
-        assertEquals(history.current().toString(), expected);
-    }
-
-    private void nextSnippetAndAssert(EditingHistory history, String expected) {
-        assertTrue(history.nextSnippet());
-        assertEquals(history.current().toString(), expected);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/Distrust.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.*;
+import java.security.cert.*;
+import java.time.*;
+import java.util.*;
+import javax.net.ssl.*;
+import sun.security.validator.Validator;
+import sun.security.validator.ValidatorException;
+
+import jdk.test.lib.security.SecurityUtils;
+
+/**
+ * @test
+ * @bug 8207258
+ * @summary Check that TLS Server certificates chaining back to distrusted
+ *          Symantec roots are invalid
+ * @library /test/lib
+ * @modules java.base/sun.security.validator
+ * @run main/othervm Distrust true
+ * @run main/othervm Distrust false
+ */
+
+public class Distrust {
+
+    private static final String TEST_SRC = System.getProperty("test.src", ".");
+    private static CertificateFactory cf;
+
+    // Each of the roots have a test certificate chain stored in a file
+    // named "<root>-chain.pem".
+    private static String[] rootsToTest = new String[] {
+        "geotrustglobalca", "geotrustprimarycag2", "geotrustprimarycag3",
+        "geotrustuniversalca", "thawteprimaryrootca", "thawteprimaryrootcag2",
+        "thawteprimaryrootcag3", "verisignclass3g3ca", "verisignclass3g4ca",
+        "verisignclass3g5ca", "verisignuniversalrootca" };
+
+    // A date that is after the restrictions take affect
+    private static final Date APRIL_17_2019 =
+        Date.from(LocalDate.of(2019, 4, 17)
+                           .atStartOfDay(ZoneOffset.UTC)
+                           .toInstant());
+
+    public static void main(String[] args) throws Exception {
+
+        cf = CertificateFactory.getInstance("X.509");
+        boolean distrust = args[0].equals("true");
+        if (!distrust) {
+            // disable policy
+            Security.setProperty("jdk.security.caDistrustPolicies", "");
+        }
+
+        X509TrustManager pkixTM = getTMF("PKIX", null);
+        X509TrustManager sunX509TM = getTMF("SunX509", null);
+        for (String test : rootsToTest) {
+            System.err.println("Testing " + test);
+            X509Certificate[] chain = loadCertificateChain(test);
+
+            testTM(sunX509TM, chain, !distrust);
+            testTM(pkixTM, chain, !distrust);
+        }
+
+        // test chain if params are passed to TrustManager
+        System.err.println("Testing verisignuniversalrootca with params");
+        testTM(getTMF("PKIX", getParams()),
+               loadCertificateChain("verisignuniversalrootca"), !distrust);
+
+        // test code-signing chain (should be valid as restrictions don't apply)
+        System.err.println("Testing verisignclass3g5ca code-signing chain");
+        Validator v = Validator.getInstance(Validator.TYPE_PKIX,
+                                            Validator.VAR_CODE_SIGNING,
+                                            getParams());
+        // set validation date so this will still pass when cert expires
+        v.setValidationDate(new Date(1544197375493l));
+        v.validate(loadCertificateChain("verisignclass3g5ca-codesigning"));
+    }
+
+    private static X509TrustManager getTMF(String type,
+            PKIXBuilderParameters params) throws Exception {
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(type);
+        if (params == null) {
+            tmf.init((KeyStore)null);
+        } else {
+            tmf.init(new CertPathTrustManagerParameters(params));
+        }
+        TrustManager[] tms = tmf.getTrustManagers();
+        for (TrustManager tm : tms) {
+            X509TrustManager xtm = (X509TrustManager)tm;
+            return xtm;
+        }
+        throw new Exception("No TrustManager for " + type);
+    }
+
+    private static PKIXBuilderParameters getParams() throws Exception {
+        PKIXBuilderParameters pbp =
+            new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(),
+                                      new X509CertSelector());
+        pbp.setRevocationEnabled(false);
+        return pbp;
+    }
+
+    private static void testTM(X509TrustManager xtm, X509Certificate[] chain,
+                               boolean valid) throws Exception {
+        // Check if TLS Server certificate (the first element of the chain)
+        // is issued after April 16, 2019 (should be rejected unless distrust
+        // property is false). To do this, we need to fake the notBefore date
+        // since none of the test certs are issued after then.
+        chain[0] = new DistrustedTLSServerCert(chain[0], APRIL_17_2019);
+
+        try {
+            xtm.checkServerTrusted(chain, "ECDHE_RSA");
+            if (!valid) {
+                throw new Exception("chain should be invalid");
+            }
+        } catch (CertificateException ce) {
+            if (valid) {
+                throw new Exception("Unexpected exception, chain " +
+                                    "should be valid", ce);
+            }
+            if (ce instanceof ValidatorException) {
+                ValidatorException ve = (ValidatorException)ce;
+                if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) {
+                    throw new Exception("Unexpected exception: " + ce);
+                }
+            } else {
+                throw new Exception("Unexpected exception: " + ce);
+            }
+        }
+    }
+
+    private static X509Certificate[] loadCertificateChain(String name)
+            throws Exception {
+        try (InputStream in = new FileInputStream(TEST_SRC + File.separator +
+                                                  name + "-chain.pem")) {
+            Collection<X509Certificate> certs =
+                (Collection<X509Certificate>)cf.generateCertificates(in);
+            return certs.toArray(new X509Certificate[0]);
+        }
+    }
+
+    private static class DistrustedTLSServerCert extends X509Certificate {
+        private final X509Certificate cert;
+        private final Date notBefore;
+        DistrustedTLSServerCert(X509Certificate cert, Date notBefore) {
+            this.cert = cert;
+            this.notBefore = notBefore;
+        }
+        public Set<String> getCriticalExtensionOIDs() {
+           return cert.getCriticalExtensionOIDs();
+        }
+        public byte[] getExtensionValue(String oid) {
+            return cert.getExtensionValue(oid);
+        }
+        public Set<String> getNonCriticalExtensionOIDs() {
+            return cert.getNonCriticalExtensionOIDs();
+        }
+        public boolean hasUnsupportedCriticalExtension() {
+            return cert.hasUnsupportedCriticalExtension();
+        }
+        public void checkValidity() throws CertificateExpiredException,
+            CertificateNotYetValidException {
+            // always pass
+        }
+        public void checkValidity(Date date) throws CertificateExpiredException,
+            CertificateNotYetValidException {
+            // always pass
+        }
+        public int getVersion() { return cert.getVersion(); }
+        public BigInteger getSerialNumber() { return cert.getSerialNumber(); }
+        public Principal getIssuerDN() { return cert.getIssuerDN(); }
+        public Principal getSubjectDN() { return cert.getSubjectDN(); }
+        public Date getNotBefore() { return notBefore; }
+        public Date getNotAfter() { return cert.getNotAfter(); }
+        public byte[] getTBSCertificate() throws CertificateEncodingException {
+            return cert.getTBSCertificate();
+        }
+        public byte[] getSignature() { return cert.getSignature(); }
+        public String getSigAlgName() { return cert.getSigAlgName(); }
+        public String getSigAlgOID() { return cert.getSigAlgOID(); }
+        public byte[] getSigAlgParams() { return cert.getSigAlgParams(); }
+        public boolean[] getIssuerUniqueID() {
+            return cert.getIssuerUniqueID();
+        }
+        public boolean[] getSubjectUniqueID() {
+            return cert.getSubjectUniqueID();
+        }
+        public boolean[] getKeyUsage() { return cert.getKeyUsage(); }
+        public int getBasicConstraints() { return cert.getBasicConstraints(); }
+        public byte[] getEncoded() throws CertificateEncodingException {
+            return cert.getEncoded();
+        }
+        public void verify(PublicKey key) throws CertificateException,
+            InvalidKeyException, NoSuchAlgorithmException,
+            NoSuchProviderException, SignatureException {
+            cert.verify(key);
+        }
+        public void verify(PublicKey key, String sigProvider) throws
+            CertificateException, InvalidKeyException, NoSuchAlgorithmException,
+            NoSuchProviderException, SignatureException {
+            cert.verify(key, sigProvider);
+        }
+        public PublicKey getPublicKey() { return cert.getPublicKey(); }
+        public String toString() { return cert.toString(); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustglobalca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,66 @@
+-----BEGIN CERTIFICATE-----
+MIIHBjCCBe6gAwIBAgIQanINWwJAuap0V7lFjnfUwTANBgkqhkiG9w0BAQsFADBE
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMU
+R2VvVHJ1c3QgU1NMIENBIC0gRzMwHhcNMTcwNTAzMDAwMDAwWhcNMjAwNTAyMjM1
+OTU5WjCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDU1vdW50YWluIFZpZXcxFzAVBgNVBAoMDkdlb1RydXN0LCBJbmMuMRgwFgYD
+VQQLDA9Sb290IDEwIC0gVkFMSUQxIjAgBgNVBAMMGXZhbGlkLXJvb3QxMC5nZW90
+cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTegUYhAh0
+P7aF6jzk8dit4Vzddo3hM+J7Eak/+N1sqVUS2HpNd7VO50FrbEWKIRusv7QNtlpY
+1Cgrla8M4RAhCB0wkkHXZ1Evz6E1AEFQqNSjyuRQxeEXl+xCL+MF+yAMhDRnHh+E
+eSJ3ie0T66saOyaLM9fPpr3xomAQ/IRlP1atJ/Z8XbPo25HuxwzxiWFW+RjwVIfI
+gxHz4Okwc1uImDUIDlEu9Uaqqb4jHhxU1EkKMmgEncpqwCROcZMujUkogfB49Z7+
+K17r6ARIrUuxqfNPrPwe+O88WgIeDSWffPM67UlvtomZOwuTNdv9OoCX1wUCLS7m
+/gZ3rqqqeJvfAgMBAAGjggOkMIIDoDAkBgNVHREEHTAbghl2YWxpZC1yb290MTAu
+Z2VvdHJ1c3QuY29tMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgWgMCsGA1UdHwQk
+MCIwIKAeoByGGmh0dHA6Ly9nbi5zeW1jYi5jb20vZ24uY3JsMIGdBgNVHSAEgZUw
+gZIwgY8GBmeBDAECAjCBhDA/BggrBgEFBQcCARYzaHR0cHM6Ly93d3cuZ2VvdHJ1
+c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5L2xlZ2FsMEEGCCsGAQUFBwICMDUM
+M2h0dHBzOi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeS9s
+ZWdhbDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU
+0m/3lvSFP3I8MH0j2oV4m6N8WnwwVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzAB
+hhNodHRwOi8vZ24uc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vZ24uc3lt
+Y2IuY29tL2duLmNydDCCAfUGCisGAQQB1nkCBAIEggHlBIIB4QHfAHUA3esdK3oN
+T6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFbz9h5vQAABAMARjBEAiAx/C0U
+5NdHxK4v2oHnstYksb1Vny8PcQkSvgpx9PsZEwIgNTOU70Zc5szG23xdbvtoH5lN
+SAoVswiF5gFQS5MGu1sAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3c
+EAAAAVvP2HnZAAAEAwBHMEUCIFGjB8r2H0VDwTUE/aY/Mv+M97sqAvEP1doOcHpg
+0qyfAiEArw/S2F7OEcmKGUY1WRBuApfAx5d7hzrTSV/jZv95qJwAdgDuS723dc5g
+uuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAVvP2HoDAAAEAwBHMEUCIQCH6MFZ
+tZF3Cqukt3/69fkU0Y5ePXXx8+xkOXRsIG3EGgIgSmCBWrnmPiiGA3x5QP8I8m4r
+Uee0y7s4NQNwjMgHrjwAdgC8eOHfxfY8aEZJM02hD6FfCXlpIAnAgbTz9pF/Ptm4
+pQAAAVvP2HqcAAAEAwBHMEUCIA8e2kAVYYuQCtn4PqK98BuHnLm9rC40DboFLCle
+SmQsAiEApbCJR05hr9VkNWmjaaUUGGZdVyUu9XX504LHVWyXZDUwDQYJKoZIhvcN
+AQELBQADggEBAEtfBfZ2y5uTohvW3h00Kcuop6Nq7Y59GU3MeizPKtx48DB8qHyd
+y5bLFwXzsGA1WkwpKzPbROsTGcAAXJHh03bj24AemUr/J/eQcjkfSoNBdHDpiSsk
+VZkQK2fGJDiYJ/r9mxKZcgd2pyN3l2OtVtNMv2dnFGF35UkkeqO3jqImwbypAmRX
+HdQV9dvW2YDRjzkebNNey6UwY9+YTSzr4da2hcaMHrj588Eqa4DDgNcY9QnE2RzN
+giArA+4RlM4AZ3jC2A756I67hrlvH+lhumHLp06hGfMiQJF1aaauFVSa36HKc3C/
+ty+sLdJbemEJLAr8uNXggFD+U8TKw1S4LSw=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIETzCCAzegAwIBAgIDAjpvMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMTMxMTA1MjEzNjUwWhcNMjIwNTIwMjEzNjUwWjBEMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
+U1NMIENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjvn4K
+hqPPa209K6GXrUkkTdd3uTR5CKWeop7eRxKSPX7qGYax6E89X/fQp3eaWx8KA7UZ
+U9ulIZRpY51qTJEMEEe+EfpshiW3qwRoQjgJZfAU2hme+msLq2LvjafvY3AjqK+B
+89FuiGdT7BKkKXWKp/JXPaKDmJfyCn3U50NuMHhiIllZuHEnRaoPZsZVP/oyFysx
+j0ag+mkUfJ2fWuLrM04QprPtd2PYw5703d95mnrU7t7dmszDt6ldzBE6B7tvl6QB
+I0eVH6N3+liSxsfQvc+TGEK3fveeZerVO8rtrMVwof7UEJrwEgRErBpbeFBFV0xv
+vYDLgVwts7x2oR5lAgMBAAGjggFKMIIBRjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjAdBgNVHQ4EFgQU0m/3lvSFP3I8MH0j2oV4m6N8WnwwEgYDVR0T
+AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNgYDVR0fBC8wLTAroCmgJ4Yl
+aHR0cDovL2cxLnN5bWNiLmNvbS9jcmxzL2d0Z2xvYmFsLmNybDAvBggrBgEFBQcB
+AQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9nMi5zeW1jYi5jb20wTAYDVR0gBEUw
+QzBBBgpghkgBhvhFAQc2MDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1
+c3QuY29tL3Jlc291cmNlcy9jcHMwKQYDVR0RBCIwIKQeMBwxGjAYBgNVBAMTEVN5
+bWFudGVjUEtJLTEtNTM5MA0GCSqGSIb3DQEBCwUAA4IBAQCg1Pcs+3QLf2TxzUNq
+n2JTHAJ8mJCi7k9o1CAacxI+d7NQ63K87oi+fxfqd4+DYZVPhKHLMk9sIb7SaZZ9
+Y73cK6gf0BOEcP72NZWJ+aZ3sEbIu7cT9clgadZM/tKO79NgwYCA4ef7i28heUrg
+3Kkbwbf7w0lZXLV3B0TUl/xJAIlvBk4BcBmsLxHA4uYPL4ZLjXvDuacu9PGsFj45
+SVGeF0tPEDpbpaiSb/361gsDTUdWVxnzy2v189bPsPX1oxHSIFMTNDcFLENaY9+N
+QNaFHlHpURceA1bJ8TCt55sRornQMYGbaLHZ6PPmlH7HrhMvh+3QJbBo+d4IWvMp
+zNSS
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag2-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,55 @@
+-----BEGIN CERTIFICATE-----
+MIIFcDCCBRegAwIBAgIQHw+Lyn4UTWqRF8/JM7DH+zAKBggqhkjOPQQDAjBHMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xHzAdBgNVBAMTFkdl
+b1RydXN0IEVDQyBFViBTU0wgQ0EwHhcNMTcwNTExMDAwMDAwWhcNMTkwNTAzMjM1
+OTU5WjCB8jETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQBgjc8AgECDAhE
+ZWxhd2FyZTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9u
+MRAwDgYDVQQFEwczNDc5NzUwMRcwFQYDVQQKDA5HZW9UcnVzdCwgSW5jLjEYMBYG
+A1UECwwPUm9vdCAxMiAtIFZBTElEMSIwIAYDVQQDDBl2YWxpZC1yb290MTIuZ2Vv
+dHJ1c3QuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbvbmcvKl4MkBRBNY
+7EOQ7ugwPIPPCp73W++hAcbFPqiDmupl/fqfrbjL06FImeWzDY7cQOhLbv0Ha8Yq
+UrL8HKOCAzcwggMzMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMA4GA1UdDwEB/wQEAwIFoDCBqQYDVR0gBIGhMIGeMIGSBgkrBgEEAfAi
+AQYwgYQwPwYIKwYBBQUHAgEWM2h0dHBzOi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNv
+dXJjZXMvcmVwb3NpdG9yeS9sZWdhbDBBBggrBgEFBQcCAjA1DDNodHRwczovL3d3
+dy5nZW90cnVzdC5jb20vcmVzb3VyY2VzL3JlcG9zaXRvcnkvbGVnYWwwBwYFZ4EM
+AQEwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2ZlLnN5bWNiLmNvbS9mZS5jcmww
+VwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vZmUuc3ltY2QuY29t
+MCYGCCsGAQUFBzAChhpodHRwOi8vZmUuc3ltY2IuY29tL2ZlLmNydDAkBgNVHREE
+HTAbghl2YWxpZC1yb290MTIuZ2VvdHJ1c3QuY29tMB8GA1UdIwQYMBaAFABLH5GB
+DgtDzgRzu5abgh1mY608MIIBfAYKKwYBBAHWeQIEAgSCAWwEggFoAWYAdQDd6x0r
+eg1PpiCLga2BaHB+Lo6dAdVciI09EcTNtuy+zAAAAVv4eJwGAAAEAwBGMEQCIBSx
+ZdTP+tDh1rstAJ7vyIPNH7HBE6mCRj9W41ccUwbGAiA7p0ljgNoO/ldknmgTiZdI
+FlgEy1KgPQiHYvNS+9MHYwB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7I
+DdwQAAABW/h4nDMAAAQDAEYwRAIgWf4vMQ9lrM5xKD+iEVXkC7g5CB3fmuxP7fNp
+7qX7PB8CIDNe8HT3262gw3D13MGQccxfUhf7dZ9aCRgk7UEDimsJAHYA7ku9t3XO
+YLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFb+Hid8wAABAMARzBFAiAxSFtr
+/dpMd53ZSC4N9FomEZhoNnARnYe7cWnTAdKVHAIhALEz0JaOqgYTf0k9yYPuNW4E
+Bo26yneH6KtdkMV7/gRoMAoGCCqGSM49BAMCA0cAMEQCIBPb1wYt8d6EdjLXiAZp
+UfKGFdQF/oexd5GCB1TU0juDAiBWPRPVggfYfc4gLOkYSqIPvPRmEmEhyY8fqsM6
+3YJgDg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDyDCCA06gAwIBAgIQDww3Kf30lVv4ZevF7vQy/DAKBggqhkjOPQQDAzCBmDEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
+KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
+MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEcyMB4XDTE2MDEwNzAwMDAwMFoXDTI2MDEwNjIzNTk1OVowRzELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDkdlb1RydXN0LCBJbmMuMR8wHQYDVQQDExZHZW9UcnVz
+dCBFQ0MgRVYgU1NMIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEF136Fo2A
+bY7q0YbhVBTL4HNFaJyTdoU3y+o8YdhxQuw1SrpQT9EwLTyx8Xzf/LNPeoalIKNu
+U/3LQgNct6Fk9aOCAcgwggHEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggr
+BgEFBQcDAQYIKwYBBQUHAwIwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJo
+dHRwOi8vZy5zeW1jZC5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADCBqQYDVR0gBIGh
+MIGeMAcGBWeBDAEBMIGSBgkrBgEEAfAiAQYwgYQwPwYIKwYBBQUHAgEWM2h0dHBz
+Oi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeS9sZWdhbDBB
+BggrBgEFBQcCAjA1GjNodHRwczovL3d3dy5nZW90cnVzdC5jb20vcmVzb3VyY2Vz
+L3JlcG9zaXRvcnkvbGVnYWwwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2cuc3lt
+Y2IuY29tL0dlb1RydXN0UENBLUcyLmNybDArBgNVHREEJDAipCAwHjEcMBoGA1UE
+AxMTU1lNQy1FQ0MtQ0EtcDI1Ni0zMjAdBgNVHQ4EFgQUAEsfkYEOC0POBHO7lpuC
+HWZjrTwwHwYDVR0jBBgwFoAUFV81V1FV+yWyrQNp/AGj+r4RVdUwCgYIKoZIzj0E
+AwMDaAAwZQIweZGj+Ar54cOBtC1I6rkfdNOtxSg77WBAvvsEv1+knWbbu8Acroz1
+Q9xqHnHLXpgRAjEAxNA5KzWxutl/kVj/7bUCYtvSWLfmb2ZTTsvof7VjjWlRnPje
+wLtx+yN5EV7LPWDi
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag3-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,67 @@
+-----BEGIN CERTIFICATE-----
+MIIG6jCCBdKgAwIBAgIQZfxPPcDd0zSbl2UQK6dtRzANBgkqhkiG9w0BAQsFADBG
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEfMB0GA1UEAxMW
+R2VvVHJ1c3QgU0hBMjU2IFNTTCBDQTAeFw0xNzAyMDEwMDAwMDBaFw0yMDAzMDIy
+MzU5NTlaMHgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYD
+VQQHDA1Nb3VudGFpbiBWaWV3MR0wGwYDVQQKDBRTeW1hbnRlYyBDb3Jwb3JhdGlv
+bjEdMBsGA1UEAwwUc3NsdGVzdDEzLmJidGVzdC5uZXQwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDV734wSAESareltMadza6jJ0SVi6bLb/Q23La5v5Z/
+rFCdPzSRrMMKj08NfAA/i1k+TF/d7NZ+rrFvCIN33kfDzSLvIQiJh7NZ/yivA9DY
+eH7RAuVXfrsqhsqpgHVNSmMXxaGxOIJ4RcEx0RB3vbb3frm46lCLMH0uCavJ7Txo
+gDJpAG6AP/hF524IVJcIcHxhJqZo1pQO/iwb/uNGkqwRuAeL9zKhv0tYyiHKNqyW
+AXk51Nzm+TQq0flw0nw7EC9f+VNrquiO5j76JKeL+DaxpUtftTpzL5b5oM/LXwDt
+62VUMujOyVuKPIj1ieQVdhETSDvf340tQI7MB4qFrHlFAgMBAAGjggOgMIIDnDAf
+BgNVHREEGDAWghRzc2x0ZXN0MTMuYmJ0ZXN0Lm5ldDAJBgNVHRMEAjAAMA4GA1Ud
+DwEB/wQEAwIFoDArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vZ2ouc3ltY2IuY29t
+L2dqLmNybDCBnQYDVR0gBIGVMIGSMIGPBgZngQwBAgIwgYQwPwYIKwYBBQUHAgEW
+M2h0dHBzOi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeS9s
+ZWdhbDBBBggrBgEFBQcCAjA1DDNodHRwczovL3d3dy5nZW90cnVzdC5jb20vcmVz
+b3VyY2VzL3JlcG9zaXRvcnkvbGVnYWwwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMB8GA1UdIwQYMBaAFBRnju2DT9YenUAEDARGoXA0sg9yMFcGCCsGAQUF
+BwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL2dqLnN5bWNkLmNvbTAmBggrBgEF
+BQcwAoYaaHR0cDovL2dqLnN5bWNiLmNvbS9nai5jcnQwggH2BgorBgEEAdZ5AgQC
+BIIB5gSCAeIB4AB1AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0RxM227L7MAAAB
+WfvjZWcAAAQDAEYwRAIgIxFLEWNCRmGQl2o+3psXrWAd88rz9G1JbxbAgHFpXmAC
+IFxZpWwuj1Aq4Yx6VrBBqvA+K/GlNY2OcThPaeoj3jdfAHYApLkJkLQYWBSHuxOi
+zGdwCjw1mAT5G9+443fNDsgN3BAAAAFZ++NlpAAABAMARzBFAiB+iko2tw6USdc2
+E956ZIpXy9TTUiVtpKHzKFhuR7mdwwIhAMwTisbIGh6UTdjXnPktWPFcWhfxQOPB
+U41c/v7zuFV9AHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFZ
+++NnWwAABAMASDBGAiEAmqY4AhQPt/tU1iR0LvrlpIjKlc0IArbxENVkVbNTYwcC
+IQCPlJZQb7mmlPwjy//aJMyOtEeVFb6DzfM4uhJiSrU9WAB2ALx44d/F9jxoRkkz
+TaEPoV8JeWkgCcCBtPP2kX8+2bilAAABWfvjZmgAAAQDAEcwRQIgMcV63d6G3RHm
+rN34V1zDiAbKG1k/pDEErcfZ+8Y0GdwCIQCcuqmKjnpUYs8ps4/NSx78U2ssNuLA
++QDpYuH1XKHCUTANBgkqhkiG9w0BAQsFAAOCAQEAjYdQJYtrhPJTIHcsyksTWGHS
+cpIt7y1bzp+t06KYn6x+ax+09sTJQzr7L2BA3h24blgMWr2yEH0mvQdVncBFt8xr
+9O8jeg5dHSeJknnDlXOA23Z2NJLanX7m29/713DxZ+HJXFx0Wiz5mtuTo7Q6FpQF
+SI44v0fbUTb7LV81fFpyriroZTlpiMI01NLWGldyCchC795fEYiibSvr1uidjp9i
++MKppG3t3YXb1/Wu2A21b6Z4akgl021A5cJcg8/Q3wjYMqQTtuUEezsBl2jLoey1
+pa/ag3epMe19zTq4iqS3Z4r+2jrZ4IjnKmkDKo4uKvTAfUX2Yu2+Lm3E6Vfdow==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIExzCCA6+gAwIBAgIQQYISfRLZxrMhOUMSVmQAuDANBgkqhkiG9w0BAQsFADCB
+mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
+MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEczMB4XDTEzMDUyMzAwMDAwMFoXDTIzMDUyMjIzNTk1OVowRjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHzAdBgNVBAMTFkdlb1Ry
+dXN0IFNIQTI1NiBTU0wgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDGqQtdF6V9xs8q78Zm0UIeX4N4aJGv5qeL8B1EAQoZypzUix3hoZCjwVu011tq
+i/wOSR7CYin+gBU5i4EqJ7X7EqgFIgvFLPXZmN0WLztm52KiQzKsj7WFyFIGLFzA
+d/pn94PoXgWNyKuhFjKK0kDshjocI6mNtQDecr2FVf4GAWBdrbPgZXOlkhSelFZv
+k+6vqTowJUqOCYTvt9LV15tJzenAXmdxIqxQkEMgXaGjFYP9/Kc5vGtlSBJg/90j
+szqq9J+cN1NBokeTgTMJ5SLGyBxJoW6NzIOzms3qQ/IZ0yTLqCmuUsz0CCewhOrO
+J7XhNBNzklyHhirGsGg2rcsJAgMBAAGjggFcMIIBWDA7BggrBgEFBQcBAQQvMC0w
+KwYIKwYBBQUHMAGGH2h0dHA6Ly9wY2EtZzMtb2NzcC5nZW90cnVzdC5jb20wEgYD
+VR0TAQH/BAgwBgEB/wIBADBMBgNVHSAERTBDMEEGCmCGSAGG+EUBBzYwMzAxBggr
+BgEFBQcCARYlaHR0cDovL3d3dy5nZW90cnVzdC5jb20vcmVzb3VyY2VzL2NwczA7
+BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9HZW9UcnVz
+dFBDQS1HMy5jcmwwDgYDVR0PAQH/BAQDAgEGMCoGA1UdEQQjMCGkHzAdMRswGQYD
+VQQDExJWZXJpU2lnbk1QS0ktMi00MTYwHQYDVR0OBBYEFBRnju2DT9YenUAEDARG
+oXA0sg9yMB8GA1UdIwQYMBaAFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3
+DQEBCwUAA4IBAQAQEOryENYIRuLBjz42WcgrD/5N7OP4tlYxeCXUdvII3e8/zYsc
+fqp//AuoI2RRs4fWCfoi+scKUejOuPYDcOAbWrmxspMREPmXBQcpbG1XJVTo+Wab
+Dvvbn+6Wb2XLH9hVzjH6zwL00H9QZv8veZulwt/Wz8gVg5aEmLJG1F8TqD6nNJwF
+ONrP1mmVqSaHdgHXslEPgWlGJhyZtoNY4ztYj9y0ccC5v0KcHAOe5Eao6rnBzfZb
+qTyW+3mkM3Onnni5cNxydMQyyAAbye9I0/s6m/r+eppAaRzI2ig3C9OjuX6WzCso
+w1Zsb+nbUrH6mvvnr7WXpiLDxaiTsQDJB7J9
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustuniversalca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,71 @@
+-----BEGIN CERTIFICATE-----
+MIIHATCCBemgAwIBAgIQJmVwMHBfVctB6q6UbCC4eDANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMX
+R2VvVHJ1c3QgRVYgU1NMIENBIC0gRzYwHhcNMTcwNTA5MDAwMDAwWhcNMTkwNTAz
+MjM1OTU5WjCB8jETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQBgjc8AgEC
+DAhEZWxhd2FyZTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
+BgNVBAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0
+aW9uMRAwDgYDVQQFEwczNDc5NzUwMRcwFQYDVQQKDA5HZW9UcnVzdCwgSW5jLjEY
+MBYGA1UECwwPUm9vdCAxNCAtIFZBTElEMSIwIAYDVQQDDBl2YWxpZC1yb290MTQu
+Z2VvdHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAua4C
+iQ+Sk3VXblrh9xI6DqxELgjGxLOxORgayEM1/x4lKC5Dah5Ey9jeDhy6eDLJRXce
+JHjR5FYFNpjRpp8w58SzmosAQk7tgRy6HGPtVUUXCVkfUDJ6LIcZE1UcwKO3CUdh
+2Dn3naVCNImdqqoUTCr4H/8iIy+1l4aUDnukiAsTV6M2Len0UQpD8MY2KyVmWNJz
+GLGzZKXKwU42CZwK8hR+xUH/BSEcWvfU2bFShVGIY1CCpJ5vdhi0QMaRfDzpAXVw
+3gvO5bN7RvDD8tABtLUjpnm0P7HzxkVkEO+BGg0P+qpw4bflu+TE7die+pFY1Skz
+1rEFOvMEVOCqoinanwIDAQABo4IDOzCCAzcwJAYDVR0RBB0wG4IZdmFsaWQtcm9v
+dDE0Lmdlb3RydXN0LmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDCBqQYD
+VR0gBIGhMIGeMIGSBgkrBgEEAfAiAQYwgYQwPwYIKwYBBQUHAgEWM2h0dHBzOi8v
+d3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeS9sZWdhbDBBBggr
+BgEFBQcCAjA1DDNodHRwczovL3d3dy5nZW90cnVzdC5jb20vcmVzb3VyY2VzL3Jl
+cG9zaXRvcnkvbGVnYWwwBwYFZ4EMAQEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL2ZpLnN5
+bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2ZpLnN5bWNiLmNvbS9maS5jcnQw
+KwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2ZpLnN5bWNiLmNvbS9maS5jcmwwHwYD
+VR0jBBgwFoAUvpmWhYTv5p/5H+H8ZmdbVqX6i1MwggGABgorBgEEAdZ5AgQCBIIB
+cASCAWwBagB3AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0RxM227L7MAAABW/fm
+zy4AAAQDAEgwRgIhALUgY0DrJaqjpgv19bbS434UDMpUfIfZ7qyxz30M1LiQAiEA
+4dXlkRJLc3i+DcFUNSjRh8dKPLZMC3DhD4bm7tDQaWwAdgCkuQmQtBhYFIe7E6LM
+Z3AKPDWYBPkb37jjd80OyA3cEAAAAVvuRpVUAAAEAwBHMEUCIGUbCcQ2agQi+sWo
+zudL0F2rSS4elFAgHy/nSzGb/fl0AiEA5zLqvTsn8ioQ89KycY3HocNCLAPtqDqe
+t9+6pcJnVFsAdwDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAVvu
+RpV3AAAEAwBIMEYCIQDrKkvy08fPVx4vbVO4wBYw7tpqkmrWTaKCIs7Tx9utYwIh
+ANuH3S2ngCM7WzCebmbLFVDmaNxQki3kmZbCOp358sRvMA0GCSqGSIb3DQEBCwUA
+A4IBAQAOEMVj7HwG97PurqFqoa9JI2adgj8er1hc70dIGkTt21OKLWvWp0Yafcjx
+qqEByFjzkF0/yreVmbxl1zf7utUMfWslmv7ElXDvS79lZ2UWO6vptyaZM6VSJ2s+
+pmGHJaQgw3AbDmu5yLmUPlHwOttv//AOuaZvrQISzrwmMs60sHn+pS7qtSdL3lYa
+PtqhCBQNJoLDstn57B/aLBUYx5rSqhK68CCxY4ZcA1i02RakZJIhGbOAOy4x5pZH
+uZiiRFTxgZRGNNUDjrhmVVk7cQDu3eDRDkUKD9m7796GJ+aFDZlvzmORaNW5GYjv
+0qIRajIKmohnwumn+xaJFpmDEuw+
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFUjCCAzqgAwIBAgIQAQAZ9apyafiMHhwSEeyNTzANBgkqhkiG9w0BAQsFADBF
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMV
+R2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTE3MDUwMTE0MTcxNloXDTI3MDQyOTE0
+MTcxNlowRzELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAe
+BgNVBAMTF0dlb1RydXN0IEVWIFNTTCBDQSAtIEc2MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEArvBCvG8ORCUSTiERfNmMdtEvKhvmnV8MrSLOw6t3q24c
++r/y69NGdUJArGmBv8crE5Vxd5mYlecmflrJtyuh08HDFc4Mr4yh2xcGmeKA7Uz5
+Q/Wpfropvop1cFB3r/8BwpfxortVi2jkawQ89TDo3l0RacJrjM29dq+rQwqIWvfK
+dHuU58t54CsXzvJrqDnhL4v+LQ2mqZMbAfh1Mhh8MftEH5UfOSgY2uXwnu5vERYI
+3cl0nakgoJOyUlb187iFd/TrSrYGquv8dYAKTKOTd44YNwxb43iKk/esqxOTiqW8
+rAFv6/E6aOmHwqyP9l7LMtLzVE27ra1wESMR70JttwIDAQABo4IBOjCCATYwHwYD
+VR0jBBgwFoAU2rsuqrAMuIgmUXRcbQPTwNiPetYwHQYDVR0OBBYEFL6ZloWE7+af
++R/h/GZnW1al+otTMA4GA1UdDwEB/wQEAwIBBjAuBggrBgEFBQcBAQQiMCAwHgYI
+KwYBBQUHMAGGEmh0dHA6Ly9nLnN5bWNkLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEA
+MB8GA1UdIAQYMBYwBwYFZ4EMAQEwCwYJKwYBBAHwIgEGMDUGA1UdHwQuMCwwKqAo
+oCaGJGh0dHA6Ly9nLnN5bWNiLmNvbS9jcmxzL2d0dW5pY2ExLmNybDAdBgNVHSUE
+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwKQYDVR0RBCIwIKQeMBwxGjAYBgNVBAMT
+EVN5bWFudGVjUEtJLTItNzU3MA0GCSqGSIb3DQEBCwUAA4ICAQA8iM9XJ01hEzSM
+iATIdK/z+F1Vtm9hHjp0FzkOvVYkp7v6LIkazg299fyAy2+A/tpSzKyMIzy5B2R/
+sjbWykIK+3vtOlgUNilP7EoudiCjR/692THUtJ/QjPNzFYhO9apU2Wpc33ZYMH0Q
+YKUPmAd7eBmsdVKHNLENcMjjCjnkjXnYtxq/jv2R4QhD83tbFnvBoKjxi2vAfDXG
+xN8aItVg/FSdScZCMhe0w/HLzcN6N3NCGDBn2PjF0o3QLJa9yVSrvJ9Nh3my6rUb
+gMhlfFEQXTmLxucqL5/n5lXyUWd0kTxFv++TalTeqYf3G/oeu5kcpfjUJREp/9ed
+gQqhDEGIuJFrMm4qi+sNDrq0OkLBHCqefFArTz2ApiI9zd9pcKfjS3f/EB87AVmW
+3m1lfqPeS+w+vBg7VCGNY9gGNUe+w4juTEBiwIjnp7I+aBVnIwxV9PdJoj1ZaLCx
+U8AEN6tXD8IcCquLxs3fBsF85svvUfK8qh3ufKB3I3RHGq5Asmtvc5URcyeuA+d2
+zPQ1qAXH5m3DLkb0KdAvJ5E6mQ2S2aqwJPXtpqx2J40C1Qx+uUsHG2vDoT3ZTazt
+LPBIIqF2YJr1hr760yXM3Jf14eyc+RXPrjA1mc/CKNbv6SvU5MvlYj+Vvx70y+k8
+U5ev+YdiYoYu0wQtDJQCJjM+eavqxQ==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,66 @@
+-----BEGIN CERTIFICATE-----
+MIIG/TCCBeWgAwIBAgIQfVQyuY0yb1Q+TZDQHtRC8TANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMX
+R2VvVHJ1c3QgRVYgU1NMIENBIC0gRzQwHhcNMTcwNTAzMDAwMDAwWhcNMTkwNTAz
+MjM1OTU5WjCB8jETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQBgjc8AgEC
+DAhEZWxhd2FyZTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
+BgNVBAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0
+aW9uMRAwDgYDVQQFEwczNDc5NzUwMRcwFQYDVQQKDA5HZW9UcnVzdCwgSW5jLjEY
+MBYGA1UECwwPUm9vdCAxMSAtIFZBTElEMSIwIAYDVQQDDBl2YWxpZC1yb290MTEu
+Z2VvdHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy5Wn
+8CUYyHQnisa3ihcezpRBrKNF9OGb9ye9G4mUFRAHoFlNdwVP3qxBtEo7N6ylZ7G0
+tMcLwqy+cdMZlyCw0qPQrJQXqp5AEL034IMeckSvR9I2RyR7DUW3kVtKRsDiAUo9
+4r8h/5ZT96OW/jtdE2WPr0Wt5r0DyG8xzUbUdh5tYFwlxMJLeHgomqsG1WXBEDvS
+cTJk9JMZpH5d1FYux+T0BkJsYyj0NRcDnQuc6P4QIkpim3wsOBKMa7beEiCanmcK
+dSBrBfl2iep67VfOEYfjYTDOwqwaknSfb2H33e0lpunI76Rwv1uZkr/4ciDyaNZS
+IsLh1i57eKvWqn+G9wIDAQABo4IDNzCCAzMwJAYDVR0RBB0wG4IZdmFsaWQtcm9v
+dDExLmdlb3RydXN0LmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDArBgNV
+HR8EJDAiMCCgHqAchhpodHRwOi8vZ20uc3ltY2IuY29tL2dtLmNybDCBqQYDVR0g
+BIGhMIGeMIGSBgkrBgEEAfAiAQYwgYQwPwYIKwYBBQUHAgEWM2h0dHBzOi8vd3d3
+Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeS9sZWdhbDBBBggrBgEF
+BQcCAjA1DDNodHRwczovL3d3dy5nZW90cnVzdC5jb20vcmVzb3VyY2VzL3JlcG9z
+aXRvcnkvbGVnYWwwBwYFZ4EMAQEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF
+BwMCMB8GA1UdIwQYMBaAFN7PXFC3rgIfFReqFugNtSidalrzMFcGCCsGAQUFBwEB
+BEswSTAfBggrBgEFBQcwAYYTaHR0cDovL2dtLnN5bWNkLmNvbTAmBggrBgEFBQcw
+AoYaaHR0cDovL2dtLnN5bWNiLmNvbS9nbS5jcnQwggF8BgorBgEEAdZ5AgQCBIIB
+bASCAWgBZgB1AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0RxM227L7MAAABW8/Y
+RIwAAAQDAEYwRAIgWDLmmEUz8FyqMxfyweXN18EAYitvP3XPnU3XkJzRSrQCIB5y
+KErRbSiDkj43iFWQVodPA70HtcgdIzk4X3KA7thOAHYApLkJkLQYWBSHuxOizGdw
+Cjw1mAT5G9+443fNDsgN3BAAAAFbz9hEtwAABAMARzBFAiAjTCcAEJDj9M/xY7a/
+pysTrl0MrE6rMzpotNZ5kik1PgIhAMTAYXIUeA7LqKhYlvOvW/cH+uB+8329J8cy
+xMF8dmEJAHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFbz9hE
+3gAABAMARjBEAiA7UGcNzFIEVvXeJRuWPfhA8t0JOjl//7ZuLYgdnt6/jAIgIHyH
+QHLo2q5o99msj2s8o1BaTmxxnSF4TZPm8iZGLywwDQYJKoZIhvcNAQELBQADggEB
+AGBUtaCjWXpAPSc7ypv6f+IJGYfGHR7NLBLLjTytKHcIx5Hb0YT14TFWnXacaSHk
+XL/vY3v3CrdGqn6UZb4UEdyB54juG6J7DLQF/l8oeG0GzPQLlSOt0ZU4Cq9DayO0
+OFS6jD7K7FqalSiBzvFnDFmWqLXZQaO/dFPHvZVIdhfO6Vl/3yH+nkphrc8AiHqV
+0LkFaoki3RUJMqPvb1pyZ41MzMVsS/LMPoxS0JUl+YKAhL5H1JS1OPMY1B++k2hs
+BoScopXAC1xsOkpQWg+U2+mMnAebcCeFWtKrjVUIA+lzaAr6jbBOK9dLSschRXBe
+R9xGJ3I9J4t0pKD5lFr9+fQ=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEbjCCA1agAwIBAgIQboqQ68/wRIpyDQgF0IKlRDANBgkqhkiG9w0BAQsFADBY
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
+R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xMzEw
+MzEwMDAwMDBaFw0yMzEwMzAyMzU5NTlaMEcxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMSAwHgYDVQQDExdHZW9UcnVzdCBFViBTU0wgQ0EgLSBH
+NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANm0BfI4Zw8J53z1Yyrl
+uV6oEa51cdlMhGetiV38KD0qsKXV1OYwCoTU5BjLhTfFRnHrHHtp22VpjDAFPgfh
+bzzBC2HmOET8vIwvTnVX9ZaZfD6HHw+QS3DDPzlFOzpry7t7QFTRi0uhctIE6eBy
+GpMRei/xq52cmFiuLOp3Xy8uh6+4a+Pi4j/WPeCWRN8RVWNSL/QmeMQPIE0KwGhw
+FYY47rd2iKsYj081HtSMydt+PUTUNozBN7VZW4f56fHUxSi9HdzMlnLReqGnILW4
+r/hupWB7K40f7vQr1mnNr8qAWCnoTAAgikkKbo6MqNEAEoS2xeKVosA7pGvwgtCW
+XSUCAwEAAaOCAUMwggE/MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQD
+AgEGMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYTaHR0cDovL2cyLnN5bWNi
+LmNvbTBHBgNVHSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93
+d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2cxLnN5bWNiLmNvbS9HZW9UcnVzdFBDQS5jcmwwKQYDVR0RBCIwIKQe
+MBwxGjAYBgNVBAMTEVN5bWFudGVjUEtJLTEtNTM4MB0GA1UdDgQWBBTez1xQt64C
+HxUXqhboDbUonWpa8zAfBgNVHSMEGDAWgBQs1VBBlxWL8I82YVtK+2vZmckzkjAN
+BgkqhkiG9w0BAQsFAAOCAQEAtI69B7mahew7Z70HYGHmhNHU7+sbuguCS5VktmZT
+I723hN3ke40J2s+y9fHDv4eEvk6mqMLnEjkoNOCkVkRADJ+IoxXT6NNe4xwEYPtp
+Nk9qfgwqKMHzqlgObM4dB8NKwJyNw3SxroLwGuH5Tim9Rt63Hfl929kPhMuSRcwc
+sxj2oM9xbwwum9Its5mTg0SsFaqbLmfsT4hpBVZ7i7JDqTpsHBMzJRv9qMhXAvsc
+4NG9O1ZEZcNj9Rvv7DDZ424uE+k5CCoMcvOazPYnKYTT70zHhBFlH8bjgQPbh8x4
+97Wdlj5qf7wRhXp15kF9Dc/55YVpJY/HjQct+GkPy0FTAA==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag2-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,51 @@
+-----BEGIN CERTIFICATE-----
+MIIFNjCCBN2gAwIBAgIQWCw1fnWLWedosJcJlxQbhDAKBggqhkjOPQQDAjBDMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMR0wGwYDVQQDExR0aGF3
+dGUgRUNDIEVWIFNTTCBDQTAeFw0xNzA1MTEwMDAwMDBaFw0xOTA1MDgyMzU5NTla
+MIHsMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIMCERlbGF3
+YXJlMRUwEwYDVQQKDAxUaGF3dGUsIEluYy4xCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+DApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR0wGwYDVQQPExRQ
+cml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMzg5ODI2MTEXMBUGA1UECwwO
+Um9vdCA4IC0gVkFMSUQxHzAdBgNVBAMMFnZhbGlkLXJvb3Q4LnRoYXd0ZS5jb20w
+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATVxsOfZ4/2K7l7FYl6ejjp5aNuX1J9
+gqfb8WdGQdmKW8TVlhzM9p3BQ61hcISHVW01ZzR2PgYQ5aALzTaZ/Vt9o4IDBzCC
+AwMwCQYDVR0TBAIwADB8BgNVHSAEdTBzMGgGC2CGSAGG+EUBBzABMFkwJgYIKwYB
+BQUHAgEWGmh0dHBzOi8vd3d3LnRoYXd0ZS5jb20vY3BzMC8GCCsGAQUFBwICMCMM
+IWh0dHBzOi8vd3d3LnRoYXd0ZS5jb20vcmVwb3NpdG9yeTAHBgVngQwBATArBgNV
+HR8EJDAiMCCgHqAchhpodHRwOi8vdHEuc3ltY2IuY29tL3RxLmNybDAdBgNVHSUE
+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMFcGCCsGAQUF
+BwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3RxLnN5bWNkLmNvbTAmBggrBgEF
+BQcwAoYaaHR0cDovL3RxLnN5bWNiLmNvbS90cS5jcnQwIQYDVR0RBBowGIIWdmFs
+aWQtcm9vdDgudGhhd3RlLmNvbTAfBgNVHSMEGDAWgBRbM681oBoZN0INV+a8vWtj
+IMKWATCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA3esdK3oNT6Ygi4GtgWhw
+fi6OnQHVXIiNPRHEzbbsvswAAAFb+KihvQAABAMARzBFAiBghdkYlqbxNHmxETaN
+TKTcLlmD8amIlOWP7KnL9/WrBAIhANAssLlY1gvBLJ61ULFbdrVTMi1dqMXPBec8
+LfKdwER4AHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFb+Kih
+ywAABAMARzBFAiAW4sOV17H0V1n4pwnfeeKflHLmr1t4pB9KBCYGh0NaEgIhAMUI
+rLg1SuTCV2pXxRvWkzIAiifaJcPbxPhEp4DGz2d5AHUA7ku9t3XOYLrhQmkfq+Ge
+ZqMPfl+wctiDAMR7iXqo/csAAAFb+Kih/AAABAMARjBEAiA1u/TczjmZ5EDB4Jue
+TYEUyFHFDj3ytCItXk6vzcVPYgIgT6Yc1ugrgocOLqpDsRoQ7Jll/5PIi7QFg5N8
+//OhX+kwCgYIKoZIzj0EAwIDRwAwRAIgCK09KwyaiPsZZMtkjCec9zeVx7YRk8oh
+PvV2UnQf6sQCIAfYgjH7ZQeIKCMi4ctdTja1ng/lU8ibnkpU5NDZGaTN
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDgDCCAwagAwIBAgIQH/L8vGMmqr0oZpOZH0PsITAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0xNjAxMDcwMDAw
+MDBaFw0yNjAxMDYyMzU5NTlaMEMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3
+dGUsIEluYy4xHTAbBgNVBAMTFHRoYXd0ZSBFQ0MgRVYgU1NMIENBMFkwEwYHKoZI
+zj0CAQYIKoZIzj0DAQcDQgAEmcXM1zsNS0E2+7pcpYHdwqumr+KIIt3jEJA6jBBm
+1SoBGgZESt6OKROJBt2sZJhUl4oU0q5kINTS/bG+eYTTlqOCAZgwggGUMA4GA1Ud
+DwEB/wQEAwIBBjAuBggrBgEFBQcBAQQiMCAwHgYIKwYBBQUHMAGGEmh0dHA6Ly90
+LnN5bWNkLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMHwGA1UdIAR1MHMwBwYFZ4EM
+AQEwaAYLYIZIAYb4RQEHMAEwWTAmBggrBgEFBQcCARYaaHR0cHM6Ly93d3cudGhh
+d3RlLmNvbS9jcHMwLwYIKwYBBQUHAgIwIxohaHR0cHM6Ly93d3cudGhhd3RlLmNv
+bS9yZXBvc2l0b3J5MDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly90LnN5bWNiLmNv
+bS9UaGF3dGVQQ0EtRzIuY3JsMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
+AjArBgNVHREEJDAipCAwHjEcMBoGA1UEAxMTU1lNQy1FQ0MtQ0EtcDI1Ni0zMTAd
+BgNVHQ4EFgQUWzOvNaAaGTdCDVfmvL1rYyDClgEwHwYDVR0jBBgwFoAUmtgAMADn
+a3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaAAwZQIwMMf+C0NMBVt58Of4YvVO
+mVS0OYfzEiB4AOz8QF9pmEyaCAelGeOmq2pOLDEsQbKzAjEA2WTDVMhnnJI3NSnD
+itmCtBQnW6NEAohvLUsB4iVehDAJK3mNY8FbYafl4LjFzA4V
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag3-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,67 @@
+-----BEGIN CERTIFICATE-----
+MIIG2TCCBcGgAwIBAgIQdS+C2M35zv3l1EWcCL2MfTANBgkqhkiG9w0BAQsFADBX
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMTEwLwYDVQQDEyh0
+aGF3dGUgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTSEEyNTYgU1NMIENBMB4XDTE3MDUw
+ODAwMDAwMFoXDTE5MDUwODIzNTk1OVowgewxEzARBgsrBgEEAYI3PAIBAxMCVVMx
+GTAXBgsrBgEEAYI3PAIBAgwIRGVsYXdhcmUxFTATBgNVBAoMDFRoYXd0ZSwgSW5j
+LjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1v
+dW50YWluIFZpZXcxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYD
+VQQFEwczODk4MjYxMRcwFQYDVQQLDA5Sb290IDkgLSBWQUxJRDEfMB0GA1UEAwwW
+dmFsaWQtcm9vdDkudGhhd3RlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMGMwXWgvpsjK9b7JwFIs8Ch6EORhDfWRMk16KGdnO0jeIh1D4NRi1GL
+g0WcHiW06dFOF9UaT/Lg66mJLjHguftTHSoi9/cuMHcy0gbbWR+j+6RMxr7RwI6S
+eC8VesPWxM+5xW6bI+QBWq678ZK8JYr/cALXX+8ekDhY8vswIdzkUp7qHekkoja6
+4ki2JyJO4Q/uf/gWfohsGc88fEiMAQi3qhyZlHm7QzjeUoB0WgPC+CVB+vxSmZip
+6rkfjgPeKPlM1tqIAPjQWnQbdi2AvYCOUT0ZvVPPmsbINp7IMdAZmv9yF5qoW36A
+oFtBL3wLNe7w+lm5ZnZ15DHB2b2gDAECAwEAAaOCAwkwggMFMCEGA1UdEQQaMBiC
+FnZhbGlkLXJvb3Q5LnRoYXd0ZS5jb20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMC
+BaAwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3RmLnN5bWNiLmNvbS90Zi5jcmww
+fAYDVR0gBHUwczBoBgtghkgBhvhFAQcwATBZMCYGCCsGAQUFBwIBFhpodHRwczov
+L3d3dy50aGF3dGUuY29tL2NwczAvBggrBgEFBQcCAjAjDCFodHRwczovL3d3dy50
+aGF3dGUuY29tL3JlcG9zaXRvcnkwBwYFZ4EMAQEwHQYDVR0lBBYwFAYIKwYBBQUH
+AwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFDskyDGgt1rQarjSygd0zB4k1MTcMFcG
+CCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3RmLnN5bWNkLmNvbTAm
+BggrBgEFBQcwAoYaaHR0cDovL3RmLnN5bWNiLmNvbS90Zi5jcnQwggF/BgorBgEE
+AdZ5AgQCBIIBbwSCAWsBaQB2AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0RxM22
+7L7MAAABW+pl8UMAAAQDAEcwRQIhAMdGpN45mO8sPe9cyqC2vxeA7kwbpPL4Ie1Z
+qP8A8YSmAiB+O2TOyUyg9TE31kCYyimqMS5tycpG8qTusAi6VClvAAB2AKS5CZC0
+GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABW+pl8i4AAAQDAEcwRQIhALoI
+UwV2CIRu4MVgjNYTnVdKI6ZeklPdb9IQzEYBLI5OAiAgR+WX0RgWiOmn0Khon7ck
+QEQ0H+j9VSFAuTqxFNWzXwB3AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6
+qP3LAAABW+pl8ZMAAAQDAEgwRgIhAO/SefmFUyrtfsa1WjfN3WRG2pVSRCqaSxc7
+8pbqk7ynAiEA12r243Cr4IWKQdp6IoTqeULQZfZEGGnIUQxVG9yRzdcwDQYJKoZI
+hvcNAQELBQADggEBALcczMzw4qLLwR1hbM2qnzs+Ng4ByHPaDcwIZzGlxLCTOjZc
+AaVc8TA/MRUQBFxWto2fLmVIoFNS9EceKOx9VWcNK+9gYKkLl0K4amLTWWW+uShT
+DooJSdkP2fX2QB1jNsD1jH+44aG6Ll94HEgz88ziVeUH5T0yM3Fou1axDVI1ADKE
+Z0UsdhlTIDKcTndv3Wk6HZz2wxtvt3Z3Eenr/6TQuipGCBpfRccVRVhrpIsylVtp
+9UkD0UpX0VRgyrQOIXmtbL0WmPodfxB8crczcd6C0Yy2A77torg72fAyUtKmaBBZ
+ajj05MMBn8QmmnAZ0pXxvFTnD8MhOZ0nBccJnQM=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE0DCCA7igAwIBAgIQCkieiFN+iqZFTW4sSyrrIDANBgkqhkiG9w0BAQsFADCB
+rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
+BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0xMzA0MDkwMDAwMDBa
+Fw0yMzA0MDgyMzU5NTlaMFcxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUs
+IEluYy4xMTAvBgNVBAMTKHRoYXd0ZSBFeHRlbmRlZCBWYWxpZGF0aW9uIFNIQTI1
+NiBTU0wgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDyxLx06CX2
+AGIo40zouN8Tn4sHN+9iSvFXCfaC6HXwCqknz5M77DaJpW4d1lTzuASXcrRpJczR
+Qg5b1Rx/omBusVIa25MvuwsNZFMWyxwJJJUpIrSKGACJ/vcfcsjoXC8aG6IYuO8Y
+XMu12zpO2w+u38R54x6qXKOk5axhmzeFj0h1G7nVaJbpJ3lwVyMau2yTkMdF1xfS
+Nyp2s82CqU/AA3vhPXp+W7iF8vUV+3CpvfVQZRad47ZrYW6hep7oDRz3Ko5pfkMw
+jnjO7mUeO5uHHkkc+DJGXShGeSpOJ10XWKg3/qgTqWkV3zYiiXW6ygFALu2d1wyq
+Mc4nrlfV0lH7AgMBAAGjggE+MIIBOjASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
+DwEB/wQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9v
+Y3NwLnRoYXd0ZS5jb20wOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEW
+Gmh0dHBzOi8vd3d3LnRoYXd0ZS5jb20vY3BzMDcGA1UdHwQwMC4wLKAqoCiGJmh0
+dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVQQ0EtRzMuY3JsMCoGA1UdEQQjMCGk
+HzAdMRswGQYDVQQDExJWZXJpU2lnbk1QS0ktMi0zNzQwHQYDVR0OBBYEFDskyDGg
+t1rQarjSygd0zB4k1MTcMB8GA1UdIwQYMBaAFK1sqpRgnO3k//o+CnQrYwP3tlm/
+MA0GCSqGSIb3DQEBCwUAA4IBAQBomCaq1DPJunVw1J9JrdbBVNzuqlYfeKfwoaTu
+C/kSr9+muO7DyzUTalkq+MnpTC+8sbwrwgIw4cO+wvCBjJl3iVgAo8x/owJMU7Ju
+Nk/+34d2sz/sWmJQtgBFWPKHrHfm0CBQY8XksnAVGJAFe3uvK0a+a04fU/yEJ66D
+0o1HU6cOH2O1utsW2GoJJVV9jz1KwYP5s7mnBFrI8xEEkVMw2VKHyzkAnOxTwwIJ
+fqc2jnIhLyO7TMZHpaHuZ8QvXDpHOGHiwx43kp7IL2v679LDzSmNmPhSF+21Uzzf
+r8kbYq3fAu5dNPZBS8vDVa+xy9qcc9UCqC2nrPzh5QfQUeg1
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g3ca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,71 @@
+-----BEGIN CERTIFICATE-----
+MIIHIDCCBgigAwIBAgIQS0wGL8U0T0yVa8wAE4DBqjANBgkqhkiG9w0BAQsFADB+
+MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
+BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj
+IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE3MDUwMTAwMDAwMFoX
+DTIwMDQzMDIzNTk1OVowgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
+bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR0wGwYDVQQKDBRTeW1hbnRlYyBD
+b3Jwb3JhdGlvbjEXMBUGA1UECwwOUm9vdCA0IC0gVkFMSUQxLTArBgNVBAMMJHZh
+bGlkLXJvb3Q0LndlYnNlY3VyaXR5LnN5bWFudGVjLmNvbTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALll3Mb7Fu0CAWPMWpSbr6RHdAl10hwmMaDr8ENk
+hAv3offJxsUmgS+vqCC+xQNiS5ClDeOLyf5QeltArLuaYNjUaXEy00EEuXFQO5kj
+HjTdsWeEkOxzmt2thAJx8eMbskvvtqnHHali2LFIOuMXuyS9mpkk7cG1yk85LvgZ
+Ov1xrpBCuB+ppir0MhhXRLmcZ9QMgVUzfjrmQoQWHE0Qu69Mci6mk7fuBboqaPe0
+v0s2KsA1tLSknn39HrXE3d5D1AOoLJP1RiHU+RFQIOJ0oiXPZSH0bdiWhO0xcyuo
+vXY+0vaQPO1Uwrj/VdpL7bs65dgdFqXpTdqvMURu5WoDumUCAwEAAaOCA3QwggNw
+MC8GA1UdEQQoMCaCJHZhbGlkLXJvb3Q0LndlYnNlY3VyaXR5LnN5bWFudGVjLmNv
+bTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD
+AQYIKwYBBQUHAwIwYQYDVR0gBFowWDBWBgZngQwBAgIwTDAjBggrBgEFBQcCARYX
+aHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGQwXaHR0cHM6Ly9k
+LnN5bWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUX2DPYZBV34RDFIpgKrL1evRDGO8w
+KwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NzLnN5bWNiLmNvbS9zcy5jcmwwVwYI
+KwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc3Muc3ltY2QuY29tMCYG
+CCsGAQUFBzAChhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNydDCCAfcGCisGAQQB
+1nkCBAIEggHnBIIB4wHhAHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbs
+vswAAAFbxYEdRwAABAMARzBFAiEAurXvGE124ya7O5ZjYZckdJ7OU64A4fEAszhI
+UG3OqMACIGbAqoQLGMr9sMYBqS3cPxtD6EIK8BXzBaYHOe3pGhcXAHYApLkJkLQY
+WBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFbxYEdagAABAMARzBFAiBY4mXZ
+w8zBWrVURFxwmQGf046/oaidgJQ3Wf9+AlJ+7AIhANWkGBd6nlwE8V/dzQvkjnTz
+2edJKGy2NqgyxinZMAbWAHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo
+/csAAAFbxYEfSwAABAMASDBGAiEAltQbZJ9+Gt1M+YV4YBJVR63aPhk1dFIyKdQL
+yjYdBh0CIQDUGxHmR2KVW8N6wHnAGFlUhcwlBJFoiTqaSRP/1Yk0wAB2ALx44d/F
+9jxoRkkzTaEPoV8JeWkgCcCBtPP2kX8+2bilAAABW8WBHkcAAAQDAEcwRQIgFqqM
+DTAo3RKfwU9gwkD53Zr1HXPJuoI/MhwHQgc8nvkCIQDbwhd3gOdRJhtMyGqxGqr7
+sbD43D/fkyH3BNWOhff04TANBgkqhkiG9w0BAQsFAAOCAQEAQkWtNshWRmFY1t1Y
+pH3Ztxd891f4VYLtBzrpapejHIe5ijlZES2d+x4+aCilVUo6sDs0RUgy5Jk9eU5I
+6vOh+NkZ1THFqod+w5FKPgDaDuHHryvRaiGdcpn9x5R7zkpgKQ1WqgvcbzAmZkAr
+YxpvXfTLhcgbQhPedxbS5YyU1y1QCi8MUrxTwejcFDhAQXGOW3cTMpGsXtRvQVE0
+iI93jCPb3Djpqus9SS7ggzkfJe3bQpl72bv2agn5peBJa0sC1PqRXIT/cWUQe9ez
+rKSDoqdPNjTmIcJjql50T+WceNF5nxNPCq+jhMOcmKXJUF3H6yYc8pjLuDDBAFFz
+uxAuxw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFFTCCA/2gAwIBAgIQKC4nkXkzkuQo8iGnTsk3rjANBgkqhkiG9w0BAQsFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzMwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw
+CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
+BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs
+YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb
+A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW
+9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu
+s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T
+L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK
+Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBQDCCATwwHQYDVR0O
+BBYEFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMBIGA1UdEwEB/wQIMAYBAf8CAQAwawYD
+VR0gBGQwYjBgBgpghkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cu
+c3ltYXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0
+aC5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9w
+Y2EzLWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAYBgNV
+BAMTEVN5bWFudGVjUEtJLTEtNTM0MC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcw
+AYYSaHR0cDovL3Muc3ltY2QuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBbF1K+1lZ7
+9Pc0CUuWysf2IdBpgO/nmhnoJOJ/2S9h3RPrWmXk4WqQy04q6YoW51KN9kMbRwUN
+gKOomv4p07wdKNWlStRxPA91xQtzPwBIZXkNq2oeJQzAAt5mrL1LBmuaV4oqgX5n
+m7pSYHPEFfe7wVDJCKW6V0o6GxBzHOF7tpQDS65RsIJAOloknO4NWF2uuil6yjOe
+soHCL47BJ89A8AShP/U3wsr8rFNtqVNpT+F2ZAwlgak3A/I5czTSwXx4GByoaxbn
+5+CdKa/Y5Gk5eZVpuXtcXQGc1PfzSEUTZJXXCm5y2kMiJG8+WnDcwJLgLeVX+OQr
+J+71/xuzAYN6
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g4ca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,56 @@
+-----BEGIN CERTIFICATE-----
+MIIFxDCCBWmgAwIBAgIQZMjAlhAdRd/Im/aYbmgO8DAKBggqhkjOPQQDAjCBizEL
+MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
+VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTwwOgYDVQQDEzNTeW1hbnRlYyBD
+bGFzcyAzIEVDQyAyNTYgYml0IEV4dGVuZGVkIFZhbGlkYXRpb24gQ0EwHhcNMTcw
+NTAxMDAwMDAwWhcNMTkwNTAxMjM1OTU5WjCCAS0xEzARBgsrBgEEAYI3PAIBAxMC
+VVMxGTAXBgsrBgEEAYI3PAIBAgwIRGVsYXdhcmUxHTAbBgNVBA8TFFByaXZhdGUg
+T3JnYW5pemF0aW9uMRAwDgYDVQQFEwcyMTU4MTEzMQswCQYDVQQGEwJVUzEOMAwG
+A1UEEQwFOTQwNDMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50
+YWluIFZpZXcxGTAXBgNVBAkMEDM1MCBFbGxpcyBTdHJlZXQxHTAbBgNVBAoMFFN5
+bWFudGVjIENvcnBvcmF0aW9uMRcwFQYDVQQLDA5Sb290IDMgLSBWQUxJRDEtMCsG
+A1UEAwwkdmFsaWQtcm9vdDMud2Vic2VjdXJpdHkuc3ltYW50ZWMuY29tMFkwEwYH
+KoZIzj0CAQYIKoZIzj0DAQcDQgAERAIBieoafYh/yFaVSP+vyzoxzZ/zKy4tx7o0
+R1gugD5SArEcRar0oodVQ99eJkT63Xn910gGKx4cP+CM+jZfJqOCAwgwggMEMC8G
+A1UdEQQoMCaCJHZhbGlkLXJvb3QzLndlYnNlY3VyaXR5LnN5bWFudGVjLmNvbTAJ
+BgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
+KwYBBQUHAwIwbwYDVR0gBGgwZjBbBgtghkgBhvhFAQcXBjBMMCMGCCsGAQUFBwIB
+FhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZDBdodHRwczov
+L2Quc3ltY2IuY29tL3JwYTAHBgVngQwBATAfBgNVHSMEGDAWgBRIE2UXlOyeFioq
+dFzoUy20+4PrjjArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc24uc3ltY2IuY29t
+L3NuLmNybDBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zbi5z
+eW1jZC5jb20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zbi5zeW1jYi5jb20vc24uY3J0
+MIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgDd6x0reg1PpiCLga2BaHB+Lo6d
+AdVciI09EcTNtuy+zAAAAVvFgWTjAAAEAwBHMEUCIF7mhfWFvkMauS0jlQz7t/fO
+nDXX+VeHwI7YIHU3Wvg5AiEA97a9fZzAjALA1VTaXOv/WSDyEzA/X9YPesI4Aq+4
+da8AdQCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVvFgWUIAAAE
+AwBGMEQCIAM5H16X3/vPGds9N8b7Q3+H8cFe7woTT9ddKPfUyLZJAiAF8FivrVBd
+wJ5rjxxJOwPSrlkRV2vhbKfSbJH0lDq1XQB2AO5Lvbd1zmC64UJpH6vhnmajD35f
+sHLYgwDEe4l6qP3LAAABW8WBZRoAAAQDAEcwRQIgRpro/bdvZbK5eW5FTbTqGUTi
+W5RSpjcFW2Gd27Ql6bACIQCgow7825ZtJ31KRYJ2fiTlqvc6jyZ+u67hFT4qs/1Q
+oDAKBggqhkjOPQQDAgNJADBGAiEAl565i7SXROFdn7y+hM0AgChi/75FGmaokJaj
+h9jhmiMCIQCqIZZ4SuOgBbkt7bMOSI1sOtFqhlsGVXwZKjzSaIFSYA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIID4zCCA2qgAwIBAgIQTZVdIK+FxJ9pJfurfGZfiTAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMTIxMjIwMDAwMDAwWhcNMjIxMjE5MjM1OTU5WjCBizELMAkG
+A1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQL
+ExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTwwOgYDVQQDEzNTeW1hbnRlYyBDbGFz
+cyAzIEVDQyAyNTYgYml0IEV4dGVuZGVkIFZhbGlkYXRpb24gQ0EwWTATBgcqhkjO
+PQIBBggqhkjOPQMBBwNCAATdBD2y8pCTl8bpu7yR21Hwo4bt+8bThZMyBUngBINh
+llH/VyGuC9oO5wShf9sqHL3KmDXFcXNAzehqq1SEQybio4IBbTCCAWkwEgYDVR0T
+AQH/BAgwBgEB/wIBADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLndzLnN5
+bWFudGVjLmNvbS9wY2EzLWc0LmNybDAOBgNVHQ8BAf8EBAMCAQYwNwYIKwYBBQUH
+AQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC53cy5zeW1hbnRlYy5jb20w
+ZQYDVR0gBF4wXDBaBgRVHSAAMFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3lt
+YXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5j
+b20vcnBhMCoGA1UdEQQjMCGkHzAdMRswGQYDVQQDExJTWU1DLUVDQy1DQS1wMjU2
+LTMwHQYDVR0OBBYEFEgTZReU7J4WKip0XOhTLbT7g+uOMB8GA1UdIwQYMBaAFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2cAMGQCMFyb7oOjdk2MLQVM
+gjS6s77Oj+jDNIH7QHfoNGxbFys7rdWno9LzZsJPsrDIdpiPvwIwT8IvzpLFqb3O
+fU7UGztmJOpOzYKvVEqI7+O/OpNjVCF9EjDSMs2ryYGwpxFDe0Vm
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,71 @@
+-----BEGIN CERTIFICATE-----
+MIIHOTCCBiGgAwIBAgIQCBmps2cB8a6CGTXUyg9ZzjANBgkqhkiG9w0BAQsFADB3
+MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
+BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVj
+IENsYXNzIDMgRVYgU1NMIENBIC0gRzMwHhcNMTcwNDI4MDAwMDAwWhcNMTkwNDI4
+MjM1OTU5WjCCAS0xEzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIB
+AgwIRGVsYXdhcmUxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYD
+VQQFEwcyMTU4MTEzMQswCQYDVQQGEwJVUzEOMAwGA1UEEQwFOTQwNDMxEzARBgNV
+BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxGTAXBgNVBAkM
+EDM1MCBFbGxpcyBTdHJlZXQxHTAbBgNVBAoMFFN5bWFudGVjIENvcnBvcmF0aW9u
+MRcwFQYDVQQLDA5Sb290IDEgLSBWQUxJRDEtMCsGA1UEAwwkdmFsaWQtcm9vdDEu
+d2Vic2VjdXJpdHkuc3ltYW50ZWMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEApbJSThUcOfpFWl6PyOeFqED399DWeBcBoAMdXkPfatQ+uJPeRryZ
+4UfC1iuQWQM6agDrMhDmnc+IiBiltbF0PVEHkQXxfR6x6TFF1doWDxVfOgl2y9Pz
+ilRgdBdGmnQsWbYqaKlCBS3aZ2jCZMUAKmQce8WNLEf8qDjQcHRT1vI2k5AW3+L0
+FccXRSFXx2wZUAh9qxa2gKxEjnUF+qy42WEgh/mXD4smbhtEf+pCUXPYuODlxOaA
+ZCy9SeBrKb5Nl3C9UzBhchONPQLUgzlk8d0M17pFLYKLfa8MvBcKRVyTk7/XXdTj
+OmW5OO7f4epmXNlN5fHnGZlA5FE/4candwIDAQABo4IDBzCCAwMwLwYDVR0RBCgw
+JoIkdmFsaWQtcm9vdDEud2Vic2VjdXJpdHkuc3ltYW50ZWMuY29tMAkGA1UdEwQC
+MAAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
+AjBvBgNVHSAEaDBmMFsGC2CGSAGG+EUBBxcGMEwwIwYIKwYBBQUHAgEWF2h0dHBz
+Oi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkMF2h0dHBzOi8vZC5zeW1j
+Yi5jb20vcnBhMAcGBWeBDAEBMB8GA1UdIwQYMBaAFAFZq+fdOgtZpmRj1s8gB1fV
+kedqMCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9zci5zeW1jYi5jb20vc3IuY3Js
+MFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3NyLnN5bWNkLmNv
+bTAmBggrBgEFBQcwAoYaaHR0cDovL3NyLnN5bWNiLmNvbS9zci5jcnQwggF8Bgor
+BgEEAdZ5AgQCBIIBbASCAWgBZgB2AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0R
+xM227L7MAAABW7a3ZxAAAAQDAEcwRQIgeoFObGH+PGc5LRj+f1yzoG3TGHrPQA/z
+nRsNG1MXNXACIQCVd5wZWbP1+hp4kaE1sYgUnSiRFN3kfMf5uUQysYvkSwB1AKS5
+CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABW7a3Z1AAAAQDAEYwRAIg
+MRBDGE2dq1xzPDJ9tKzDTwKP5rC4DrjHZbmtYiZZh3sCIDCMlTV8bpEeeq2evzna
+Xq/930hOaclzf4pXEwUHmW/HAHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7
+iXqo/csAAAFbtrdpDwAABAMARjBEAiBQpNfvWoFAkIraeupW8zM804c8XvlLIbX4
+6kCYS04HbQIgOmEunrjYREwtG5Rdk1Vd01Fp7lR42AgJ/LQFn7DmXigwDQYJKoZI
+hvcNAQELBQADggEBAKlkTQil8u0sfwLdpfFmtUvFexhx4C8gTsZwZeN/40n+S4xR
+b6U3rEHIKlFAelipc5EzeYIsJKHGP5qHSs7m7jPKBrf0KsoryvZrSfhMfXDHvrJF
+RpF0Rs1VODoK2l/1CosUZ9rTqEjQcv7kUvFvgZpNIoV++k/Y2TsoBsLliRdXKpL8
+SQADr18BlEt1Y8A7E77lJFMmgD4bFN1jJWkEJoAGkrYqsF6i8fAHiESjSLy85Bcs
+DGXgP4z8Nifje78wGVygI/4NYgYiFClsk8epBHXOveEV5HRO42XzPG0Zn0BMWCSI
+0P08Lq3dwSQSQarkID6iRuhgt4GZvm3zh6MdfrA=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFKzCCBBOgAwIBAgIQfuFKb2/v8tN/P61lTTratDANBgkqhkiG9w0BAQsFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB3MQsw
+CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
+BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVjIENs
+YXNzIDMgRVYgU1NMIENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDYoWV0I+grZOIy1zM3PY71NBZI3U9/hxz4RCMTjvsR2ERaGHGOYBYmkpv9
+FwvhcXBC/r/6HMCqo6e1cej/GIP23xAKE2LIPZyn3i4/DNkd5y77Ks7Imn+Hv9hM
+BBUyydHMlXGgTihPhNk1++OGb5RT5nKKY2cuvmn2926OnGAE6yn6xEdC0niY4+wL
+pZLct5q9gGQrOHw4CVtm9i2VeoayNC6FnpAOX7ddpFFyRnATv2fytqdNFB5suVPu
+IxpOjUhVQ0GxiXVqQCjFfd3SbtICGS97JJRL6/EaqZvjI5rq+jOrCiy39GAI3Z8c
+zd0tAWaAr7MvKR0juIrhoXAHDDQPAgMBAAGjggFdMIIBWTAvBggrBgEFBQcBAQQj
+MCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wEgYDVR0TAQH/BAgw
+BgEB/wIBADBlBgNVHSAEXjBcMFoGBFUdIAAwUjAmBggrBgEFBQcCARYaaHR0cDov
+L3d3dy5zeW1hdXRoLmNvbS9jcHMwKAYIKwYBBQUHAgIwHBoaaHR0cDovL3d3dy5z
+eW1hdXRoLmNvbS9ycGEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3MxLnN5bWNi
+LmNvbS9wY2EzLWc1LmNybDAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwx
+GjAYBgNVBAMTEVN5bWFudGVjUEtJLTEtNTMzMB0GA1UdDgQWBBQBWavn3ToLWaZk
+Y9bPIAdX1ZHnajAfBgNVHSMEGDAWgBR/02Wnwt3su/AwCfNDOfoCrzMxMzANBgkq
+hkiG9w0BAQsFAAOCAQEAQgFVe9AWGl1Y6LubqE3X89frE5SG1n8hC0e8V5uSXU8F
+nzikEHzPg74GQ0aNCLxq1xCm+quvL2GoY/Jl339MiBKIT7Np2f8nwAqXkY9W+4nE
+qLuSLRtzsMarNvSWbCAI7woeZiRFT2cAQMgHVHQzO6atuyOfZu2iRHA0+w7qAf3P
+eHTfp61Vt19N9tY/4IbOJMdCqRMURDVLtt/JYKwMf9mTIUvunORJApjTYHtcvNUw
+LwfORELEC5n+5p/8sHiGUW3RLJ3GlvuFgrsEL/digO9i2n/2DqyQuFa9eT/ygG6j
+2bkPXToHHZGThkspTOHcteHgM52zyzaRS/6htO7w+Q==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-codesigning-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,170 @@
+Signer #1:
+
+Signature:
+
+Certificate owner: CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US
+
+-----BEGIN CERTIFICATE-----
+MIIE4DCCA8igAwIBAgIQMJBKmqOhTgIuAsUw5l33hTANBgkqhkiG9w0BAQsFADB/
+MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
+BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxMDAuBgNVBAMTJ1N5bWFudGVj
+IENsYXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQTAeFw0xNzEyMjEwMDAwMDBa
+Fw0yMDAyMDEyMzU5NTlaMIGWMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv
+cm5pYTEVMBMGA1UEBwwMUmVkd29vZCBDaXR5MR0wGwYDVQQKDBRPcmFjbGUgQW1l
+cmljYSwgSW5jLjEdMBsGA1UECwwUU29mdHdhcmUgRW5naW5lZXJpbmcxHTAbBgNV
+BAMMFE9yYWNsZSBBbWVyaWNhLCBJbmMuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxrxa5UAMwofgt7m++glHqMSYP3nlTDxRnWu14FtVtQiaacn20u3w
+T5d+5mkoezHXNU3g1sgwkr/Ovf4YVSwz9wtqZWTbK3/r6Ctb9eRxb2th64N4AuDI
+R9C/LU2J7ruXsu7FpEhXMIdNLxR4ihfkBA5ndpNqmXmIG9HvFQkd8APsSFRpMQh7
+Com1YlbkySgMyjBwYfAw74bqNrClBmLNAVfq7JSqjJ8EJtlq6lEJWHXEYysZfRIf
+StxZ0XtKD3wtADeowBHs1DRnXrkgD/q3kWX5LF75nfHtRWEtHxWKk7/R452pweIv
+ZZYXsvSrRA3vC+jbbhtZiRYRk2QCXsUxrQIDAQABo4IBPjCCATowCQYDVR0TBAIw
+ADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwYQYDVR0gBFow
+WDBWBgZngQwBBAEwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9j
+cHMwJQYIKwYBBQUHAgIwGQwXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwHwYDVR0j
+BBgwFoAUljtT8Hkzl699g+8uK8zKt4YecmYwKwYDVR0fBCQwIjAgoB6gHIYaaHR0
+cDovL3N2LnN5bWNiLmNvbS9zdi5jcmwwVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUF
+BzABhhNodHRwOi8vc3Yuc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vc3Yu
+c3ltY2IuY29tL3N2LmNydDANBgkqhkiG9w0BAQsFAAOCAQEAQcZqmjMAuBgnaQZ5
+JsP3+Rzaa5FrukVVk2brqrJFnqt/79khvfCf95pBafHHCqdndB0T4xuzBL4fk2ZW
+Z48ACgq3U6oNP9Ci4pcDuTqU/vZHwh7ICkSWLhGzpErfwby7zZV9ZeIK0AB5vJCK
+qgL4DetXgqGOm29gAjTKcXa67jP9lX6tAdh9TcQDbBbGny3NHGAiCderJxTOYhid
+9+4v+p+lt2OPxlxmZMPnT/9U2Yp3OzH//OYgQysnwy/UkSVCa2DuMPbL4LTxwV65
+nwEU3jT0Iq7io+oEcjW5FTZDgVC2A7lDVVrNlbAW/f5QoKcmyw8hDLo7TH6tDv8n
+hhKFDg==
+-----END CERTIFICATE-----
+
+Certificate owner: CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US
+
+-----BEGIN CERTIFICATE-----
+MIIFWTCCBEGgAwIBAgIQPXjX+XZJYLJhffTwHsqGKjANBgkqhkiG9w0BAQsFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMTMxMjEwMDAwMDAwWhcNMjMxMjA5MjM1OTU5WjB/MQsw
+CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
+BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxMDAuBgNVBAMTJ1N5bWFudGVjIENs
+YXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAJeDHgAWryyx0gjE12iTUWAecfbiR7TbWE0jYmq0v1obUfej
+DRh3aLvYNqsvIVDanvPnXydOC8KXyAlwk6naXA1OpA2RoLTsFM6RclQuzqPbROlS
+Gz9BPMpK5KrA6DmrU8wh0MzPf5vmwsxYaoIV7j02zxzFlwckjvF7vjEtPW7ctZlC
+n0thlV8ccO4XfduL5WGJeMdoG68ReBqYrsRVR1PZszLWoQ5GQMWXkorRU6eZW4U1
+V9Pqk2JhIArHMHckEU1ig7a6e2iCMe5lyt/51Y2yNdyMK29qclxghJzyDJRewFZS
+AEjM0/ilfd4v1xPkOKiE1Ua4E4bCG53qWjjdm9sCAwEAAaOCAYMwggF/MC8GCCsG
+AQUFBwEBBCMwITAfBggrBgEFBQcwAYYTaHR0cDovL3MyLnN5bWNiLmNvbTASBgNV
+HRMBAf8ECDAGAQH/AgEAMGwGA1UdIARlMGMwYQYLYIZIAYb4RQEHFwMwUjAmBggr
+BgEFBQcCARYaaHR0cDovL3d3dy5zeW1hdXRoLmNvbS9jcHMwKAYIKwYBBQUHAgIw
+HBoaaHR0cDovL3d3dy5zeW1hdXRoLmNvbS9ycGEwMAYDVR0fBCkwJzAloCOgIYYf
+aHR0cDovL3MxLnN5bWNiLmNvbS9wY2EzLWc1LmNybDAdBgNVHSUEFjAUBggrBgEF
+BQcDAgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRow
+GAYDVQQDExFTeW1hbnRlY1BLSS0xLTU2NzAdBgNVHQ4EFgQUljtT8Hkzl699g+8u
+K8zKt4YecmYwHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwDQYJKoZI
+hvcNAQELBQADggEBABOFGh5pqTf3oL2kr34dYVP+nYxeDKZ1HngXI9397BoDVTn7
+cZXHZVqnjjDSRFph23Bv2iEFwi5zuknx0ZP+XcnNXgPgiZ4/dB7X9ziLqdbPuzUv
+M1ioklbRyE07guZ5hBb8KLCxR/Mdoj7uh9mmf6RWpT+thC4p3ny8qKqjPQQB6rqT
+og5QIikXTIfkOhFf1qQliZsFay+0yQFMJ3sLrBkFIqBgFT/ayftNTI/7cmd3/SeU
+x7o1DohJ/o39KK9KEr0Ns5cF3kQMFfo2KwPcwVAB8aERXRTl4r0nS1S+K4ReD6bD
+dAUK75fDiSKxH3fzvc1D1PFMqT+1i4SvZPLQFCE=
+-----END CERTIFICATE-----
+
+Certificate owner: CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
+
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+Timestamp:
+
+Certificate owner: CN=Symantec SHA256 TimeStamping Signer - G2, OU=Symantec Trust Network, O=Symantec Corporation, C=US
+
+-----BEGIN CERTIFICATE-----
+MIIFSzCCBDOgAwIBAgIQVFjyqtdB1kS8hKl7oJZS5jANBgkqhkiG9w0BAQsFADB3
+MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
+BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVj
+IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMTcwMTAyMDAwMDAwWhcNMjgwNDAx
+MjM1OTU5WjCBgDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBv
+cmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQD
+EyhTeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIFNpZ25lciAtIEcyMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmfP82AQJA4b511ymk8BCfOp8Y89d
+AOKO88CQ348p9RjqlLeS5dewoHOB6OkKm0p8Af+dj6Q5pw7qRfQiDDpw7TlFi+TF
+G1zwRWhGJAVjdpsc/J5sKrFW5Yp/UnGu8jXVRiMGHM9ILR20zbjZdiOOHP8+v7sG
+XGkHpmUO+F6ufS7tTa4178nXAEL9KJUOn11yQgm8w9pE0u3MR4Tk/MotrFi+rveu
+2UQNCLfCd9YaQ3DRbgPeUpLEEAhx2boiVfIfvO2bnTviXh1Mg/+XD3sL51WDTtIN
+677X7K5uR7mf36XWUbwEVe3/J3BMye0qSxPhsblMD8kB7lVlX2kCeGbLPwIDAQAB
+o4IBxzCCAcMwDAYDVR0TAQH/BAIwADBmBgNVHSAEXzBdMFsGC2CGSAGG+EUBBxcD
+MEwwIwYIKwYBBQUHAgEWF2h0dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUF
+BwICMBkaF2h0dHBzOi8vZC5zeW1jYi5jb20vcnBhMEAGA1UdHwQ5MDcwNaAzoDGG
+L2h0dHA6Ly90cy1jcmwud3Muc3ltYW50ZWMuY29tL3NoYTI1Ni10c3MtY2EuY3Js
+MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDB3BggrBgEF
+BQcBAQRrMGkwKgYIKwYBBQUHMAGGHmh0dHA6Ly90cy1vY3NwLndzLnN5bWFudGVj
+LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL3RzLWFpYS53cy5zeW1hbnRlYy5jb20v
+c2hhMjU2LXRzcy1jYS5jZXIwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVT
+dGFtcC0yMDQ4LTUwHQYDVR0OBBYEFAm1wf6WcpcpQ5rJ4AK6rvj9L7r2MB8GA1Ud
+IwQYMBaAFK9j1sqjToVy4Ke8QfMpojh/gHViMA0GCSqGSIb3DQEBCwUAA4IBAQAX
+swqI6VxaXiBrOwoVsmzFqYoyh9Ox9BxTroW+P5v/17y3lIW0x1J+lOi97WGy1KeZ
+5MPJk8E1PQvoaApdVpi9sSI70UR617/wbVEyitUj3zgBN/biUyt6KxGPt01sejMD
+G3xrCZQXu+TbWNQhE2Xn7NElyix1mpx//Mm7KmirxH20z6PJbKfZxACciQp3kfRN
+ovsxO4Zu9uYfUAOGm7/LQqvmdptyWhEBisbvpW+V592uuuYiZfAYWRsRyc2At9iX
+Rx9CCPiscR+wRlOz1LLVo6tQdUgSF4Ktz+BBTzJ+zZUcv5GKCD2kp2cClt8kTKXQ
+QcCCYKOKFzJL07zPpLSM
+-----END CERTIFICATE-----
+
+Certificate owner: CN=Symantec SHA256 TimeStamping CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US
+
+-----BEGIN CERTIFICATE-----
+MIIFODCCBCCgAwIBAgIQewWx1EloUUT3yYnSnBmdEjANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0xNjAxMTIwMDAwMDBaFw0zMTAxMTEyMzU5NTlaMHcxCzAJBgNVBAYTAlVTMR0w
+GwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMg
+VHJ1c3QgTmV0d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgU0hBMjU2IFRpbWVTdGFt
+cGluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALtZnVlVT52M
+cl0agaLrVfOwAa08cawyjwVrhponADKXak3JZBRLKbvC2Sm5Luxjs+HPPwtWkPhi
+G37rpgfi3n9ebUA41JEG50F8eRzLy60bv9iVkfPw7mz4rZY5Ln/BJ7h4OcWEpe3t
+r4eOzo3HberSmLU6Hx45ncP0mqj0hOHE0XxxxgYptD/kgw0mw3sIPk35CrczSf/K
+O9T1sptL4YiZGvXA6TMU1t/HgNuR7v68kldyd/TNqMz+CfWTN76ViGrF3PSxS9TO
+6AmRX7WEeTWKeKwZMo8jwTJBG1kOqT6xzPnWK++32OTVHW0ROpL2k8mc40juu1MO
+1DaXhnjFoTcCAwEAAaOCAXcwggFzMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8E
+CDAGAQH/AgEAMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEHFwMwTDAjBggrBgEFBQcC
+ARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6
+Ly9kLnN5bWNiLmNvbS9ycGEwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJo
+dHRwOi8vcy5zeW1jZC5jb20wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL3Muc3lt
+Y2IuY29tL3VuaXZlcnNhbC1yb290LmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAo
+BgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMzAdBgNVHQ4E
+FgQUr2PWyqNOhXLgp7xB8ymiOH+AdWIwHwYDVR0jBBgwFoAUtnf6aUhHn1MS1cLq
+BzJ2B9GXBxkwDQYJKoZIhvcNAQELBQADggEBAHXqsC3VNBlcMkX+DuHUT6Z4wW/X
+6t3cT/OhyIGI96ePFeZAKa3mXfSi2VZkhHEwKt0eYRdmIFYGmBmNXXHy+Je8Cf0c
+kUfJ4uiNA/vMkC/WCmxOM+zWtJPITJBjSDlAIcTd1m6JmDy1mJfoqQa3CcmPU1dB
+kC/hHk1O3MoQeGxCbvC2xfhhXFL1TvZrjfdKer7zzf0D19n2A6gP41P3CnXsxnUu
+qmaFBJm3+AZX4cYO9uiv2uybGB+queM6AL/OipTLAduexzi7D1Kr0eOUA2AKTaD+
+J20UMvw/l0Dhv5mJ2+Q5FL3a5NPD6itas5VYVQR9x5rsIwONhSrS/66pYYE=
+-----END CERTIFICATE-----
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignuniversalrootca-chain.pem	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,73 @@
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBjegAwIBAgIQPYH1xfKSpwYMrTEqOxG4OzANBgkqhkiG9w0BAQsFADCB
+ijELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w
+HQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTswOQYDVQQDEzJTeW1hbnRl
+YyBDbGFzcyAzIEV4dGVuZGVkIFZhbGlkYXRpb24gU0hBMjU2IFNTTCBDQTAeFw0x
+NzA1MDEwMDAwMDBaFw0xOTA1MDEyMzU5NTlaMIIBLTETMBEGCysGAQQBgjc8AgED
+EwJVUzEZMBcGCysGAQQBgjc8AgECDAhEZWxhd2FyZTEdMBsGA1UEDxMUUHJpdmF0
+ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzIxNTgxMTMxCzAJBgNVBAYTAlVTMQ4w
+DAYDVQQRDAU5NDA0MzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEZMBcGA1UECQwQMzUwIEVsbGlzIFN0cmVldDEdMBsGA1UECgwU
+U3ltYW50ZWMgQ29ycG9yYXRpb24xFzAVBgNVBAsMDlJvb3QgMiAtIFZBTElEMS0w
+KwYDVQQDDCR2YWxpZC1yb290Mi53ZWJzZWN1cml0eS5zeW1hbnRlYy5jb20wggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjQDZuIKKgrjmO0+0ty8WIlFZk
+HcvIGX/kIAxByd/XA19h0Zk6kjFLgZaRtsUdRotG40DST72Ki8Vmy7nX3w/cqpFg
+0x0nl7ZORE/L1EjEOUApqEpaA5GtcMaznu/SVVp2mZgoOWhn4EAvocT6GKQWaKi1
+/tCh6UiieHRz6L29CrN6/JWT6OXv6TGePkGcVKSjJrZoNMiNzoTFyCdvVpYutZiv
+YsMzcRJ+KxTepwFM1imssBGc5WM2Wit+Z3kWJhYe0IdOIdqmuR6WxwLGb7nrY44R
+dPy+h0n71GJvjbEzI+Qb/ehc8HjOGba0sh/+x/p14t7PplDZyicxzaC/tpTnAgMB
+AAGjggMJMIIDBTAvBgNVHREEKDAmgiR2YWxpZC1yb290Mi53ZWJzZWN1cml0eS5z
+eW1hbnRlYy5jb20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMG8GA1UdIARoMGYwWwYLYIZIAYb4RQEHFwYw
+TDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUH
+AgIwGQwXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwBwYFZ4EMAQEwHwYDVR0jBBgw
+FoAUsm3j5BQPjDxzQqZamRrTFHW2htswKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDov
+L3NoLnN5bWNiLmNvbS9zaC5jcmwwVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzAB
+hhNodHRwOi8vc2guc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vc2guc3lt
+Y2IuY29tL3NoLmNydDCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA3esdK3oN
+T6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFbxYHx8wAABAMARzBFAiEAoZAV
+7qASZQXq7visy9vw4552zDWP/+K/8FmgvPpFHuACICl4k+7Omje9NoIRTwnPs4fm
+fqW4rDXzK+HKIGNfEmQ4AHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN
+3BAAAAFbxYHyLgAABAMARzBFAiAuvBGEqgabzmMmG2Tzv1KjGR0nTtEz1R1XluNc
+w8NrnAIhAOBL9OgiJfN4SRq6Gmfesx8BJGFr7pDfpDKECGOT1uqZAHYA7ku9t3XO
+YLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFbxYHz8gAABAMARzBFAiEA2/T1
+kmfJQ/F0SrRDPozVMhaQW/ydrynOQovjsNJM3M0CIEN0T1ac8FsiatIVoxv690J3
+sIfanWlSX7UvPVShVGg2MA0GCSqGSIb3DQEBCwUAA4IBAQB4unTd5lxCGKsEyViE
+m1AZpxTwISBdxuixpXoskuHwCw5LApp8WbaO0W4h4ZLfL+P2cAKx7awvfsaLKQ0i
+tnmhyCZitwI9cfmRs8wwU3WgVH/CiIWv96R9mqA8AQ0pMRUp240idzd/VkLYc2RL
+CFECQOdsgflyp95PqWyFD1aGdMmwCW5nFUYkbA18cJER5VG9nquBNROzM14z73Wa
+PelMX56on9fk+KgryPQIMJFQxqwWbiszby6UaWLQ3ZDKiNwdJsmZWvQ/Gw05NTtp
+J1gOExSwrDQM0X5gxMaSxTDU7zEWQz2kjYWjdtdtiq8AtRjQ8DlqXseTpHOUB8iW
+5vWY
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFSTCCBDGgAwIBAgIQCbdJ/X8LSRbKBVZWz/bZgjANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0xMzA0MDkwMDAwMDBaFw0yMzA0MDgyMzU5NTlaMIGKMQswCQYDVQQGEwJVUzEd
+MBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVj
+IFRydXN0IE5ldHdvcmsxOzA5BgNVBAMTMlN5bWFudGVjIENsYXNzIDMgRXh0ZW5k
+ZWQgVmFsaWRhdGlvbiBTSEEyNTYgU1NMIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAwUo5gP1SVSC5FK9OwhPfSgNKsGXFaGaKJJxyi63peok7gyXs
+LFcSKSb3qHD0Y+AGVTyD8cPxY0sypzk9D/exa/G+Xxua5KoXZUbBpue3YXWKmCYZ
+HqcPo8eypoUnOQR0G8YHFiqSqOjpm8RaIIoby0YJUeSi5CGDM9UnyXvbqOF2hljp
+4b0TV2vgGq9xA7MV8EQB5WFk9fIRmVLs7ej1PRNrISfCxgPA8g/VWH/17yql/yjq
+jeWOdt8sZmSbNb9j/Z9KSJ8whT7VsvH+yESoWC6gnWC9Cs7BJQgcTfK0w+tcOLfY
+1JslzuMzFs/JL8wocPpjdNXExxEVpZnyKSLABQIDAQABo4IBdDCCAXAwNwYIKwYB
+BQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC53cy5zeW1hbnRlYy5j
+b20wEgYDVR0TAQH/BAgwBgEB/wIBADBlBgNVHSAEXjBcMFoGBFUdIAAwUjAmBggr
+BgEFBQcCARYaaHR0cDovL3d3dy5zeW1hdXRoLmNvbS9jcHMwKAYIKwYBBQUHAgIw
+HBoaaHR0cDovL3d3dy5zeW1hdXRoLmNvbS9ycGEwPgYDVR0fBDcwNTAzoDGgL4Yt
+aHR0cDovL2NybC53cy5zeW1hbnRlYy5jb20vdW5pdmVyc2FsLXJvb3QuY3JsMA4G
+A1UdDwEB/wQEAwIBBjAqBgNVHREEIzAhpB8wHTEbMBkGA1UEAxMSVmVyaVNpZ25N
+UEtJLTItMzcyMB0GA1UdDgQWBBSybePkFA+MPHNCplqZGtMUdbaG2zAfBgNVHSME
+GDAWgBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEAdJ3d
+mGjc+GgcDYkNvwlH3cWvtjX7EqazxfQGSbmJcnB0fKn1cxQh6wAW9VOsKBq0salx
+V6wBS/SYJMULRSKRRtL+1rYIRPMbgwUcFMBo34qHylbm72/zlBO0W4VPrVe68Ow7
+gOeiAV+7ZYUARJc0uNiuIW+Xva9zHMVw3Mb3x2sgh6oEYmnI9sPzpHSPG1VPKrsH
+NUZlCdqof2NXVfDrn0kVlVeqf8tER1EAWVaDHUCRLdgd0l9x7ibBbkUNxU0SP7+R
+5TYnB2qysmYrhf8nQaKSs8pOAY371fbh5FTWa8ySae7kOY6dNM4Us/CAauNW7mW0
+zB9UpGiJBN2YLL3Pow==
+-----END CERTIFICATE-----
--- a/test/jdk/sun/security/util/math/BigIntegerModuloP.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/sun/security/util/math/BigIntegerModuloP.java	Wed Dec 12 08:38:45 2018 -0500
@@ -27,6 +27,8 @@
 
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Optional;
 
 /**
  * Arithmetic in the field of integers modulo a prime value implemented using
@@ -171,6 +173,13 @@
         }
 
         @Override
+        public void conditionalSet(IntegerModuloP b, int set) {
+            if (set == 1) {
+                v = b.asBigInteger();
+            }
+        }
+
+        @Override
         public void conditionalSwapWith(MutableIntegerModuloP b, int swap) {
             if (swap == 1) {
                 BigInteger temp = v;
@@ -244,6 +253,18 @@
             return this;
         }
 
+        @Override
+        public MutableElement setAdditiveInverse() {
+            v = BigInteger.ZERO.subtract(v);
+            return this;
+        }
+
+        @Override
+        public MutableElement setReduced() {
+            // do nothing
+            return this;
+        }
+
     }
 
     private class SmallElement extends ImmutableElement implements SmallValue {
--- a/test/jdk/sun/security/util/math/TestIntegerModuloP.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/jdk/sun/security/util/math/TestIntegerModuloP.java	Wed Dec 12 08:38:45 2018 -0500
@@ -23,16 +23,23 @@
 
 /*
  * @test
- * @bug 8181594
+ * @bug 8181594 8208648
  * @summary Test proper operation of integer field arithmetic
  * @modules java.base/sun.security.util java.base/sun.security.util.math java.base/sun.security.util.math.intpoly
  * @build BigIntegerModuloP
  * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 32 0
  * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial448 56 1
  * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial1305 16 2
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP256 32 5
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP384 48 6
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP521 66 7
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P256OrderField 32 8
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P384OrderField 48 9
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P521OrderField 66 10
  */
 
 import sun.security.util.math.*;
+import sun.security.util.math.intpoly.*;
 import java.util.function.*;
 
 import java.util.*;
@@ -124,11 +131,9 @@
         } catch (Exception ex) {
             throw new RuntimeException(ex);
         }
-
         System.out.println("All tests passed");
     }
 
-
     static void assertEqual(IntegerModuloP e1, IntegerModuloP e2) {
 
         if (!e1.asBigInteger().equals(e2.asBigInteger())) {
@@ -302,6 +307,17 @@
             TestPair<IntegerModuloP> result2 =
                 applyAndCheck(addFunc2, left, right);
 
+            if (elem.test.getField() instanceof IntegerPolynomial) {
+                IntegerPolynomial field =
+                    (IntegerPolynomial) elem.test.getField();
+                int numAdds = field.getMaxAdds();
+                for (int j = 1; j < numAdds; j++) {
+                    ElemFunction addFunc3 = ADD_FUNCTIONS.
+                        get(random.nextInt(ADD_FUNCTIONS.size()));
+                    result2 = applyAndCheck(addFunc3, left, right);
+                }
+            }
+
             ElemFunction multFunc2 =
                 MULT_FUNCTIONS.get(random.nextInt(MULT_FUNCTIONS.size()));
             TestPair<MutableIntegerModuloP> multResult =
--- a/test/jdk/sun/text/IntHashtable/Bug4170614Test.sh	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#
-# @test
-# @bug 4170614
-# @summary Test internal hashCode() functions
-#
-
-set -x
-if [ "${TESTSRC}" = "" ]
-then
-  echo "TESTSRC not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTSRC=${TESTSRC}"
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTJAVA=${TESTJAVA}"
-if [ "${COMPILEJAVA}" = "" ]; then
-   COMPILEJAVA="${TESTJAVA}"
-fi
-echo "COMPILEJAVA=${COMPILEJAVA}"
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-echo "TESTCLASSES=${TESTCLASSES}"
-
-goback=`pwd`
-
-cd ${TESTSRC}
-
-TEST_JAVABASE=${TESTCLASSES}/java.base
-mkdir -p ${TEST_JAVABASE}
-${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-    --patch-module java.base=patch-src \
-    -d ${TEST_JAVABASE} patch-src/java/text/Bug4170614Test.java
-
-${TESTJAVA}/bin/java ${TESTVMOPTS} --patch-module java.base=${TEST_JAVABASE} java.text.Bug4170614Test
-
-result=$?
-
-cd ${goback}
-
-if [ $result -eq 0 ]
-then
-  echo "Passed"
-else
-  echo "Failed"
-fi
-exit $result
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/text/IntHashtable/Bug4170614TestRun.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1999, 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.
+ */
+
+/* @test
+ * @bug 4170614
+ * @summary Test internal hashCode() and equals() functions
+ * @library patch-src
+ * @build java.base/java.text.Bug4170614Test
+ * @run main java.base/java.text.Bug4170614Test
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/text/IntHashtable/patch-src/java.base/java/text/Bug4170614Test.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1999, 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.
+ */
+
+/*
+    (this test doesn't have an at-test tag because it's run by Bug4170614TestRun.java
+     instead of directly by the test harness)
+*/
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+package java.text;
+import sun.text.IntHashtable;
+
+
+/**
+ * This class tests some internal hashCode() functions.
+ * Bug #4170614 complained that we had two iternal classes that
+ * break the invariant that if a.equals(b) than a.hashCode() ==
+ * b.hashCode().  This is because these classes overrode equals()
+ * but not hashCode().  These are both purely internal classes, and
+ * the library itself doesn't actually call hashCode(), so this isn't
+ * actually causing anyone problems yet.  But if these classes are
+ * ever exposed in the API, their hashCode() methods need to work right.
+ * PatternEntry will never be exposed in the API, but IntHashtable
+ * might be.
+ * @author Richard Gillam
+ */
+public class Bug4170614Test {
+    public static void main(String[] args) throws Exception {
+        testIntHashtable();
+        testPatternEntry();
+    }
+
+
+    public static void testIntHashtable() throws Exception {
+        IntHashtable fred = new IntHashtable();
+        fred.put(1, 10);
+        fred.put(2, 20);
+        fred.put(3, 30);
+
+        IntHashtable barney = new IntHashtable();
+        barney.put(1, 10);
+        barney.put(3, 30);
+        barney.put(2, 20);
+
+        IntHashtable homer = new IntHashtable();
+        homer.put(3, 30);
+        homer.put(1, 10);
+        homer.put(7, 900);
+
+        if (fred.equals(barney)) {
+            System.out.println("fred.equals(barney)");
+        }
+        else {
+            System.out.println("!fred.equals(barney)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("barney.hashCode() == " + barney.hashCode());
+
+        if (!fred.equals(barney)) {
+            throw new Exception("equals() failed on two hashtables that are equal");
+        }
+
+        if (fred.hashCode() != barney.hashCode()) {
+           throw new Exception("hashCode() failed on two hashtables that are equal");
+        }
+
+        System.out.println();
+        if (fred.equals(homer)) {
+            System.out.println("fred.equals(homer)");
+        }
+        else {
+            System.out.println("!fred.equals(homer)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("homer.hashCode() == " + homer.hashCode());
+
+        if (fred.equals(homer)) {
+            throw new Exception("equals() failed on two hashtables that are not equal");
+        }
+
+        if (fred.hashCode() == homer.hashCode()) {
+            throw new Exception("hashCode() failed on two hashtables that are not equal");
+        }
+
+        System.out.println();
+        System.out.println("testIntHashtable() passed.\n");
+    }
+
+    public static void testPatternEntry() throws Exception {
+        PatternEntry fred = new PatternEntry(1,
+                                             new StringBuffer("hello"),
+                                             new StringBuffer("up"));
+        PatternEntry barney = new PatternEntry(1,
+                                               new StringBuffer("hello"),
+                                               new StringBuffer("down"));
+        // (equals() only considers the "chars" field, so fred and barney are equal)
+        PatternEntry homer = new PatternEntry(1,
+                                              new StringBuffer("goodbye"),
+                                              new StringBuffer("up"));
+
+        if (fred.equals(barney)) {
+            System.out.println("fred.equals(barney)");
+        }
+        else {
+            System.out.println("!fred.equals(barney)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("barney.hashCode() == " + barney.hashCode());
+
+        if (!fred.equals(barney)) {
+            throw new Exception("equals() failed on two hashtables that are equal");
+        }
+
+        if (fred.hashCode() != barney.hashCode()) {
+           throw new Exception("hashCode() failed on two hashtables that are equal");
+        }
+
+        System.out.println();
+        if (fred.equals(homer)) {
+            System.out.println("fred.equals(homer)");
+        }
+        else {
+            System.out.println("!fred.equals(homer)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("homer.hashCode() == " + homer.hashCode());
+
+        if (fred.equals(homer)) {
+            throw new Exception("equals() failed on two hashtables that are not equal");
+        }
+
+        if (fred.hashCode() == homer.hashCode()) {
+            throw new Exception("hashCode() failed on two hashtables that are not equal");
+        }
+
+        System.out.println();
+        System.out.println("testPatternEntry() passed.\n");
+    }
+}
--- a/test/jdk/sun/text/IntHashtable/patch-src/java/text/Bug4170614Test.java	Wed Dec 12 08:27:16 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 1999, 2016, 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.
- */
-
-/*
-    (this test doesn't have an at-test tag because it's run by a shell
-    script instead of directly by the test harness)
-*/
-
-/*
- *
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
- *
- * Portions copyright (c) 2007 Sun Microsystems, Inc.
- * All Rights Reserved.
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for NON-COMMERCIAL purposes and without
- * fee is hereby granted provided that this copyright notice
- * appears in all copies. Please refer to the file "copyright.html"
- * for further important copyright and licensing information.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
- * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-package java.text;
-import sun.text.IntHashtable;
-
-
-/**
- * This class tests some internal hashCode() functions.
- * Bug #4170614 complained that we had two iternal classes that
- * break the invariant that if a.equals(b) than a.hashCode() ==
- * b.hashCode().  This is because these classes overrode equals()
- * but not hashCode().  These are both purely internal classes, and
- * the library itself doesn't actually call hashCode(), so this isn't
- * actually causing anyone problems yet.  But if these classes are
- * ever exposed in the API, their hashCode() methods need to work right.
- * PatternEntry will never be exposed in the API, but IntHashtable
- * might be.  This is a shell test to allow us to access classes that
- * are declared package private.
- * @author Richard Gillam
- */
-public class Bug4170614Test {
-    public static void main(String[] args) throws Exception {
-        testIntHashtable();
-        testPatternEntry();
-    }
-
-
-    public static void testIntHashtable() throws Exception {
-        IntHashtable fred = new IntHashtable();
-        fred.put(1, 10);
-        fred.put(2, 20);
-        fred.put(3, 30);
-
-        IntHashtable barney = new IntHashtable();
-        barney.put(1, 10);
-        barney.put(3, 30);
-        barney.put(2, 20);
-
-        IntHashtable homer = new IntHashtable();
-        homer.put(3, 30);
-        homer.put(1, 10);
-        homer.put(7, 900);
-
-        if (fred.equals(barney)) {
-            System.out.println("fred.equals(barney)");
-        }
-        else {
-            System.out.println("!fred.equals(barney)");
-        }
-        System.out.println("fred.hashCode() == " + fred.hashCode());
-        System.out.println("barney.hashCode() == " + barney.hashCode());
-
-        if (!fred.equals(barney)) {
-            throw new Exception("equals() failed on two hashtables that are equal");
-        }
-
-        if (fred.hashCode() != barney.hashCode()) {
-           throw new Exception("hashCode() failed on two hashtables that are equal");
-        }
-
-        System.out.println();
-        if (fred.equals(homer)) {
-            System.out.println("fred.equals(homer)");
-        }
-        else {
-            System.out.println("!fred.equals(homer)");
-        }
-        System.out.println("fred.hashCode() == " + fred.hashCode());
-        System.out.println("homer.hashCode() == " + homer.hashCode());
-
-        if (fred.equals(homer)) {
-            throw new Exception("equals() failed on two hashtables that are not equal");
-        }
-
-        if (fred.hashCode() == homer.hashCode()) {
-            throw new Exception("hashCode() failed on two hashtables that are not equal");
-        }
-
-        System.out.println();
-        System.out.println("testIntHashtable() passed.\n");
-    }
-
-    public static void testPatternEntry() throws Exception {
-        PatternEntry fred = new PatternEntry(1,
-                                             new StringBuffer("hello"),
-                                             new StringBuffer("up"));
-        PatternEntry barney = new PatternEntry(1,
-                                               new StringBuffer("hello"),
-                                               new StringBuffer("down"));
-        // (equals() only considers the "chars" field, so fred and barney are equal)
-        PatternEntry homer = new PatternEntry(1,
-                                              new StringBuffer("goodbye"),
-                                              new StringBuffer("up"));
-
-        if (fred.equals(barney)) {
-            System.out.println("fred.equals(barney)");
-        }
-        else {
-            System.out.println("!fred.equals(barney)");
-        }
-        System.out.println("fred.hashCode() == " + fred.hashCode());
-        System.out.println("barney.hashCode() == " + barney.hashCode());
-
-        if (!fred.equals(barney)) {
-            throw new Exception("equals() failed on two hashtables that are equal");
-        }
-
-        if (fred.hashCode() != barney.hashCode()) {
-           throw new Exception("hashCode() failed on two hashtables that are equal");
-        }
-
-        System.out.println();
-        if (fred.equals(homer)) {
-            System.out.println("fred.equals(homer)");
-        }
-        else {
-            System.out.println("!fred.equals(homer)");
-        }
-        System.out.println("fred.hashCode() == " + fred.hashCode());
-        System.out.println("homer.hashCode() == " + homer.hashCode());
-
-        if (fred.equals(homer)) {
-            throw new Exception("equals() failed on two hashtables that are not equal");
-        }
-
-        if (fred.hashCode() == homer.hashCode()) {
-            throw new Exception("hashCode() failed on two hashtables that are not equal");
-        }
-
-        System.out.println();
-        System.out.println("testPatternEntry() passed.\n");
-    }
-}
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Wed Dec 12 08:38:45 2018 -0500
@@ -25,7 +25,7 @@
  * @test
  * @bug 8141492 8071982 8141636 8147890 8166175 8168965 8176794 8175218 8147881
  *      8181622 8182263 8074407 8187521 8198522 8182765 8199278 8196201 8196202
- *      8184205
+ *      8184205 8214468
  * @summary Test the search feature of javadoc.
  * @author bpatel
  * @library ../lib
@@ -646,19 +646,17 @@
                 "jquery/jszip-utils/dist/jszip-utils.min.js",
                 "jquery/jszip-utils/dist/jszip-utils-ie.js",
                 "jquery/jszip-utils/dist/jszip-utils-ie.min.js",
-                "jquery/images/ui-bg_flat_0_aaaaaa_40x100.png",
+                "jquery/images/ui-bg_glass_65_dadada_1x400.png",
                 "jquery/images/ui-icons_454545_256x240.png",
                 "jquery/images/ui-bg_glass_95_fef1ec_1x400.png",
                 "jquery/images/ui-bg_glass_75_dadada_1x400.png",
                 "jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png",
                 "jquery/images/ui-icons_888888_256x240.png",
                 "jquery/images/ui-icons_2e83ff_256x240.png",
-                "jquery/images/ui-bg_glass_65_ffffff_1x400.png",
                 "jquery/images/ui-icons_cd0a0a_256x240.png",
                 "jquery/images/ui-bg_glass_55_fbf9ee_1x400.png",
                 "jquery/images/ui-icons_222222_256x240.png",
                 "jquery/images/ui-bg_glass_75_e6e6e6_1x400.png",
-                "jquery/images/ui-bg_flat_75_ffffff_40x100.png",
                 "resources/x.png",
                 "resources/glass.png");
     }
--- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -212,19 +212,17 @@
             "jquery/jszip-utils/dist/jszip-utils.min.js",
             "jquery/jszip-utils/dist/jszip-utils-ie.js",
             "jquery/jszip-utils/dist/jszip-utils-ie.min.js",
-            "jquery/images/ui-bg_flat_0_aaaaaa_40x100.png",
+            "jquery/images/ui-bg_glass_65_dadada_1x400.png",
             "jquery/images/ui-icons_454545_256x240.png",
             "jquery/images/ui-bg_glass_95_fef1ec_1x400.png",
             "jquery/images/ui-bg_glass_75_dadada_1x400.png",
             "jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png",
             "jquery/images/ui-icons_888888_256x240.png",
             "jquery/images/ui-icons_2e83ff_256x240.png",
-            "jquery/images/ui-bg_glass_65_ffffff_1x400.png",
             "jquery/images/ui-icons_cd0a0a_256x240.png",
             "jquery/images/ui-bg_glass_55_fbf9ee_1x400.png",
             "jquery/images/ui-icons_222222_256x240.png",
             "jquery/images/ui-bg_glass_75_e6e6e6_1x400.png",
-            "jquery/images/ui-bg_flat_75_ffffff_40x100.png",
             "member-search-index.js",
             "member-search-index.zip",
             "overview-tree.html",
--- a/test/langtools/jdk/jshell/CommandCompletionTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/CommandCompletionTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, 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
@@ -170,13 +170,15 @@
                 "/edit ", "/env ", "/exit ",
                 "/help ", "/history ", "/imports ",
                 "/list ", "/methods ", "/open ", "/reload ", "/reset ",
-                "/save ", "/set ", "/types ", "/vars ", "context ", "id ", "intro ", "rerun ", "shortcuts "),
+                "/save ", "/set ", "/types ", "/vars ", "context ",
+                "id ", "intro ", "keys ", "rerun ", "shortcuts "),
                 a -> assertCompletion(a, "/? |", false,
                 "/! ", "/-<n> ", "/<id> ", "/? ", "/drop ",
                 "/edit ", "/env ", "/exit ",
                 "/help ", "/history ", "/imports ",
                 "/list ", "/methods ", "/open ", "/reload ", "/reset ",
-                "/save ", "/set ", "/types ", "/vars ", "context ", "id ", "intro ", "rerun ", "shortcuts "),
+                "/save ", "/set ", "/types ", "/vars ", "context ",
+                "id ", "intro ", "keys ", "rerun ", "shortcuts "),
                 a -> assertCompletion(a, "/help /s|", false,
                 "/save ", "/set "),
                 a -> assertCompletion(a, "/help /set |", false,
--- a/test/langtools/jdk/jshell/HistoryTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/HistoryTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -25,21 +25,24 @@
  * @test
  * @bug 8166744
  * @summary Test Completion
- * @modules jdk.internal.le/jdk.internal.jline.extra
+ * @modules jdk.internal.le/jdk.internal.org.jline.reader
  *          jdk.jshell/jdk.internal.jshell.tool:+open
  * @build HistoryTest
  * @run testng HistoryTest
  */
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.Locale;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import jdk.internal.jline.extra.EditingHistory;
+
 import org.testng.annotations.Test;
 import jdk.internal.jshell.tool.JShellTool;
 import jdk.internal.jshell.tool.JShellToolBuilder;
+import jdk.internal.org.jline.reader.History;
 import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
 
 public class HistoryTest extends ReplToolTesting {
 
@@ -68,8 +71,10 @@
              a -> {
                  if (!a) {
                      try {
-                         previousAndAssert(getHistory(), "} //test");
-                         previousSnippetAndAssert(getHistory(), "void test() {");
+                         previousAndAssert(getHistory(), "void test() {\n" +
+                                                         "    System.err.println(1);\n" +
+                                                         "    System.err.println(1);\n" +
+                                                         "} //test");
                      } catch (Exception ex) {
                          throw new IllegalStateException(ex);
                      }
@@ -82,12 +87,15 @@
              a -> {
                  if (!a) {
                      try {
-                         previousAndAssert(getHistory(), "} //test2");
-                         previousSnippetAndAssert(getHistory(), "void test2() {");
-                         previousSnippetAndAssert(getHistory(), "/debug 0"); //added by test framework
-                         previousSnippetAndAssert(getHistory(), "/exit");
-                         previousSnippetAndAssert(getHistory(), "int dummy;");
-                         previousSnippetAndAssert(getHistory(), "void test() {");
+                         previousAndAssert(getHistory(), "void test2() {\n" +
+                                                         "} //test2");
+                         previousAndAssert(getHistory(), "/debug 0"); //added by test framework
+                         previousAndAssert(getHistory(), "/exit");
+                         previousAndAssert(getHistory(), "int dummy;");
+                         previousAndAssert(getHistory(), "void test() {\n" +
+                                                         "    System.err.println(1);\n" +
+                                                         "    System.err.println(1);\n" +
+                                                         "} //test");
                      } catch (Exception ex) {
                          throw new IllegalStateException(ex);
                      }
@@ -106,11 +114,14 @@
              a -> {
                  if (!a) {
                      try {
-                         previousAndAssert(getHistory(), "}");
-                         previousAndAssert(getHistory(), "}");
-                         previousAndAssert(getHistory(), "void f() {");
-                         previousAndAssert(getHistory(), "class C {");
-                         getHistory().add("class C{");
+                         previousAndAssert(getHistory(), "class C {\n" +
+                                                         "void f() {\n" +
+                                                         "}\n" +
+                                                         "}");
+                         getHistory().add("class C {\n" +
+                                          "void f() {\n" +
+                                          "}\n" +
+                                          "}");
                      } catch (Exception ex) {
                          throw new IllegalStateException(ex);
                      }
@@ -125,8 +136,14 @@
              a -> {
                  if (!a) {
                      try {
-                         previousSnippetAndAssert(getHistory(), "class C {");
-                         getHistory().add("class C{");
+                         previousAndAssert(getHistory(), "class C {\n" +
+                                                         "void f() {\n" +
+                                                         "}\n" +
+                                                         "}");
+                         getHistory().add("class C {\n" +
+                                          "void f() {\n" +
+                                          "}\n" +
+                                          "}");
                      } catch (Exception ex) {
                          throw new IllegalStateException(ex);
                      }
@@ -135,23 +152,65 @@
              });
     }
 
-    private EditingHistory getHistory() throws Exception {
+    @Test
+    public void testReadExistingHistory() {
+        prefsMap.put("HISTORY_LINE_0", "/debug 0");
+        prefsMap.put("HISTORY_LINE_1", "void test() {\\");
+        prefsMap.put("HISTORY_LINE_2", "    System.err.println(1);\\");
+        prefsMap.put("HISTORY_LINE_3", "    System.err.println(`\\\\\\\\\\");
+        prefsMap.put("HISTORY_LINE_4", "    \\\\\\");
+        prefsMap.put("HISTORY_LINE_5", "`);\\");
+        prefsMap.put("HISTORY_LINE_6", "} //test");
+        test(
+             a -> {assertCommand(a, "int i", "i ==> 0");},
+             a -> {
+                 if (!a) {
+                     try {
+                         previousAndAssert(getHistory(), "int i");
+                         previousAndAssert(getHistory(), "/debug 0"); //added by test framework
+                         previousAndAssert(getHistory(), "void test() {\n" +
+                                                         "    System.err.println(1);\n" +
+                                                         "    System.err.println(`\\\\\n" +
+                                                         "    \\\n" +
+                                                         "`);\n" +
+                                                         "} //test");
+                     } catch (Exception ex) {
+                         throw new IllegalStateException(ex);
+                     }
+                 }
+                  assertCommand(a, "/exit", "");
+             });
+        assertEquals(prefsMap.get("HISTORY_LINE_00"), "/debug 0");
+        assertEquals(prefsMap.get("HISTORY_LINE_01"), "void test() {\\");
+        assertEquals(prefsMap.get("HISTORY_LINE_02"), "    System.err.println(1);\\");
+        assertEquals(prefsMap.get("HISTORY_LINE_03"), "    System.err.println(`\\\\\\\\\\");
+        assertEquals(prefsMap.get("HISTORY_LINE_04"), "    \\\\\\");
+        assertEquals(prefsMap.get("HISTORY_LINE_05"), "`);\\");
+        assertEquals(prefsMap.get("HISTORY_LINE_06"), "} //test");
+        assertEquals(prefsMap.get("HISTORY_LINE_07"), "/debug 0");
+        assertEquals(prefsMap.get("HISTORY_LINE_08"), "int i");
+        assertEquals(prefsMap.get("HISTORY_LINE_09"), "/exit");
+        System.err.println("prefsMap: " + prefsMap);
+    }
+
+    private History getHistory() throws Exception {
         Field input = repl.getClass().getDeclaredField("input");
         input.setAccessible(true);
         Object console = input.get(repl);
-        Field history = console.getClass().getDeclaredField("history");
-        history.setAccessible(true);
-        return (EditingHistory) history.get(console);
+        Method getHistory = console.getClass().getDeclaredMethod("getHistory");
+        getHistory.setAccessible(true);
+        return (History) getHistory.invoke(console);
     }
 
-    private void previousAndAssert(EditingHistory history, String expected) {
+    private void previousAndAssert(History history, String expected) {
         assertTrue(history.previous());
         assertEquals(history.current().toString(), expected);
     }
 
-    private void previousSnippetAndAssert(EditingHistory history, String expected) {
-        assertTrue(history.previousSnippet());
-        assertEquals(history.current().toString(), expected);
+    @BeforeMethod
+    public void setUp() {
+        super.setUp();
+        System.setProperty("jshell.test.allow.incomplete.inputs", "false");
     }
 
 }
--- a/test/langtools/jdk/jshell/HistoryUITest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/HistoryUITest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -33,7 +33,7 @@
  * @library /tools/lib
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
  * @build Compiler UITesting
- * @build HistoryUITest
+ * @compile HistoryUITest.java
  * @run testng HistoryUITest
  */
 
@@ -42,43 +42,39 @@
 @Test
 public class HistoryUITest extends UITesting {
 
+    public HistoryUITest() {
+        super(true);
+    }
+
     public void testPrevNextSnippet() throws Exception {
         doRunTest((inputSink, out) -> {
             inputSink.write("void test1() {\nSystem.err.println(1);\n}\n");
             waitOutput(out, PROMPT);
             inputSink.write("void test2() {\nSystem.err.println(2);\n}\n");
             waitOutput(out, PROMPT);
-            inputSink.write(CTRL_UP);
-            waitOutput(out, "^void test2\\(\\) \\{");
-            inputSink.write(CTRL_UP);
-            waitOutput(out, "^" + clearOut("2() {") + "1\\(\\) \\{");
-            inputSink.write(CTRL_DOWN);
-            waitOutput(out, "^" + clearOut("1() {") + "2\\(\\) \\{");
-            inputSink.write(ENTER);
-            waitOutput(out, "^\n\u0006");
             inputSink.write(UP);
-            waitOutput(out, "^}");
+            waitOutput(out, "^void test2\\(\\) \\{\n" +
+                            CONTINUATION_PROMPT + "System.err.println\\(2\\);\n" +
+                            CONTINUATION_PROMPT + "\\}");
+            inputSink.write(UP);
+            waitOutput(out, "^\u001b\\[A");
+            inputSink.write(UP);
+            waitOutput(out, "^\u001b\\[A");
             inputSink.write(UP);
-            waitOutput(out, "^" + clearOut("}") + "System.err.println\\(2\\);");
-            inputSink.write(UP);
-            waitOutput(out, "^" + clearOut("System.err.println(2);") + "void test2\\(\\) \\{");
-            inputSink.write(UP);
-            waitOutput(out, "^" + BELL);
+            waitOutput(out, "^\u001b\\[8C1\n" +
+                            "\u001b\\[19C1\n\u001b\\[C");
             inputSink.write(DOWN);
-            waitOutput(out, "^" + clearOut("void test2() {") + "System.err.println\\(2\\);");
-            inputSink.write(DOWN);
-            waitOutput(out, "^" + clearOut("System.err.println(2);") + "}");
-            inputSink.write(DOWN);
-            waitOutput(out, "^" + clearOut("}"));
-            inputSink.write(DOWN);
-            waitOutput(out, "^" + BELL);
+            waitOutput(out, "^\u001B\\[2A\u001b\\[8C2\n" +
+                            "\u001b\\[19C2\n\u001b\\[C");
+            inputSink.write(UP);
+            waitOutput(out, "^\u001b\\[A");
+            for (int i = 0; i < 19; i++) inputSink.write("\033[C");
+            waitOutput(out, "C");
+            inputSink.write("\u0008\"Modified!\"\n");
+            waitOutput(out, PROMPT);
+            inputSink.write("test2()\n");
+            waitOutput(out, "\\u001B\\[\\?2004lModified!\n\\u001B\\[\\?2004h" + PROMPT);
         });
     }
-    //where:
-        private static final String CTRL_UP = "\033[1;5A";
-        private static final String CTRL_DOWN = "\033[1;5B";
-        private static final String UP = "\033[A";
-        private static final String DOWN = "\033[B";
-        private static final String ENTER = "\n";
 
 }
--- a/test/langtools/jdk/jshell/PasteAndMeasurementsUITest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/PasteAndMeasurementsUITest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -48,6 +48,10 @@
 @Test
 public class PasteAndMeasurementsUITest extends UITesting {
 
+    public PasteAndMeasurementsUITest() {
+        super(true);
+    }
+
     public void testPrevNextSnippet() throws Exception {
         Field cons = System.class.getDeclaredField("cons");
         cons.setAccessible(true);
@@ -55,17 +59,17 @@
         console.setAccessible(true);
         cons.set(null, console.newInstance());
         doRunTest((inputSink, out) -> {
-            inputSink.write("void test1() {\nSystem.err.println(1);\n}\n" + LOC +
-                            "void test2() {\nSystem.err.println(1);\n}\n" + LOC + LOC + LOC + LOC + LOC);
-            waitOutput(out,       "\u001b\\[6nvoid test1\\(\\) \\{\n" +
-                            "\u0006\u001b\\[6nSystem.err.println\\(1\\);\n" +
-                            "\u0006\u001b\\[6n\\}\n" +
-                            "\\|  created method test1\\(\\)\n" +
-                            PROMPT + "\u001b\\[6nvoid test2\\(\\) \\{\n" +
-                            "\u0006\u001b\\[6nSystem.err.println\\(1\\);\n" +
-                            "\u0006\u001b\\[6n\\}\n" +
-                            "\\|  created method test2\\(\\)\n" +
-                            PROMPT + "\u001b\\[6n");
+            inputSink.write("void test1() {\nSystem.err.println(1);\n}\n" + //LOC +
+                            "void test2() {\nSystem.err.println(1);\n}\n"/* + LOC + LOC + LOC + LOC + LOC*/);
+            waitOutput(out,       "void test1\\(\\)\u001B\\[2D\u001B\\[2C \\{\n" +
+                            CONTINUATION_PROMPT + "System.err.println\\(1\\)\u001B\\[3D\u001B\\[3C;\n" +
+                            CONTINUATION_PROMPT + "\\}\u001B\\[2A\u001B\\[12C\n\n\u001B\\[C\n" +
+                            "\u001B\\[\\?2004l\\|  created method test1\\(\\)\n" +
+                            "\u001B\\[\\?2004h" + PROMPT + "void test2\\(\\)\u001B\\[2D\u001B\\[2C \\{\n" +
+                            CONTINUATION_PROMPT + "System.err.println\\(1\\)\u001B\\[3D\u001B\\[3C;\n" +
+                            CONTINUATION_PROMPT + "\\}\u001B\\[2A\u001B\\[12C\n\n\u001B\\[C\n" +
+                            "\u001B\\[\\?2004l\\|  created method test2\\(\\)\n" +
+                            "\u001B\\[\\?2004h" + PROMPT);
         });
     }
         private static final String LOC = "\033[12;1R";
--- a/test/langtools/jdk/jshell/ReplToolTesting.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ReplToolTesting.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -115,7 +115,7 @@
     private Map<String, ClassInfo> classes;
     private Map<String, ImportInfo> imports;
     private boolean isDefaultStartUp = true;
-    private Map<String, String> prefsMap;
+    protected Map<String, String> prefsMap;
     private Map<String, String> envvars;
 
     public interface ReplTest {
@@ -260,6 +260,7 @@
     public void setUp() {
         prefsMap = new HashMap<>();
         envvars = new HashMap<>();
+        System.setProperty("jshell.test.allow.incomplete.inputs", "true");
     }
 
     protected void setEnvVar(String name, String value) {
@@ -491,7 +492,11 @@
             if (userinput != null) {
                 setUserInput(userinput);
             }
-            setCommandInput(cmd + "\n");
+            if (cmd.endsWith("\u0003")) {
+                setCommandInput(cmd);
+            } else {
+                setCommandInput(cmd + "\n");
+            }
         } else {
             assertOutput(getCommandOutput().trim(), out==null? out : out.trim(), "command output: " + cmd);
             assertOutput(getCommandErrorOutput(), err, "command error: " + cmd);
@@ -501,7 +506,12 @@
     }
 
     public Consumer<String> assertStartsWith(String prefix) {
-        return (output) -> assertTrue(output.trim().startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
+        return (output) -> {
+                            if (!output.trim().startsWith(prefix)) {
+                                int i = 0;
+        }
+            assertTrue(output.trim().startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
+        };
     }
 
     public void assertOutput(String got, String expected, String display) {
@@ -511,8 +521,9 @@
     }
 
     private String normalizeLineEndings(String text) {
-        return text.replace(System.getProperty("line.separator"), "\n");
+        return ANSI_CODE_PATTERN.matcher(text.replace(System.getProperty("line.separator"), "\n")).replaceAll("");
     }
+        private static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[\060-\077]*[\040-\057]*[\100-\176]");
 
     public static abstract class MemberInfo {
         public final String source;
--- a/test/langtools/jdk/jshell/StartOptionTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/StartOptionTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -44,6 +44,8 @@
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -90,6 +92,8 @@
         byte[] bytes = str.toByteArray();
         str.reset();
         String out = new String(bytes, StandardCharsets.UTF_8);
+        out = stripAnsi(out);
+        out = out.replaceAll("[\r\n]+", "\n");
         if (checkOut != null) {
             checkOut.accept(out);
         } else {
@@ -363,4 +367,11 @@
         usererr = null;
         cmdInStream = null;
     }
+
+    private static String stripAnsi(String str) {
+        if (str == null) return "";
+        return ANSI_CODE_PATTERN.matcher(str).replaceAll("");
+    }
+
+    public static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[\060-\077]*[\040-\057]*[\100-\176]");
 }
--- a/test/langtools/jdk/jshell/ToolLocalSimpleTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ToolLocalSimpleTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -30,7 +30,7 @@
  *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @build KullaTesting TestingInputStream ToolSimpleTest
- * @run testng ToolLocalSimpleTest
+ * @run testng/othervm ToolLocalSimpleTest
  */
 
 import java.util.Locale;
--- a/test/langtools/jdk/jshell/ToolMultilineSnippetHistoryTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ToolMultilineSnippetHistoryTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -45,13 +45,15 @@
     public void testUpArrow() throws Exception {
         doRunTest((inputSink, out) -> {
             inputSink.write("int x=\n44\n");
-            waitOutput(out, "x ==> 44\n\u0005");
+            waitOutput(out, "\u001B\\[\\?2004lx ==> 44\n\u001B\\[\\?2004h" + PROMPT);
             inputSink.write("/!\n");
-            waitOutput(out, "int x=\n44;\nx ==> 44\n\u0005");
-            inputSink.write("\020");
-            waitOutput(out,   "44;");
-            inputSink.write("\020");
-            waitOutput(out,  "int x=");
+            waitOutput(out, "\u001B\\[\\?2004lint x=\n44;\nx ==> 44\n\u001B\\[\\?2004h" + PROMPT);
+            inputSink.write(UP);
+            waitOutput(out,  "int x=\n" +
+                            CONTINUATION_PROMPT + "44;");
+            inputSink.write(UP);
+            inputSink.write(UP);
+            waitOutput(out,  "\u001B\\[A\n\u001B\\[2C\u001B\\[K");
         });
     }
 
--- a/test/langtools/jdk/jshell/ToolSimpleTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ToolSimpleTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -30,7 +30,7 @@
  *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @build KullaTesting TestingInputStream
- * @run testng ToolSimpleTest
+ * @run testng/othervm ToolSimpleTest
  */
 
 import java.util.ArrayList;
--- a/test/langtools/jdk/jshell/ToolTabCommandTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ToolTabCommandTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -41,6 +41,10 @@
 @Test
 public class ToolTabCommandTest extends UITesting {
 
+    public ToolTabCommandTest() {
+        super(true);
+    }
+
     public void testCommand() throws Exception {
         // set terminal height so that help output won't hit page breaks
         System.setProperty("test.terminal.height", "1000000");
@@ -84,7 +88,7 @@
             waitOutput(out, resource("help.edit"));
 
             inputSink.write(INTERRUPT + "/env " + TAB);
-            waitOutput(out, PROMPT + "/env -\n" +
+            waitOutput(out, PROMPT + "/env \n" +
                             "-add-exports    -add-modules    -class-path     -module-path    \n" +
                             "\n" +
                             resource("jshell.console.see.synopsis") +
@@ -118,7 +122,7 @@
                             REDRAW_PROMPT + "/exit ");
             inputSink.write(INTERRUPT);
             inputSink.write("int zebraStripes = 11\n");
-            waitOutput(out, "zebraStripes ==> 11\n\u0005");
+            waitOutput(out, "\\u001B\\[\\?2004lzebraStripes ==> 11\n\\u001B\\[\\?2004h" + PROMPT);
             inputSink.write("/exit zeb" + TAB);
             waitOutput(out, "braStr.*es");
             inputSink.write(INTERRUPT + "/doesnotexist" + TAB);
--- a/test/langtools/jdk/jshell/ToolTabSnippetTest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/ToolTabSnippetTest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -53,13 +53,17 @@
 @Test
 public class ToolTabSnippetTest extends UITesting {
 
+    public ToolTabSnippetTest() {
+        super(true);
+    }
+
     public void testExpression() throws Exception {
         Path classes = prepareZip();
         doRunTest((inputSink, out) -> {
             inputSink.write("/env -class-path " + classes.toString() + "\n");
-            waitOutput(out, resource("jshell.msg.set.restore") + "\n\u0005");
+            waitOutput(out, resource("jshell.msg.set.restore") + "\n\\u001B\\[\\?2004h" + PROMPT);
             inputSink.write("import jshelltest.*;\n");
-            waitOutput(out, "\n\u0005");
+            waitOutput(out, "\n\\u001B\\[\\?2004l\\u001B\\[\\?2004h" + PROMPT);
 
             //-> <tab>
             inputSink.write(TAB);
@@ -70,7 +74,7 @@
 
             //new JShellTes<tab>
             inputSink.write("new JShellTes" + TAB);
-            waitOutput(out, "t\nJShellTest\\(      JShellTestAux\\(   " +
+            waitOutput(out, "\nJShellTest\\(      JShellTestAux\\(   " +
                             REDRAW_PROMPT + "new JShellTest");
 
             //new JShellTest<tab>
--- a/test/langtools/jdk/jshell/UITesting.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/jdk/jshell/UITesting.java	Wed Dec 12 08:38:45 2018 -0500
@@ -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
@@ -44,8 +44,11 @@
     protected static final String TAB = "\011";
     protected static final String INTERRUPT = "\u0003";
     protected static final String BELL = "\u0007";
-    protected static final String PROMPT = "\u0005";
-    protected static final String REDRAW_PROMPT = "\n\r" + PROMPT;
+    protected static final String PROMPT = " \u0005";
+    protected static final String CONTINUATION_PROMPT = " \u0006";
+    protected static final String REDRAW_PROMPT = "\n\r?" + PROMPT;
+    protected static final String UP = "\033[A";
+    protected static final String DOWN = "\033[B";
     private final boolean laxLineEndings;
 
     public UITesting() {
@@ -141,11 +144,11 @@
     // Return true if expected is found, false if secondary is found,
     // otherwise, time out with an IllegalStateException
     protected boolean waitOutput(StringBuilder out, String expected, String secondary) {
-        expected = expected.replaceAll("\n", laxLineEndings ? "\r?\n" : System.getProperty("line.separator"));
+        expected = expected.replaceAll("\n", laxLineEndings ? "\r*\n" : System.getProperty("line.separator"));
         Pattern expectedPattern = Pattern.compile(expected, Pattern.DOTALL);
         Pattern secondaryPattern = null;
         if (secondary != null) {
-            secondary = secondary.replaceAll("\n", laxLineEndings ? "\r?\n" : System.getProperty("line.separator"));
+            secondary = secondary.replaceAll("\n", laxLineEndings ? "\r*\n" : System.getProperty("line.separator"));
             secondaryPattern = Pattern.compile(secondary, Pattern.DOTALL);
         }
         synchronized (out) {
@@ -222,7 +225,12 @@
     }
 
     protected String resource(String key) {
-        return Pattern.quote(getResource(key));
+        return patternQuote(getResource(key));
+    }
+
+    protected String patternQuote(String str) {
+        //from JDK-6507804:
+        return str.replaceAll("([\\\\\\[\\].^$?*+{}()|])", "\\\\$1");
     }
 
     protected String getMessage(String key, Object... args) {
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchBugs.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchBugs.java	Wed Dec 12 08:38:45 2018 -0500
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8206986 8214529
+ * @bug 8206986 8214114 8214529
  * @summary Verify various corner cases with nested switch expressions.
  * @compile --enable-preview -source 12 ExpressionSwitchBugs.java
  * @run main/othervm --enable-preview ExpressionSwitchBugs
@@ -33,6 +33,7 @@
     public static void main(String... args) {
         new ExpressionSwitchBugs().testNested();
         new ExpressionSwitchBugs().testAnonymousClasses();
+        new ExpressionSwitchBugs().testFields();
     }
 
     private void testNested() {
@@ -84,6 +85,33 @@
         }
     }
 
+    private void testFields() {
+        check(3, field);
+        check(3, ExpressionSwitchBugs.staticField);
+    }
+
+    private final int value = 2;
+    private final int field = id(switch(value) {
+        case 0 -> -1;
+        case 2 -> {
+            int temp = 0;
+            temp += 3;
+            break temp;
+        }
+        default -> throw new IllegalStateException();
+    });
+
+    private static final int staticValue = 2;
+    private static final int staticField = new ExpressionSwitchBugs().id(switch(staticValue) {
+        case 0 -> -1;
+        case 2 -> {
+            int temp = 0;
+            temp += 3;
+            break temp;
+        }
+        default -> throw new IllegalStateException();
+    });
+
     private int id(int i) {
         return i;
     }
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchEmbedding.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchEmbedding.java	Wed Dec 12 08:38:45 2018 -0500
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8214031
+ * @bug 8214031 8214114
  * @summary Verify switch expressions embedded in various statements work properly.
  * @compile --enable-preview -source 12 ExpressionSwitchEmbedding.java
  * @run main/othervm --enable-preview ExpressionSwitchEmbedding
@@ -66,6 +66,50 @@
         {
             int i = 6;
             int o = 0;
+            while (switch (i) {
+                case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
+                case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
+                case 3, 4:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        if (i == 2 || i == 4) {
+                            try {
+                                break switch (i) {
+                                    case 2 -> throw new ResultException(true);
+                                    case 4 -> false;
+                                    default -> throw new IllegalStateException();
+                                };
+                            } catch (ResultException ex) {
+                                break ex.result;
+                            }
+                        } else {
+                            break true;
+                        }
+                    }
+                default:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        break switch (i) {
+                            case -1 -> false;
+                            case 3 -> true;
+                            default -> true;
+                        };
+                    }
+                    throw new AssertionError();
+            }) {
+                o++;
+            }
+            if (o != 6 && i >= 0) {
+                throw new IllegalStateException();
+            }
+        }
+        {
+            int i = 6;
+            int o = 0;
             if (switch (i) {
                 case 1: i = 0; break true;
                 case 2: i = 1; break true;
@@ -92,6 +136,50 @@
             }
         }
         {
+            int i = 6;
+            int o = 0;
+            if (switch (i) {
+                case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
+                case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
+                case 3, 4:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        if (i == 2 || i == 4) {
+                            try {
+                                break switch (i) {
+                                    case 2 -> throw new ResultException(true);
+                                    case 4 -> false;
+                                    default -> throw new IllegalStateException();
+                                };
+                            } catch (ResultException ex) {
+                                break ex.result;
+                            }
+                        } else {
+                            break true;
+                        }
+                    }
+                default:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        break switch (i) {
+                            case -1 -> false;
+                            case 3 -> true;
+                            default -> true;
+                        };
+                    }
+                    throw new AssertionError();
+            }) {
+                o++;
+            }
+            if (o != 1 && i != 5) {
+                throw new IllegalStateException();
+            }
+        }
+        {
             int o = 0;
             for (int i = 6; (switch (i) {
                 case 1: i = 0; break true;
@@ -119,6 +207,49 @@
             }
         }
         {
+            int o = 0;
+            for (int i = 6; (switch (i) {
+                case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
+                case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
+                case 3, 4:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        if (i == 2 || i == 4) {
+                            try {
+                                break switch (i) {
+                                    case 2 -> throw new ResultException(true);
+                                    case 4 -> false;
+                                    default -> throw new IllegalStateException();
+                                };
+                            } catch (ResultException ex) {
+                                break ex.result;
+                            }
+                        } else {
+                            break true;
+                        }
+                    }
+                default:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        break switch (i) {
+                            case -1 -> false;
+                            case 3 -> true;
+                            default -> true;
+                        };
+                    }
+                    throw new AssertionError();
+            }); ) {
+                o++;
+            }
+            if (o != 6) {
+                throw new IllegalStateException();
+            }
+        }
+        {
             int i = 6;
             int o = 0;
             do {
@@ -146,6 +277,60 @@
                 throw new IllegalStateException();
             }
         }
+        {
+            int i = 6;
+            int o = 0;
+            do {
+                o++;
+            } while (switch (i) {
+                case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
+                case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
+                case 3, 4:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        if (i == 2 || i == 4) {
+                            try {
+                                break switch (i) {
+                                    case 2 -> throw new ResultException(true);
+                                    case 4 -> false;
+                                    default -> throw new IllegalStateException();
+                                };
+                            } catch (ResultException ex) {
+                                break ex.result;
+                            }
+                        } else {
+                            break true;
+                        }
+                    }
+                default:
+                    try {
+                        new ExpressionSwitchEmbedding().throwException();
+                    } catch (Throwable t) {
+                        i--;
+                        break switch (i) {
+                            case -1 -> false;
+                            case 3 -> true;
+                            default -> true;
+                        };
+                    }
+                    throw new AssertionError();
+            });
+            if (o != 6 && i >= 0) {
+                throw new IllegalStateException();
+            }
+        }
     }
 
+    private void throwException() {
+        throw new RuntimeException();
+    }
+
+    private static final class ResultException extends RuntimeException {
+        public final boolean result;
+        public ResultException(boolean result) {
+            this.result = result;
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/TryCatch.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,423 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8214114
+ * @summary Verify try-catch inside a switch expression works properly.
+ * @compile --enable-preview -source 12 TryCatch.java
+ * @run main/othervm --enable-preview TryCatch
+ */
+public class TryCatch {
+    public static void main(String[] args) {
+        {
+            int val = 3;
+            for (int p : new int[] {0, 1, 2}) {
+                int res = 1 + new TryCatch().id(switch(p) {
+                    case 0 -> switch (p + 1) {
+                        case 1:
+                            try {
+                                new TryCatch().throwException();
+                                break -1;
+                            } catch(Throwable ex) {
+                                break val;
+                            }
+                        default: break -1;
+                    };
+                    case 1 -> {
+                        try {
+                            break new TryCatch().id(switch (p + 1) {
+                                case 2:
+                                    try {
+                                        new TryCatch().throwException();
+                                        break -1;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break -1;
+                            });
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break -1;
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                } - 1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+        {
+            int val = 3;
+            for (int p : new int[] {0, 1, 2}) {
+                int x;
+                int res = new TryCatch().id(val == 3 && switch(p) {
+                    case 0 -> switch (p + 1) {
+                        case 1:
+                            try {
+                                new TryCatch().throwException();
+                                break false;
+                            } catch(Throwable ex) {
+                                break true;
+                            }
+                        default: break false;
+                    };
+                    case 1 -> {
+                        try {
+                            break new TryCatch().id(switch (p + 1) {
+                                case 2:
+                                    try {
+                                        new TryCatch().throwException();
+                                        break false;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break false;
+                            });
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break false;
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                } && (x = 1) == 1 && x == 1 ? val : -1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+        {
+            int val = 3;
+            for (E e : new E[] {E.A, E.B, E.C}) {
+                int res = 1 + new TryCatch().id(switch(e) {
+                    case A -> switch (e.next()) {
+                        case B:
+                            try {
+                                new TryCatch().throwException();
+                                break -1;
+                            } catch(Throwable ex) {
+                                break val;
+                            }
+                        default: break -1;
+                    };
+                    case B -> {
+                        try {
+                            break new TryCatch().id(switch (e.next()) {
+                                case C:
+                                    try {
+                                        new TryCatch().throwException();
+                                        break -1;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break -1;
+                            });
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break -1;
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                } - 1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+        {
+            int val = 3;
+            for (E e : new E[] {E.A, E.B, E.C}) {
+                int x;
+                int res = new TryCatch().id(val == 3 && switch(e) {
+                    case A -> switch (e.next()) {
+                        case B:
+                            try {
+                                new TryCatch().throwException();
+                                break false;
+                            } catch(Throwable ex) {
+                                break true;
+                            }
+                        default: break false;
+                    };
+                    case B -> {
+                        try {
+                            break new TryCatch().id(switch (e.next()) {
+                                case C:
+                                    try {
+                                        new TryCatch().throwException();
+                                        break false;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break false;
+                            });
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break false;
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                } && (x = 1) == 1 && x == 1 ? val : -1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+        {
+            int val = 3;
+            for (String s : new String[] {"", "a", "b"}) {
+                int res = 1 + new TryCatch().id(switch(s) {
+                    case "" -> switch (s + "c") {
+                        case "c":
+                            try {
+                                new TryCatch().throwException();
+                                break -1;
+                            } catch(Throwable ex) {
+                                break val;
+                            }
+                        default: break -1;
+                    };
+                    case "a" -> {
+                        try {
+                            break new TryCatch().id(switch (s + "c") {
+                                case "ac":
+                                    try {
+                                        new TryCatch().throwException();
+                                        break -1;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break -1;
+                            });
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break -1;
+                        } catch(Throwable ex) {
+                            break val;
+                        }
+                    }
+                } - 1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+        {
+            int val = 3;
+            for (String s : new String[] {"", "a", "b"}) {
+                int x;
+                int res = new TryCatch().id(val == 3 && switch(s) {
+                    case "" -> switch (s + "c") {
+                        case "c":
+                            try {
+                                new TryCatch().throwException();
+                                break false;
+                            } catch(Throwable ex) {
+                                break true;
+                            }
+                        default: break false;
+                    };
+                    case "a" -> {
+                        try {
+                            break new TryCatch().id(switch (s + "c") {
+                                case "ac":
+                                    try {
+                                        new TryCatch().throwException();
+                                        break false;
+                                    } catch(Throwable ex) {
+                                        throw ex;
+                                    }
+                                default: break false;
+                            });
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                    default -> {
+                        try {
+                            new TryCatch().throwException();
+                            break false;
+                        } catch(Throwable ex) {
+                            break true;
+                        }
+                    }
+                } && (x = 1) == 1 && x == 1 ? val : -1);
+                if (res != 3) {
+                    throw new AssertionError("Unexpected result: " + res);
+                }
+            }
+        }
+
+        {
+            int res = new FieldHolder().intTest;
+
+            if (res != 3) {
+                throw new AssertionError("Unexpected result: " + res);
+            }
+        }
+        {
+            int res = FieldHolder.intStaticTest;
+
+            if (res != 3) {
+                throw new AssertionError("Unexpected result: " + res);
+            }
+        }
+        {
+            boolean res = new FieldHolder().booleanTest;
+
+            if (!res) {
+                throw new AssertionError("Unexpected result: " + res);
+            }
+        }
+        {
+            boolean res = FieldHolder.booleanStaticTest;
+
+            if (!res) {
+                throw new AssertionError("Unexpected result: " + res);
+            }
+        }
+    }
+
+    static class FieldHolder {
+        private final int intTest = switch (0) {
+            case -1: break -1;
+            default:
+                try {
+                    break new TryCatch().id(switch (2) {
+                        case 2:
+                            try {
+                                new TryCatch().throwException();
+                                break -1;
+                            } catch(Throwable ex) {
+                                throw ex;
+                            }
+                        default: break -1;
+                    });
+                } catch(Throwable ex) {
+                    break 3;
+                }
+        };
+        private static final int intStaticTest = switch (0) {
+            case -1: break -1;
+            default:
+                try {
+                    break new TryCatch().id(switch (2) {
+                        case 2:
+                            try {
+                                new TryCatch().throwException();
+                                break -1;
+                            } catch(Throwable ex) {
+                                throw ex;
+                            }
+                        default: break -1;
+                    });
+                } catch(Throwable ex) {
+                    break 3;
+                }
+        };
+        private final boolean booleanTest = switch (0) {
+            case -1: break false;
+            default:
+                try {
+                    break new TryCatch().id(switch (2) {
+                        case 2:
+                            try {
+                                new TryCatch().throwException();
+                                break false;
+                            } catch(Throwable ex) {
+                                throw ex;
+                            }
+                        default: break false;
+                    });
+                } catch(Throwable ex) {
+                    break true;
+                }
+        };
+        private static final boolean booleanStaticTest = switch (0) {
+            case -1: break false;
+            default:
+                try {
+                    break new TryCatch().id(switch (2) {
+                        case 2:
+                            try {
+                                new TryCatch().throwException();
+                                break false;
+                            } catch(Throwable ex) {
+                                throw ex;
+                            }
+                        default: break false;
+                    });
+                } catch(Throwable ex) {
+                    break true;
+                }
+        };
+    }
+
+    private int id(int i) {
+        return i;
+    }
+
+    private boolean id(boolean b) {
+        return b;
+    }
+
+    private void throwException() {
+        throw new RuntimeException();
+    }
+    enum E {
+        A, B, C;
+        public E next() {
+            return values()[(ordinal() + 1) % values().length];
+        }
+    }
+}
--- a/test/langtools/tools/javadoc/api/basic/APITest.java	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/langtools/tools/javadoc/api/basic/APITest.java	Wed Dec 12 08:38:45 2018 -0500
@@ -212,19 +212,17 @@
             "jquery/jszip-utils/dist/jszip-utils.min.js",
             "jquery/jszip-utils/dist/jszip-utils-ie.js",
             "jquery/jszip-utils/dist/jszip-utils-ie.min.js",
-            "jquery/images/ui-bg_flat_0_aaaaaa_40x100.png",
+            "jquery/images/ui-bg_glass_65_dadada_1x400.png",
             "jquery/images/ui-icons_454545_256x240.png",
             "jquery/images/ui-bg_glass_95_fef1ec_1x400.png",
             "jquery/images/ui-bg_glass_75_dadada_1x400.png",
             "jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png",
             "jquery/images/ui-icons_888888_256x240.png",
             "jquery/images/ui-icons_2e83ff_256x240.png",
-            "jquery/images/ui-bg_glass_65_ffffff_1x400.png",
             "jquery/images/ui-icons_cd0a0a_256x240.png",
             "jquery/images/ui-bg_glass_55_fbf9ee_1x400.png",
             "jquery/images/ui-icons_222222_256x240.png",
             "jquery/images/ui-bg_glass_75_e6e6e6_1x400.png",
-            "jquery/images/ui-bg_flat_75_ffffff_40x100.png",
             "member-search-index.js",
             "member-search-index.zip",
             "overview-tree.html",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/security/SecurityUtils.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package jdk.test.lib.security;
+
+import java.io.File;
+import java.security.KeyStore;
+
+/**
+ * Common library for various security test helper functions.
+ */
+public final class SecurityUtils {
+
+    private static String getCacerts() {
+        String sep = File.separator;
+        return System.getProperty("java.home") + sep
+                + "lib" + sep + "security" + sep + "cacerts";
+    }
+
+    /**
+     * Returns the cacerts keystore with the configured CA certificates.
+     */
+    public static KeyStore getCacertsKeyStore() throws Exception {
+        File file = new File(getCacerts());
+        if (!file.exists()) {
+            return null;
+        }
+        return KeyStore.getInstance(file, (char[])null);
+    }
+
+    private SecurityUtils() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/java/lang/Characters.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.openjdk.bench.java.lang;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Thread)
+public class Characters {
+
+    @Param({"9", "48", "65", "97", "128", "170", "192", "223"})
+    private int codePoint;
+
+    @Benchmark
+    public boolean isDigit() {
+        return Character.isDigit(codePoint);
+    }
+
+    @Benchmark
+    public boolean isLowerCase() {
+        return Character.isLowerCase(codePoint);
+    }
+
+    @Benchmark
+    public boolean isUpperCase() {
+        return Character.isUpperCase(codePoint);
+    }
+
+    @Benchmark
+    public boolean isWhitespace() {
+        return Character.isWhitespace(codePoint);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,85 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidParameterSpecException;
+
+public class AESBench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"AES/ECB/NoPadding", "AES/ECB/PKCS5Padding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"})
+    private String algorithm;
+
+    @Param({"128"})
+    private int keyLength;
+
+    @Param({"" + 16 * 1024})
+    private int dataSize;
+
+    byte[][] data;
+    byte[][] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    int index = 0;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidParameterSpecException {
+        setupProvider();
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        SecretKeySpec ks = new SecretKeySpec(keystring, "AES");
+        encryptCipher = makeCipher(prov, algorithm);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+        decryptCipher = makeCipher(prov, algorithm);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] d = data[index];
+        index = (index +1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] e = encryptedData[index];
+        index = (index +1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,106 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidParameterSpecException;
+
+
+public class AESGCMBench extends CryptoBase {
+
+    @Param({"AES/GCM/NoPadding","AES/GCM/PKCS5Padding"})
+    private String algorithm;
+
+    @Param({"128"})
+    private int keyLength;
+
+    @Param({""+16*1024})
+    private int dataSize;
+
+    byte[] data;
+    byte[] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    SecretKeySpec ks;
+    GCMParameterSpec gcm_spec;
+    byte[] aad;
+    byte[] iv;
+
+    public static final int IV_BUFFER_SIZE = 32;
+    public static final int IV_MODULO = IV_BUFFER_SIZE - 16;
+    int iv_index = 0;
+
+    private int next_iv_index() {
+        int r = iv_index;
+        iv_index = (iv_index + 1) % IV_MODULO;
+        return r;
+    }
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidParameterSpecException {
+        setupProvider();
+        assert algorithm.split("/")[1].compareToIgnoreCase("GCM") == 0;
+
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        ks = new SecretKeySpec(keystring, "AES");
+        iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]);
+        gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
+        aad = fillSecureRandom(new byte[5]);
+        encryptCipher = makeCipher(prov, algorithm);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
+        encryptCipher.updateAAD(aad);
+        decryptCipher = makeCipher(prov, algorithm);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters().getParameterSpec(GCMParameterSpec.class));
+        decryptCipher.updateAAD(aad);
+        data = fillRandom(new byte[dataSize]);
+        encryptedData = encryptCipher.doFinal(data);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
+        gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
+        encryptCipher.updateAAD(aad);
+        return encryptCipher.doFinal(data);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException {
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters().getParameterSpec(GCMParameterSpec.class));
+        decryptCipher.updateAAD(aad);
+        return decryptCipher.doFinal(encryptedData);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/CryptoBase.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,102 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+
+@Fork(5)
+@Warmup(iterations = 3, time = 3)
+@Measurement(iterations = 8, time = 2)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@State(Scope.Thread)
+@BenchmarkMode(Mode.Throughput)
+public class CryptoBase {
+
+    @Param({""})
+    private String provider;
+
+    public Provider prov = null;
+
+    @Setup
+    public void setupProvider() {
+        if (provider != null && !provider.isEmpty()) {
+            prov = Security.getProvider(provider);
+            if (prov == null) {
+                throw new RuntimeException("Can't find prodiver \"" + provider + "\"");
+            }
+        }
+    }
+
+    public static Cipher makeCipher(Provider prov, String algorithm) throws NoSuchPaddingException, NoSuchAlgorithmException {
+        return (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+    }
+
+    public static byte[][] fillRandom(byte[][] data) {
+        Random rnd = new Random();
+        for (byte[] d : data) {
+            rnd.nextBytes(d);
+        }
+        return data;
+    }
+
+    public static byte[] fillRandom(byte[] data) {
+        Random rnd = new Random();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[] fillSecureRandom(byte[] data) {
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[][] fillEncrypted(byte[][] data, Cipher encryptCipher) throws BadPaddingException, IllegalBlockSizeException {
+        byte[][] encryptedData = new byte[data.length][];
+        for (int i = 0; i < encryptedData.length; i++) {
+            encryptedData[i] = encryptCipher.doFinal(data[i]);
+        }
+        return encryptedData;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/DESedeBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,86 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+
+public class DESedeBench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"DESede/ECB/NoPadding", "DESede/ECB/PKCS5Padding", "DESede/CBC/NoPadding","DESede/CBC/PKCS5Padding"})
+    private String algorithm;
+
+    @Param({"168"})
+    private int keyLength;
+
+    @Param({""+16*1024})
+    private int dataSize;
+
+    byte[][] data;
+    byte[][] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    int index = 0;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
+        setupProvider();
+        KeyGenerator kg = KeyGenerator.getInstance("DESede");
+        kg.init(keyLength);
+        Key key = kg.generateKey();
+        encryptCipher = makeCipher(prov, algorithm);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, key);
+        decryptCipher = makeCipher(prov, algorithm);
+        decryptCipher.init(Cipher.DECRYPT_MODE, key, encryptCipher.getParameters());
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] d = data[index];
+        index = (index +1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] e = encryptedData[index];
+        index = (index +1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/KeyPairGeneratorBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,75 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+
+public class KeyPairGeneratorBench extends CryptoBase {
+
+    private KeyPairGenerator generator;
+
+    @Param({"DSA", "DiffieHellman"})
+    private String algorithm;
+
+    @Param({"1024", "2048"})
+    private int keyLength;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException {
+        setupProvider();
+        generator = (prov == null) ? KeyPairGenerator.getInstance(algorithm) : KeyPairGenerator.getInstance(algorithm, prov);
+        generator.initialize(keyLength);
+    }
+
+    @Benchmark
+    public KeyPair generateKeyPair() {
+        return generator.generateKeyPair();
+    }
+
+    public static class RSA extends KeyPairGeneratorBench {
+
+        @Param({"RSA"})
+        private String algorithm;
+
+        @Param({"1024", "2048", "3072"})
+        private int keyLength;
+
+    }
+
+    public static class EC extends KeyPairGeneratorBench {
+
+        @Param({"EC"})
+        private String algorithm;
+
+        @Param({"160", "224", "256"})
+        private int keyLength;
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/MacBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+public class MacBench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"HmacMD5", "HmacSHA1", "HmacSHA256", "HmacSHA512"})
+    private String algorithm;
+
+    @Param({"128", "1024"})
+    int dataSize;
+
+    private byte[][] data;
+    private Mac mac;
+    int index = 0;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, InvalidKeyException {
+        setupProvider();
+        mac = (prov == null) ? Mac.getInstance(algorithm) : Mac.getInstance(algorithm, prov);
+        mac.init(KeyGenerator.getInstance(algorithm).generateKey());
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+    }
+
+    @Benchmark
+    public byte[] mac() throws NoSuchAlgorithmException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return mac.doFinal(d);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/MessageDigestBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MessageDigestBench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"MD5", "SHA", "SHA-256", "SHA-384", "SHA-512"})
+    private String algorithm;
+
+    /*
+     * Note: dataSize value shouldn't be small unless you want to evaluate MessageDigest.getInstance performance.
+     * Small value causes large impact of MessageDigest.getInstance including lock contention in multi-threaded
+     * execution.
+     */
+    @Param({""+1024*1024})
+    int dataSize;
+
+    private byte[][] data;
+    int index = 0;
+
+
+    @Setup
+    public void setup() {
+        setupProvider();
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+    }
+
+    @Benchmark
+    public byte[] digest() throws NoSuchAlgorithmException {
+        MessageDigest md = (prov == null) ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, prov);
+        byte[] d = data[index];
+        index = (index +1) % SET_SIZE;
+        return md.digest(d);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/RSABench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,104 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+
+public class RSABench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"RSA/ECB/NoPadding", "RSA/ECB/PKCS1Padding", "RSA/ECB/OAEPPadding"})
+    protected String algorithm;
+
+    @Param({"32"})
+    protected int dataSize;
+
+    @Param({"1024", "2048", "3072"})
+    protected int keyLength;
+
+
+    private byte[][] data;
+    private byte[][] encryptedData;
+
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    private int index = 0;
+
+    @Setup()
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        setupProvider();
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+        kpg.initialize(keyLength);
+        KeyPair keyPair = kpg.generateKeyPair();
+
+        encryptCipher = makeCipher(prov, algorithm);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
+
+        decryptCipher = makeCipher(prov, algorithm);
+        decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+        encryptedData = fillEncrypted(data, encryptCipher);
+
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] d = data[index];
+        index = (index +1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] e = encryptedData[index];
+        index = (index +1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+    public static class Extra extends RSABench {
+
+        @Param({"RSA/ECB/NoPadding", "RSA/ECB/PKCS1Padding"})
+        private String algorithm;
+
+        @Param({"214"})
+        private int dataSize;
+
+        @Param({"2048", "3072"})
+        private int keyLength;
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/SecureRandomBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,75 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+
+public class SecureRandomBench extends CryptoBase {
+
+    @Param({"NativePRNG", "SHA1PRNG"})
+    private String algorithm;
+
+    @Param({"64"})
+    int dataSize;
+
+    @Param({"true", "false"})
+    // if shared - use the single SecureRandom instance for all threads
+    // otherwise - each thread uses its own SecureRandom instance
+    boolean shared;
+
+    private byte[] bytes;
+    private SecureRandom rnd;
+
+    private static SecureRandom sharedRnd;
+
+    private static synchronized SecureRandom getSharedInstance(String algorithm, Provider prov) throws NoSuchAlgorithmException {
+        if (sharedRnd == null) {
+            sharedRnd = (prov == null) ? SecureRandom.getInstance(algorithm) : SecureRandom.getInstance(algorithm, prov);
+        }
+        return sharedRnd;
+    }
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException {
+        setupProvider();
+        bytes = new byte[dataSize];
+        if (shared) {
+            rnd = getSharedInstance(algorithm, prov);
+        } else {
+            rnd = (prov == null) ? SecureRandom.getInstance(algorithm) : SecureRandom.getInstance(algorithm, prov);
+        }
+    }
+
+    @Benchmark
+    public byte[] nextBytes() {
+        rnd.nextBytes(bytes);
+        return bytes;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/full/SignatureBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.full;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.util.Random;
+
+public class SignatureBench extends CryptoBase {
+
+    public static final int SET_SIZE = 128;
+
+    @Param({"SHA256withDSA"})
+    private String algorithm;
+
+    @Param({"1024", "16384"})
+    int dataSize;
+
+    @Param({"1024"})
+    private int keyLength;
+
+    private PrivateKey privateKey;
+    private PublicKey publicKey;
+    private byte[][] data;
+    private byte[][] signedData;
+    int index;
+
+
+    private String getKeyPairGeneratorName() {
+        String tail = algorithm.substring(algorithm.lastIndexOf("with") + 4);
+        return "ECDSA".equals(tail) ? "EC" : tail;
+    }
+
+    @Setup()
+    public void setup() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        setupProvider();
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(getKeyPairGeneratorName());
+        kpg.initialize(keyLength);
+        KeyPair keys = kpg.generateKeyPair();
+        this.privateKey = keys.getPrivate();
+        this.publicKey = keys.getPublic();
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        signedData = new byte[data.length][];
+        for (int i = 0; i < data.length; i++) {
+            signedData[i] = sign(data[i]);
+        }
+
+    }
+
+    public byte[] sign(byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature signature = (prov == null) ? Signature.getInstance(algorithm) : Signature.getInstance(algorithm, prov);
+        signature.initSign(privateKey);
+        signature.update(data);
+        return signature.sign();
+    }
+
+    @Benchmark
+    public byte[] sign() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return sign(d);
+    }
+
+    @Benchmark
+    public boolean verify() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature signature = (prov == null) ? Signature.getInstance(algorithm) : Signature.getInstance(algorithm, prov);
+        signature.initVerify(publicKey);
+        byte[] d = data[index];
+        byte[] s = signedData[index];
+        index = (index + 1) % SET_SIZE;
+        signature.update(d);
+        return signature.verify(s);
+    }
+
+    public static class RSA extends SignatureBench {
+
+        @Param({"MD5withRSA", "SHA256withRSA"})
+        private String algorithm;
+
+        @Param({"1024", "2048", "3072"})
+        private int keyLength;
+
+    }
+
+    public static class ECDSA extends SignatureBench {
+
+        @Param({"SHA256withECDSA"})
+        private String algorithm;
+
+        @Param({"160", "224", "256"})
+        private int keyLength;
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/AESBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,38 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public class AESBench extends org.openjdk.bench.javax.crypto.full.AESBench {
+
+    @Param({"AES/ECB/NoPadding", "AES/CBC/NoPadding" })
+    private String algorithm;
+
+    @Param({"128"})
+    private int keyLength;
+
+    @Param({"1024"})
+    private int dataSize;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/AESGCMBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,39 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public class AESGCMBench extends org.openjdk.bench.javax.crypto.full.AESGCMBench {
+
+
+    @Param({"AES/GCM/NoPadding"})
+    private String algorithm;
+
+    @Param({"128"})
+    private int keyLength;
+
+    @Param({"1024"})
+    private int dataSize;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/KeyPairGeneratorBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,35 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public class KeyPairGeneratorBench extends org.openjdk.bench.javax.crypto.full.KeyPairGeneratorBench {
+
+    @Param({"DSA", "RSA"})
+    private String algorithm;
+
+    @Param({"2048"})
+    private int keyLength;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/MessageDigestBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,32 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public class MessageDigestBench extends org.openjdk.bench.javax.crypto.full.MessageDigestBench {
+
+    @Param({"SHA1", "SHA-256"})
+    private String algorithm;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/RSABench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,38 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public class RSABench extends org.openjdk.bench.javax.crypto.full.RSABench {
+
+    @Param({"RSA/ECB/NoPadding"})
+    protected String algorithm;
+
+    @Param({"32"})
+    protected int dataSize;
+
+    @Param({"2048"})
+    protected int keyLength;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/SecureRandomBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,27 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+public class SecureRandomBench extends org.openjdk.bench.javax.crypto.full.SecureRandomBench {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/javax/crypto/small/SignatureBench.java	Wed Dec 12 08:38:45 2018 -0500
@@ -0,0 +1,55 @@
+/*
+ * 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
+ * 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.
+ */
+package org.openjdk.bench.javax.crypto.small;
+
+import org.openjdk.jmh.annotations.Param;
+
+public abstract class SignatureBench extends org.openjdk.bench.javax.crypto.full.SignatureBench {
+
+    public static class RSA extends SignatureBench {
+
+        @Param({"SHA256withRSA"})
+        private String algorithm;
+
+        @Param({"2048"})
+        private int keyLength;
+
+        @Param({"1024"})
+        int dataSize;
+
+    }
+
+    public static class DSA extends SignatureBench {
+
+        @Param({"SHA256withDSA"})
+        private String algorithm;
+
+        @Param({"1024"})
+        int dataSize;
+
+        @Param({"1024"})
+        private int keyLength;
+
+    }
+
+}
--- a/test/nashorn/script/nosecurity/JDK-8055034.js.EXPECTED	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/nashorn/script/nosecurity/JDK-8055034.js.EXPECTED	Wed Dec 12 08:38:45 2018 -0500
@@ -1,6 +1,3 @@
-jjs> var x = Object.create(null);
-jjs> x;
-jjs> print('PASSED');
-PASSED
+jjs> var x = Object.create(null)jjs> jjs> print('PASSED')PASSED
 jjs> exit(0)
 exit code = 0
--- a/test/nashorn/script/nosecurity/JDK-8130127.js.EXPECTED	Wed Dec 12 08:27:16 2018 -0500
+++ b/test/nashorn/script/nosecurity/JDK-8130127.js.EXPECTED	Wed Dec 12 08:38:45 2018 -0500
@@ -2,6 +2,5 @@
 
 
 
-jjs> print('hello')
-hello
+jjs> print('hello')hello
 jjs>